Commit 1fc14993 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here's the big char/misc driver patchset for 4.1-rc1.

  Lots of different driver subsystem updates here, nothing major, full
  details are in the shortlog.

  All of this has been in linux-next for a while"

* tag 'char-misc-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (133 commits)
  mei: trace: remove unused TRACE_SYSTEM_STRING
  DTS: ARM: OMAP3-N900: Add lis3lv02d support
  Documentation: DT: lis302: update wakeup binding
  lis3lv02d: DT: add wakeup unit 2 and wakeup threshold
  lis3lv02d: DT: use s32 to support negative values
  Drivers: hv: hv_balloon: correctly handle num_pages>INT_MAX case
  Drivers: hv: hv_balloon: correctly handle val.freeram<num_pages case
  mei: replace check for connection instead of transitioning
  mei: use mei_cl_is_connected consistently
  mei: fix mei_poll operation
  hv_vmbus: Add gradually increased delay for retries in vmbus_post_msg()
  Drivers: hv: hv_balloon: survive ballooning request with num_pages=0
  Drivers: hv: hv_balloon: eliminate jumps in piecewiese linear floor function
  Drivers: hv: hv_balloon: do not online pages in offline blocks
  hv: remove the per-channel workqueue
  hv: don't schedule new works in vmbus_onoffer()/vmbus_onoffer_rescind()
  hv: run non-blocking message handlers in the dispatch tasklet
  coresight: moving to new "hwtracing" directory
  coresight-tmc: Adding a status interface to sysfs
  coresight: remove the unnecessary configuration coresight-default-sink
  ...
parents 41d5e08e ea5505fa
......@@ -61,7 +61,6 @@ Example:
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0x20010000 0 0x1000>;
coresight-default-sink;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
......
USB GPIO Extcon device
This is a virtual device used to generate USB cable states from the USB ID pin
connected to a GPIO pin.
Required properties:
- compatible: Should be "linux,extcon-usb-gpio"
- id-gpio: gpio for USB ID pin. See gpio binding.
Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
extcon_usb1 {
compatible = "linux,extcon-usb-gpio";
id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
}
&omap_dwc3_1 {
extcon = <&extcon_usb1>;
};
* Ingenic JZ4780 NAND/external memory controller (NEMC)
This file documents the device tree bindings for the NEMC external memory
controller in Ingenic JZ4780
Required properties:
- compatible: Should be set to one of:
"ingenic,jz4780-nemc" (JZ4780)
- reg: Should specify the NEMC controller registers location and length.
- clocks: Clock for the NEMC controller.
- #address-cells: Must be set to 2.
- #size-cells: Must be set to 1.
- ranges: A set of ranges for each bank describing the physical memory layout.
Each should specify the following 4 integer values:
<cs number> 0 <physical address of mapping> <size of mapping>
Each child of the NEMC node describes a device connected to the NEMC.
Required child node properties:
- reg: Should contain at least one register specifier, given in the following
format:
<cs number> <offset> <size>
Multiple registers can be specified across multiple banks. This is needed,
for example, for packaged NAND devices with multiple dies. Such devices
should be grouped into a single node.
Optional child node properties:
- ingenic,nemc-bus-width: Specifies the bus width in bits. Defaults to 8 bits.
- ingenic,nemc-tAS: Address setup time in nanoseconds.
- ingenic,nemc-tAH: Address hold time in nanoseconds.
- ingenic,nemc-tBP: Burst pitch time in nanoseconds.
- ingenic,nemc-tAW: Access wait time in nanoseconds.
- ingenic,nemc-tSTRV: Static memory recovery time in nanoseconds.
If a child node references multiple banks in its "reg" property, the same value
for all optional parameters will be configured for all banks. If any optional
parameters are omitted, they will be left unchanged from whatever they are
configured to when the NEMC device is probed (which may be the reset value as
given in the hardware reference manual, or a value configured by the boot
loader).
Example (NEMC node with a NAND child device attached at CS1):
nemc: nemc@13410000 {
compatible = "ingenic,jz4780-nemc";
reg = <0x13410000 0x10000>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <1 0 0x1b000000 0x1000000
2 0 0x1a000000 0x1000000
3 0 0x19000000 0x1000000
4 0 0x18000000 0x1000000
5 0 0x17000000 0x1000000
6 0 0x16000000 0x1000000>;
clocks = <&cgu JZ4780_CLK_NEMC>;
nand: nand@1 {
compatible = "ingenic,jz4780-nand";
reg = <1 0 0x1000000>;
ingenic,nemc-tAS = <10>;
ingenic,nemc-tAH = <5>;
ingenic,nemc-tBP = <10>;
ingenic,nemc-tAW = <15>;
ingenic,nemc-tSTRV = <100>;
...
};
};
......@@ -46,11 +46,18 @@ Optional properties for all bus drivers:
interrupt 2
- st,wakeup-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for
upper/lower limit
- st,wakeup-threshold: set wakeup threshold
- st,wakeup2-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for
upper/lower limit for second wakeup
engine.
- st,wakeup2-threshold: set wakeup threshold for second wakeup
engine.
- st,highpass-cutoff-hz=: 1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of
highpass cut-off frequency
- st,hipass{1,2}-disable: disable highpass 1/2.
- st,default-rate=: set the default rate
- st,axis-{x,y,z}=: set the axis to map to the three coordinates
- st,axis-{x,y,z}=: set the axis to map to the three coordinates.
Negative values can be used for inverted axis.
- st,{min,max}-limit-{x,y,z} set the min/max limits for x/y/z axis
(used by self-test)
......
Qualcomm SPMI Controller (PMIC Arbiter)
The SPMI PMIC Arbiter is found on the Snapdragon 800 Series. It is an SPMI
The SPMI PMIC Arbiter is found on Snapdragon chipsets. It is an SPMI
controller with wrapping arbitration logic to allow for multiple on-chip
devices to control a single SPMI master.
......@@ -19,6 +19,10 @@ Required properties:
"core" - core registers
"intr" - interrupt controller registers
"cnfg" - configuration registers
Registers used only for V2 PMIC Arbiter:
"chnls" - tx-channel per virtual slave registers.
"obsrvr" - rx-channel (called observer) per virtual slave registers.
- reg : address + size pairs describing the PMIC arb register sets; order must
correspond with the order of entries in reg-names
- #address-cells : must be set to 2
......
......@@ -276,6 +276,7 @@ IOMAP
devm_ioport_unmap()
devm_ioremap()
devm_ioremap_nocache()
devm_ioremap_wc()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
devm_iounmap()
pcim_iomap()
......
......@@ -14,7 +14,7 @@ document is concerned with the latter.
HW assisted tracing is becoming increasingly useful when dealing with systems
that have many SoCs and other components like GPU and DMA engines. ARM has
developed a HW assisted tracing solution by means of different components, each
being added to a design at systhesis time to cater to specific tracing needs.
being added to a design at synthesis time to cater to specific tracing needs.
Compoments are generally categorised as source, link and sinks and are
(usually) discovered using the AMBA bus.
......
......@@ -958,7 +958,7 @@ ARM/CORESIGHT FRAMEWORK AND DRIVERS
M: Mathieu Poirier <mathieu.poirier@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/coresight/*
F: drivers/hwtracing/coresight/*
F: Documentation/trace/coresight.txt
F: Documentation/devicetree/bindings/arm/coresight.txt
F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
......@@ -1828,7 +1828,7 @@ S: Supported
F: drivers/spi/spi-atmel.*
ATMEL SSC DRIVER
M: Bo Shen <voice.shen@atmel.com>
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
F: drivers/misc/atmel-ssc.c
......
......@@ -1610,59 +1610,6 @@ config DEBUG_SET_MODULE_RONX
against certain classes of kernel exploits.
If in doubt, say "N".
menuconfig CORESIGHT
bool "CoreSight Tracing Support"
select ARM_AMBA
help
This framework provides a kernel interface for the CoreSight debug
and trace drivers to register themselves with. It's intended to build
a topological view of the CoreSight components based on a DT
specification and configure the right serie of components when a
trace source gets enabled.
if CORESIGHT
config CORESIGHT_LINKS_AND_SINKS
bool "CoreSight Link and Sink drivers"
help
This enables support for CoreSight link and sink drivers that are
responsible for transporting and collecting the trace data
respectively. Link and sinks are dynamically aggregated with a trace
entity at run time to form a complete trace path.
config CORESIGHT_LINK_AND_SINK_TMC
bool "Coresight generic TMC driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Memory Controller driver. Depending
on its configuration the device can act as a link (embedded trace router
- ETR) or sink (embedded trace FIFO). The driver complies with the
generic implementation of the component without special enhancement or
added features.
config CORESIGHT_SINK_TPIU
bool "Coresight generic TPIU driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Port Interface Unit driver, responsible
for bridging the gap between the on-chip coresight components and a trace
port collection engine, typically connected to an external host for use
case capturing more traces than the on-board coresight memory can handle.
config CORESIGHT_SINK_ETBV10
bool "Coresight ETBv1.0 driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Embedded Trace Buffer version 1.0 driver
that complies with the generic implementation of the component without
special enhancement or added features.
source "drivers/hwtracing/coresight/Kconfig"
config CORESIGHT_SOURCE_ETM3X
bool "CoreSight Embedded Trace Macrocell 3.x driver"
select CORESIGHT_LINKS_AND_SINKS
help
This driver provides support for processor ETM3.x and PTM1.x modules,
which allows tracing the instructions that a processor is executing
This is primarily useful for instruction level tracing. Depending
the ETM version data tracing may also be available.
endif
endmenu
......@@ -275,7 +275,6 @@ etb@0,e3c42000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0xe3c42000 0 0x1000>;
coresight-default-sink;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
......
......@@ -150,7 +150,6 @@ etb@5401b000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
coresight-default-sink;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
......
......@@ -145,7 +145,6 @@ etb@540000000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
coresight-default-sink;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
......
......@@ -609,6 +609,58 @@ &i2c3 {
pinctrl-0 = <&i2c3_pins>;
clock-frequency = <400000>;
lis302dl: lis3lv02d@1d {
compatible = "st,lis3lv02d";
reg = <0x1d>;
Vdd-supply = <&vaux1>;
Vdd_IO-supply = <&vio>;
interrupt-parent = <&gpio6>;
interrupts = <21 20>; /* 181 and 180 */
/* click flags */
st,click-single-x;
st,click-single-y;
st,click-single-z;
/* Limits are 0.5g * value */
st,click-threshold-x = <8>;
st,click-threshold-y = <8>;
st,click-threshold-z = <10>;
/* Click must be longer than time limit */
st,click-time-limit = <9>;
/* Kind of debounce filter */
st,click-latency = <50>;
/* Interrupt line 2 for click detection */
st,irq2-click;
st,wakeup-x-hi;
st,wakeup-y-hi;
st,wakeup-threshold = <(800/18)>; /* millig-value / 18 to get HW values */
st,wakeup2-z-hi;
st,wakeup2-threshold = <(900/18)>; /* millig-value / 18 to get HW values */
st,hipass1-disable;
st,hipass2-disable;
st,axis-x = <1>; /* LIS3_DEV_X */
st,axis-y = <(-2)>; /* LIS3_INV_DEV_Y */
st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */
st,min-limit-x = <(-32)>;
st,min-limit-y = <3>;
st,min-limit-z = <3>;
st,max-limit-x = <(-3)>;
st,max-limit-y = <32>;
st,max-limit-z = <32>;
};
};
&mmc1 {
......
......@@ -362,7 +362,6 @@ etb@0,20010000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0x20010000 0 0x1000>;
coresight-default-sink;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
......
......@@ -89,4 +89,6 @@ config DEBUG_ALIGN_RODATA
If in doubt, say N
source "drivers/hwtracing/coresight/Kconfig"
endmenu
......@@ -67,6 +67,7 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
extern void iounmap(volatile void __iomem *addr);
#define ioremap_nocache(off,size) ioremap(off,size)
#define ioremap_wc ioremap_nocache
/*
* IO bus memory addresses are also 1:1 with the physical address
......
......@@ -225,6 +225,8 @@
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INSUFFICIENT_MEMORY 11
#define HV_STATUS_INVALID_CONNECTION_ID 18
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
typedef struct _HV_REFERENCE_TSC_PAGE {
......
......@@ -163,5 +163,5 @@ obj-$(CONFIG_POWERCAP) += powercap/
obj-$(CONFIG_MCB) += mcb/
obj-$(CONFIG_RAS) += ras/
obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
obj-$(CONFIG_CORESIGHT) += coresight/
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
obj-$(CONFIG_ANDROID) += android/
......@@ -300,11 +300,14 @@ static const struct file_operations rng_chrdev_ops = {
.llseek = noop_llseek,
};
static const struct attribute_group *rng_dev_groups[];
static struct miscdevice rng_miscdev = {
.minor = RNG_MISCDEV_MINOR,
.name = RNG_MODULE_NAME,
.nodename = "hwrng",
.fops = &rng_chrdev_ops,
.groups = rng_dev_groups,
};
......@@ -377,37 +380,22 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
hwrng_attr_available_show,
NULL);
static struct attribute *rng_dev_attrs[] = {
&dev_attr_rng_current.attr,
&dev_attr_rng_available.attr,
NULL
};
ATTRIBUTE_GROUPS(rng_dev);
static void __exit unregister_miscdev(void)
{
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
misc_deregister(&rng_miscdev);
}
static int __init register_miscdev(void)
{
int err;
err = misc_register(&rng_miscdev);
if (err)
goto out;
err = device_create_file(rng_miscdev.this_device,
&dev_attr_rng_current);
if (err)
goto err_misc_dereg;
err = device_create_file(rng_miscdev.this_device,
&dev_attr_rng_available);
if (err)
goto err_remove_current;
out:
return err;
err_remove_current:
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
err_misc_dereg:
misc_deregister(&rng_miscdev);
goto out;
return misc_register(&rng_miscdev);
}
static int hwrng_fillfn(void *unused)
......
......@@ -133,7 +133,7 @@ static int rng_remove(struct platform_device *dev)
return 0;
}
static struct of_device_id rng_match[] = {
static const struct of_device_id rng_match[] = {
{ .compatible = "1682m-rng", },
{ .compatible = "pasemi,pwrficient-rng", },
{ },
......
......@@ -61,7 +61,7 @@ static int powernv_rng_probe(struct platform_device *pdev)
return 0;
}
static struct of_device_id powernv_rng_match[] = {
static const struct of_device_id powernv_rng_match[] = {
{ .compatible = "ibm,power-rng",},
{},
};
......
......@@ -123,7 +123,7 @@ static int ppc4xx_rng_remove(struct platform_device *dev)
return 0;
}
static struct of_device_id ppc4xx_rng_match[] = {
static const struct of_device_id ppc4xx_rng_match[] = {
{ .compatible = "ppc4xx-rng", },
{ .compatible = "amcc,ppc460ex-rng", },
{ .compatible = "amcc,ppc440epx-rng", },
......
......@@ -510,13 +510,15 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
* 9) AC power
* 10) Fn Key status
*/
return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
I8K_PROC_FMT,
bios_version,
i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
cpu_temp,
left_fan, right_fan, left_speed, right_speed,
ac_power, fn_key);
seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
I8K_PROC_FMT,
bios_version,
i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
cpu_temp,
left_fan, right_fan, left_speed, right_speed,
ac_power, fn_key);
return 0;
}
static int i8k_open_fs(struct inode *inode, struct file *file)
......
......@@ -2667,7 +2667,7 @@ static struct pci_driver ipmi_pci_driver = {
};
#endif /* CONFIG_PCI */
static struct of_device_id ipmi_match[];
static const struct of_device_id ipmi_match[];
static int ipmi_probe(struct platform_device *dev)
{
#ifdef CONFIG_OF
......@@ -2764,7 +2764,7 @@ static int ipmi_remove(struct platform_device *dev)
return 0;
}
static struct of_device_id ipmi_match[] =
static const struct of_device_id ipmi_match[] =
{
{ .type = "ipmi", .compatible = "ipmi-kcs",
.data = (void *)(unsigned long) SI_KCS },
......
......@@ -140,12 +140,17 @@ static int misc_open(struct inode * inode, struct file * file)
goto fail;
}
/*
* Place the miscdevice in the file's
* private_data so it can be used by the
* file operations, including f_op->open below
*/
file->private_data = c;
err = 0;
replace_fops(file, new_fops);
if (file->f_op->open) {
file->private_data = c;
if (file->f_op->open)
err = file->f_op->open(inode,file);
}
fail:
mutex_unlock(&misc_mtx);
return err;
......@@ -169,7 +174,9 @@ static const struct file_operations misc_fops = {
* the minor number requested is used.
*
* The structure passed is linked into the kernel and may not be
* destroyed until it has been unregistered.
* destroyed until it has been unregistered. By default, an open()
* syscall to the device sets file->private_data to point to the
* structure. Drivers don't need open in fops for this.
*
* A zero is returned on success and a negative errno code for
* failure.
......@@ -205,8 +212,9 @@ int misc_register(struct miscdevice * misc)
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->this_device = device_create(misc_class, misc->parent, dev,
misc, "%s", misc->name);
misc->this_device =
device_create_with_groups(misc_class, misc->parent, dev,
misc, misc->groups, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
int i = DYNAMIC_MINORS - misc->minor - 1;
if (i < DYNAMIC_MINORS && i >= 0)
......
......@@ -355,7 +355,7 @@ static inline bool use_multiport(struct ports_device *portdev)
* early_init
*/
if (!portdev->vdev)
return 0;
return false;
return __virtio_test_bit(portdev->vdev, VIRTIO_CONSOLE_F_MULTIPORT);
}
......
......@@ -1237,6 +1237,8 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,
unsigned char *tail;
int i;
howmany = 0;
end_offset_plus1 = bufpos >>
channel->log2_element_size;
......
......@@ -31,7 +31,7 @@ MODULE_LICENSE("GPL v2");
static const char xillyname[] = "xillybus_of";
/* Match table for of_platform binding */
static struct of_device_id xillybus_of_match[] = {
static const struct of_device_id xillybus_of_match[] = {
{ .compatible = "xillybus,xillybus-1.00.a", },
{ .compatible = "xlnx,xillybus-1.00.a", }, /* Deprecated */
{}
......
......@@ -55,6 +55,16 @@ config EXTCON_MAX77693
Maxim MAX77693 PMIC. The MAX77693 MUIC is a USB port accessory
detector and switch.
config EXTCON_MAX77843
tristate "MAX77843 EXTCON Support"
depends on MFD_MAX77843
select IRQ_DOMAIN
select REGMAP_I2C
help
If you say yes here you get support for the MUIC device of
Maxim MAX77843. The MAX77843 MUIC is a USB port accessory
detector add switch.
config EXTCON_MAX8997
tristate "MAX8997 EXTCON Support"
depends on MFD_MAX8997 && IRQ_DOMAIN
......@@ -93,4 +103,11 @@ config EXTCON_SM5502
Silicon Mitus SM5502. The SM5502 is a USB port accessory
detector and switch.
config EXTCON_USB_GPIO
tristate "USB GPIO extcon support"
depends on GPIOLIB
help
Say Y here to enable GPIO based USB cable detection extcon support.
Used typically if GPIO is used for USB ID pin detection.
endif # MULTISTATE_SWITCH
......@@ -2,13 +2,15 @@
# Makefile for external connector class (extcon) devices
#
obj-$(CONFIG_EXTCON) += extcon-class.o
obj-$(CONFIG_EXTCON) += extcon.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
......@@ -136,18 +136,35 @@ static const char *arizona_cable[] = {
static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
unsigned int magic)
static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
bool clamp)
{
struct arizona *arizona = info->arizona;
unsigned int mask = 0, val = 0;
int ret;
switch (arizona->type) {
case WM5110:
mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
ARIZONA_HP1L_SHRTI;
if (clamp)
val = ARIZONA_HP1L_SHRTO;
else
val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
break;
default:
mask = ARIZONA_RMV_SHRT_HP1L;
if (clamp)
val = ARIZONA_RMV_SHRT_HP1L;
break;
};
mutex_lock(&arizona->dapm->card->dapm_mutex);
arizona->hpdet_magic = magic;
arizona->hpdet_clamp = clamp;
/* Keep the HP output stages disabled while doing the magic */
if (magic) {
/* Keep the HP output stages disabled while doing the clamp */
if (clamp) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA |
......@@ -158,20 +175,20 @@ static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
ret);
}
ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
magic);
ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
mask, val);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
dev_warn(arizona->dev, "Failed to do clamp: %d\n",
ret);
ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
magic);
ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
mask, val);
if (ret != 0)
dev_warn(arizona->dev, "Failed to do magic: %d\n",
dev_warn(arizona->dev, "Failed to do clamp: %d\n",
ret);
/* Restore the desired state while not doing the magic */
if (!magic) {
/* Restore the desired state while not doing the clamp */
if (!clamp) {
ret = regmap_update_bits(arizona->regmap,
ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA |
......@@ -603,7 +620,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
0);
arizona_extcon_do_magic(info, 0);
arizona_extcon_hp_clamp(info, false);
if (id_gpio)
gpio_set_value_cansleep(id_gpio, 0);
......@@ -648,7 +665,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
if (info->mic)
arizona_stop_mic(info);
arizona_extcon_do_magic(info, 0x4000);
arizona_extcon_hp_clamp(info, true);
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1,
......@@ -699,7 +716,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
info->hpdet_active = true;
arizona_extcon_do_magic(info, 0x4000);
arizona_extcon_hp_clamp(info, true);
ret = regmap_update_bits(arizona->regmap,
ARIZONA_ACCESSORY_DETECT_MODE_1,
......
......@@ -539,8 +539,6 @@ static void max14577_muic_irq_work(struct work_struct *work)
dev_err(info->dev, "failed to handle MUIC interrupt\n");
mutex_unlock(&info->mutex);
return;
}
/*
......@@ -730,8 +728,7 @@ static int max14577_muic_probe(struct platform_device *pdev)
muic_irq->name, info);
if (ret) {
dev_err(&pdev->dev,
"failed: irq request (IRQ: %d,"
" error :%d)\n",
"failed: irq request (IRQ: %d, error :%d)\n",
muic_irq->irq, ret);
return ret;
}
......
......@@ -190,8 +190,8 @@ enum max77693_muic_acc_type {
/* The below accessories have same ADC value so ADCLow and
ADC1K bit is used to separate specific accessory */
/* ADC|VBVolot|ADCLow|ADC1K| */
MAX77693_MUIC_GND_USB_OTG = 0x100, /* 0x0| 0| 0| 0| */
MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* 0x0| 1| 0| 0| */
MAX77693_MUIC_GND_USB_HOST = 0x100, /* 0x0| 0| 0| 0| */
MAX77693_MUIC_GND_USB_HOST_VB = 0x104, /* 0x0| 1| 0| 0| */
MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */
MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */
MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */
......@@ -228,7 +228,7 @@ static const char *max77693_extcon_cable[] = {
[EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger",
[EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream",
[EXTCON_CABLE_MHL] = "MHL",
[EXTCON_CABLE_MHL_TA] = "MHL_TA",
[EXTCON_CABLE_MHL_TA] = "MHL-TA",
[EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON",
[EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
[EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
......@@ -403,8 +403,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
/**
* [0x1|VBVolt|ADCLow|ADC1K]
* [0x1| 0| 0| 0] USB_OTG
* [0x1| 1| 0| 0] USB_OTG_VB
* [0x1| 0| 0| 0] USB_HOST
* [0x1| 1| 0| 0] USB_HSOT_VB
* [0x1| 0| 1| 0] Audio Video cable with load
* [0x1| 0| 1| 1] MHL without charging cable
* [0x1| 1| 1| 1] MHL with charging cable
......@@ -523,7 +523,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
* - Support charging and data connection through micro-usb port
* if USB cable is connected between target and host
* device.
* - Support OTG device (Mouse/Keyboard)
* - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
*/
ret = max77693_muic_set_path(info, info->path_usb, attached);
if (ret < 0)
......@@ -609,9 +609,9 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
MAX77693_CABLE_GROUP_ADC_GND, &attached);
switch (cable_type_gnd) {
case MAX77693_MUIC_GND_USB_OTG:
case MAX77693_MUIC_GND_USB_OTG_VB:
/* USB_OTG, PATH: AP_USB */
case MAX77693_MUIC_GND_USB_HOST:
case MAX77693_MUIC_GND_USB_HOST_VB:
/* USB_HOST, PATH: AP_USB */
ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
if (ret < 0)
return ret;
......@@ -704,7 +704,7 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info)
switch (cable_type) {
case MAX77693_MUIC_ADC_GROUND:
/* USB_OTG/MHL/Audio */
/* USB_HOST/MHL/Audio */
max77693_muic_adc_ground_handler(info);
break;
case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
......@@ -823,19 +823,19 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_GND_MHL:
case MAX77693_MUIC_GND_MHL_VB:
/*
* MHL cable with MHL_TA(USB/TA) cable
* MHL cable with MHL-TA(USB/TA) cable
* - MHL cable include two port(HDMI line and separate
* micro-usb port. When the target connect MHL cable,
* extcon driver check whether MHL_TA(USB/TA) cable is
* connected. If MHL_TA cable is connected, extcon
* extcon driver check whether MHL-TA(USB/TA) cable is
* connected. If MHL-TA cable is connected, extcon
* driver notify state to notifiee for charging battery.
*
* Features of 'MHL_TA(USB/TA) with MHL cable'
* Features of 'MHL-TA(USB/TA) with MHL cable'
* - Support MHL
* - Support charging through micro-usb port without
* data connection
*/
extcon_set_cable_state(info->edev, "MHL_TA", attached);
extcon_set_cable_state(info->edev, "MHL-TA", attached);
if (!cable_attached)
extcon_set_cable_state(info->edev,
"MHL", cable_attached);
......@@ -886,7 +886,7 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
* - Support charging and data connection through micro-
* usb port if USB cable is connected between target
* and host device
* - Support OTG device (Mouse/Keyboard)
* - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
*/
ret = max77693_muic_set_path(info, info->path_usb,
attached);
......@@ -1019,8 +1019,6 @@ static void max77693_muic_irq_work(struct work_struct *work)
dev_err(info->dev, "failed to handle MUIC interrupt\n");
mutex_unlock(&info->mutex);
return;
}
static irqreturn_t max77693_muic_irq_handler(int irq, void *data)
......@@ -1171,8 +1169,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
muic_irq->name, info);
if (ret) {
dev_err(&pdev->dev,
"failed: irq request (IRQ: %d,"
" error :%d)\n",
"failed: irq request (IRQ: %d, error :%d)\n",
muic_irq->irq, ret);
return ret;
}
......
This diff is collapsed.
......@@ -579,8 +579,6 @@ static void max8997_muic_irq_work(struct work_struct *work)
dev_err(info->dev, "failed to handle MUIC interrupt\n");
mutex_unlock(&info->mutex);
return;
}
static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
......@@ -689,8 +687,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
muic_irq->name, info);
if (ret) {
dev_err(&pdev->dev,
"failed: irq request (IRQ: %d,"
" error :%d)\n",
"failed: irq request (IRQ: %d, error :%d)\n",
muic_irq->irq, ret);
goto err_irq;
}
......
......@@ -582,10 +582,8 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
return -EINVAL;
info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
if (!info) {
dev_err(&i2c->dev, "failed to allocate memory\n");
if (!info)
return -ENOMEM;
}
i2c_set_clientdata(i2c, info);
info->dev = &i2c->dev;
......@@ -681,7 +679,7 @@ static int rt8973a_muic_i2c_remove(struct i2c_client *i2c)
return 0;
}
static struct of_device_id rt8973a_dt_match[] = {
static const struct of_device_id rt8973a_dt_match[] = {
{ .compatible = "richtek,rt8973a-muic" },
{ },
};
......
......@@ -359,8 +359,8 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
break;
default:
dev_dbg(info->dev,
"cannot identify the cable type: adc(0x%x) "
"dev_type1(0x%x)\n", adc, dev_type1);
"cannot identify the cable type: adc(0x%x)\n",
adc);
return -EINVAL;
};
break;
......@@ -659,7 +659,7 @@ static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
return 0;
}
static struct of_device_id sm5502_dt_match[] = {
static const struct of_device_id sm5502_dt_match[] = {
{ .compatible = "siliconmitus,sm5502-muic" },
{ },
};
......
/**
* drivers/extcon/extcon-usb-gpio.c - USB GPIO extcon driver
*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
* Author: Roger Quadros <rogerq@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/extcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
struct usb_extcon_info {
struct device *dev;
struct extcon_dev *edev;
struct gpio_desc *id_gpiod;
int id_irq;
unsigned long debounce_jiffies;
struct delayed_work wq_detcable;
};
/* List of detectable cables */
enum {
EXTCON_CABLE_USB = 0,
EXTCON_CABLE_USB_HOST,
EXTCON_CABLE_END,
};
static const char *usb_extcon_cable[] = {
[EXTCON_CABLE_USB] = "USB",
[EXTCON_CABLE_USB_HOST] = "USB-HOST",
NULL,
};
static void usb_extcon_detect_cable(struct work_struct *work)
{
int id;
struct usb_extcon_info *info = container_of(to_delayed_work(work),
struct usb_extcon_info,
wq_detcable);
/* check ID and update cable state */
id = gpiod_get_value_cansleep(info->id_gpiod);
if (id) {
/*
* ID = 1 means USB HOST cable detached.
* As we don't have event for USB peripheral cable attached,
* we simulate USB peripheral attach here.
*/
extcon_set_cable_state(info->edev,
usb_extcon_cable[EXTCON_CABLE_USB_HOST],
false);
extcon_set_cable_state(info->edev,
usb_extcon_cable[EXTCON_CABLE_USB],
true);
} else {
/*
* ID = 0 means USB HOST cable attached.
* As we don't have event for USB peripheral cable detached,
* we simulate USB peripheral detach here.
*/
extcon_set_cable_state(info->edev,
usb_extcon_cable[EXTCON_CABLE_USB],
false);
extcon_set_cable_state(info->edev,
usb_extcon_cable[EXTCON_CABLE_USB_HOST],
true);
}
}
static irqreturn_t usb_irq_handler(int irq, void *dev_id)
{
struct usb_extcon_info *info = dev_id;
queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
info->debounce_jiffies);
return IRQ_HANDLED;
}
static int usb_extcon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct usb_extcon_info *info;
int ret;
if (!np)
return -EINVAL;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->dev = dev;
info->id_gpiod = devm_gpiod_get(&pdev->dev, "id");
if (IS_ERR(info->id_gpiod)) {
dev_err(dev, "failed to get ID GPIO\n");
return PTR_ERR(info->id_gpiod);
}
ret = gpiod_set_debounce(info->id_gpiod,
USB_GPIO_DEBOUNCE_MS * 1000);
if (ret < 0)
info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
info->id_irq = gpiod_to_irq(info->id_gpiod);
if (info->id_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
return info->id_irq;
}
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
usb_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
pdev->name, info);
if (ret < 0) {
dev_err(dev, "failed to request handler for ID IRQ\n");
return ret;
}
info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, info->edev);
if (ret < 0) {
dev_err(dev, "failed to register extcon device\n");
return ret;
}
platform_set_drvdata(pdev, info);
device_init_wakeup(dev, 1);
/* Perform initial detection */
usb_extcon_detect_cable(&info->wq_detcable.work);
return 0;
}
static int usb_extcon_remove(struct platform_device *pdev)
{
struct usb_extcon_info *info = platform_get_drvdata(pdev);
cancel_delayed_work_sync(&info->wq_detcable);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int usb_extcon_suspend(struct device *dev)
{
struct usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0;
if (device_may_wakeup(dev)) {
ret = enable_irq_wake(info->id_irq);
if (ret)
return ret;
}
/*
* We don't want to process any IRQs after this point
* as GPIOs used behind I2C subsystem might not be
* accessible until resume completes. So disable IRQ.
*/
disable_irq(info->id_irq);
return ret;
}
static int usb_extcon_resume(struct device *dev)
{
struct usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0;
if (device_may_wakeup(dev)) {
ret = disable_irq_wake(info->id_irq);
if (ret)
return ret;
}
enable_irq(info->id_irq);
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(usb_extcon_pm_ops,
usb_extcon_suspend, usb_extcon_resume);
static const struct of_device_id usb_extcon_dt_match[] = {
{ .compatible = "linux,extcon-usb-gpio", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usb_extcon_dt_match);
static struct platform_driver usb_extcon_driver = {
.probe = usb_extcon_probe,
.remove = usb_extcon_remove,
.driver = {
.name = "extcon-usb-gpio",
.pm = &usb_extcon_pm_ops,
.of_match_table = usb_extcon_dt_match,
},
};
module_platform_driver(usb_extcon_driver);
MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
MODULE_DESCRIPTION("USB GPIO extcon driver");
MODULE_LICENSE("GPL v2");
......@@ -158,6 +158,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
/* Optional callback given by the user */
if (edev->print_name) {
int ret = edev->print_name(edev, buf);
if (ret >= 0)
return ret;
}
......@@ -444,6 +445,9 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
const char *extcon_name, const char *cable_name,
struct notifier_block *nb)
{
unsigned long flags;
int ret;
if (!obj || !cable_name || !nb)
return -EINVAL;
......@@ -461,8 +465,11 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
obj->internal_nb.notifier_call = _call_per_cable;
return raw_notifier_chain_register(&obj->edev->nh,
spin_lock_irqsave(&obj->edev->lock, flags);
ret = raw_notifier_chain_register(&obj->edev->nh,
&obj->internal_nb);
spin_unlock_irqrestore(&obj->edev->lock, flags);
return ret;
} else {
struct class_dev_iter iter;
struct extcon_dev *extd;
......@@ -495,10 +502,17 @@ EXPORT_SYMBOL_GPL(extcon_register_interest);
*/
int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
{
unsigned long flags;
int ret;
if (!obj)
return -EINVAL;
return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
spin_lock_irqsave(&obj->edev->lock, flags);
ret = raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
spin_unlock_irqrestore(&obj->edev->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(extcon_unregister_interest);
......@@ -515,7 +529,14 @@ EXPORT_SYMBOL_GPL(extcon_unregister_interest);
int extcon_register_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return raw_notifier_chain_register(&edev->nh, nb);
unsigned long flags;
int ret;
spin_lock_irqsave(&edev->lock, flags);
ret = raw_notifier_chain_register(&edev->nh, nb);
spin_unlock_irqrestore(&edev->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(extcon_register_notifier);
......@@ -527,7 +548,14 @@ EXPORT_SYMBOL_GPL(extcon_register_notifier);
int extcon_unregister_notifier(struct extcon_dev *edev,
struct notifier_block *nb)
{
return raw_notifier_chain_unregister(&edev->nh, nb);
unsigned long flags;
int ret;
spin_lock_irqsave(&edev->lock, flags);
ret = raw_notifier_chain_unregister(&edev->nh, nb);
spin_unlock_irqrestore(&edev->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
......
......@@ -71,7 +71,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
struct vmbus_channel_msginfo *open_info = NULL;
void *in, *out;
unsigned long flags;
int ret, t, err = 0;
int ret, err = 0;
unsigned long t;
spin_lock_irqsave(&newchannel->lock, flags);
if (newchannel->state == CHANNEL_OPEN_STATE) {
......@@ -89,9 +90,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
get_order(send_ringbuffer_size + recv_ringbuffer_size));
if (!out)
return -ENOMEM;
if (!out) {
err = -ENOMEM;
goto error0;
}
in = (void *)((unsigned long)out + send_ringbuffer_size);
......@@ -135,7 +137,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
GFP_KERNEL);
if (!open_info) {
err = -ENOMEM;
goto error0;
goto error_gpadl;
}
init_completion(&open_info->waitevent);
......@@ -151,7 +153,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
if (userdatalen > MAX_USER_DEFINED_BYTES) {
err = -EINVAL;
goto error0;
goto error_gpadl;
}
if (userdatalen)
......@@ -195,10 +197,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
list_del(&open_info->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
error_gpadl:
vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
error0:
free_pages((unsigned long)out,
get_order(send_ringbuffer_size + recv_ringbuffer_size));
kfree(open_info);
newchannel->state = CHANNEL_OPEN_STATE;
return err;
}
EXPORT_SYMBOL_GPL(vmbus_open);
......@@ -534,6 +540,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
free_pages((unsigned long)channel->ringbuffer_pages,
get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
/*
* If the channel has been rescinded; process device removal.
*/
if (channel->rescind)
hv_process_channel_removal(channel,
channel->offermsg.child_relid);
return ret;
}
......@@ -569,23 +581,9 @@ void vmbus_close(struct vmbus_channel *channel)
}
EXPORT_SYMBOL_GPL(vmbus_close);
/**
* vmbus_sendpacket() - Send the specified buffer on the given channel
* @channel: Pointer to vmbus_channel structure.
* @buffer: Pointer to the buffer you want to receive the data into.
* @bufferlen: Maximum size of what the the buffer will hold
* @requestid: Identifier of the request
* @type: Type of packet that is being send e.g. negotiate, time
* packet etc.
*
* Sends data in @buffer directly to hyper-v via the vmbus
* This will send the data unparsed to hyper-v.
*
* Mainly used by Hyper-V drivers.
*/
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u64 requestid,
enum vmbus_packet_type type, u32 flags)
enum vmbus_packet_type type, u32 flags, bool kick_q)
{
struct vmpacket_descriptor desc;
u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
......@@ -613,21 +611,61 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
if (ret == 0 && signal)
/*
* Signalling the host is conditional on many factors:
* 1. The ring state changed from being empty to non-empty.
* This is tracked by the variable "signal".
* 2. The variable kick_q tracks if more data will be placed
* on the ring. We will not signal if more data is
* to be placed.
*
* If we cannot write to the ring-buffer; signal the host
* even if we may not have written anything. This is a rare
* enough condition that it should not matter.
*/
if (((ret == 0) && kick_q && signal) || (ret))
vmbus_setevent(channel);
return ret;
}
EXPORT_SYMBOL(vmbus_sendpacket_ctl);
/**
* vmbus_sendpacket() - Send the specified buffer on the given channel
* @channel: Pointer to vmbus_channel structure.
* @buffer: Pointer to the buffer you want to receive the data into.
* @bufferlen: Maximum size of what the the buffer will hold
* @requestid: Identifier of the request
* @type: Type of packet that is being send e.g. negotiate, time
* packet etc.
*
* Sends data in @buffer directly to hyper-v via the vmbus
* This will send the data unparsed to hyper-v.
*
* Mainly used by Hyper-V drivers.
*/
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u64 requestid,
enum vmbus_packet_type type, u32 flags)
{
return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid,
type, flags, true);
}
EXPORT_SYMBOL(vmbus_sendpacket);
/*
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
* packets using a GPADL Direct packet type.
* vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer
* packets using a GPADL Direct packet type. This interface allows you
* to control notifying the host. This will be useful for sending
* batched data. Also the sender can control the send flags
* explicitly.
*/
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
struct hv_page_buffer pagebuffers[],
u32 pagecount, void *buffer, u32 bufferlen,
u64 requestid)
u64 requestid,
u32 flags,
bool kick_q)
{
int ret;
int i;
......@@ -655,7 +693,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
/* Setup the descriptor */
desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
desc.flags = flags;
desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
desc.length8 = (u16)(packetlen_aligned >> 3);
desc.transactionid = requestid;
......@@ -676,11 +714,40 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
if (ret == 0 && signal)
/*
* Signalling the host is conditional on many factors:
* 1. The ring state changed from being empty to non-empty.
* This is tracked by the variable "signal".
* 2. The variable kick_q tracks if more data will be placed
* on the ring. We will not signal if more data is
* to be placed.
*
* If we cannot write to the ring-buffer; signal the host
* even if we may not have written anything. This is a rare
* enough condition that it should not matter.
*/
if (((ret == 0) && kick_q && signal) || (ret))
vmbus_setevent(channel);
return ret;
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
/*
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
* packets using a GPADL Direct packet type.
*/
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
struct hv_page_buffer pagebuffers[],
u32 pagecount, void *buffer, u32 bufferlen,
u64 requestid)
{
u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount,
buffer, bufferlen, requestid,
flags, true);
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
/*
......
This diff is collapsed.
......@@ -216,10 +216,21 @@ int vmbus_connect(void)
cleanup:
pr_err("Unable to connect to host\n");
vmbus_connection.conn_state = DISCONNECTED;
vmbus_disconnect();
kfree(msginfo);
if (vmbus_connection.work_queue)
return ret;
}
void vmbus_disconnect(void)
{
if (vmbus_connection.work_queue) {
drain_workqueue(vmbus_connection.work_queue);
destroy_workqueue(vmbus_connection.work_queue);
}
if (vmbus_connection.int_page) {
free_pages((unsigned long)vmbus_connection.int_page, 0);
......@@ -230,10 +241,6 @@ int vmbus_connect(void)
free_pages((unsigned long)vmbus_connection.monitor_pages[1], 0);
vmbus_connection.monitor_pages[0] = NULL;
vmbus_connection.monitor_pages[1] = NULL;
kfree(msginfo);
return ret;
}
/*
......@@ -311,10 +318,8 @@ static void process_chn_event(u32 relid)
*/
channel = pcpu_relid2channel(relid);
if (!channel) {
pr_err("channel not found for relid - %u\n", relid);
if (!channel)
return;
}
/*
* A channel once created is persistent even when there
......@@ -349,10 +354,7 @@ static void process_chn_event(u32 relid)
else
bytes_to_read = 0;
} while (read_state && (bytes_to_read != 0));
} else {
pr_err("no channel callback for relid - %u\n", relid);
}
}
/*
......@@ -420,6 +422,7 @@ int vmbus_post_msg(void *buffer, size_t buflen)
union hv_connection_id conn_id;
int ret = 0;
int retries = 0;
u32 msec = 1;
conn_id.asu32 = 0;
conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
......@@ -429,13 +432,20 @@ int vmbus_post_msg(void *buffer, size_t buflen)
* insufficient resources. Retry the operation a couple of
* times before giving up.
*/
while (retries < 10) {
while (retries < 20) {
ret = hv_post_message(conn_id, 1, buffer, buflen);
switch (ret) {
case HV_STATUS_INVALID_CONNECTION_ID:
/*
* We could get this if we send messages too
* frequently.
*/
ret = -EAGAIN;
break;
case HV_STATUS_INSUFFICIENT_MEMORY:
case HV_STATUS_INSUFFICIENT_BUFFERS:
ret = -ENOMEM;
case -ENOMEM:
break;
case HV_STATUS_SUCCESS:
return ret;
......@@ -445,7 +455,9 @@ int vmbus_post_msg(void *buffer, size_t buflen)
}
retries++;
msleep(100);
msleep(msec);
if (msec < 2048)
msec *= 2;
}
return ret;
}
......
......@@ -312,7 +312,11 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
dev->features = CLOCK_EVT_FEAT_ONESHOT;
dev->cpumask = cpumask_of(cpu);
dev->rating = 1000;
dev->owner = THIS_MODULE;
/*
* Avoid settint dev->owner = THIS_MODULE deliberately as doing so will
* result in clockevents_config_and_register() taking additional
* references to the hv_vmbus module making it impossible to unload.
*/
dev->set_mode = hv_ce_setmode;
dev->set_next_event = hv_ce_set_next_event;
......@@ -469,6 +473,20 @@ void hv_synic_init(void *arg)
return;
}
/*
* hv_synic_clockevents_cleanup - Cleanup clockevent devices
*/
void hv_synic_clockevents_cleanup(void)
{
int cpu;
if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE))
return;
for_each_online_cpu(cpu)
clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
}
/*
* hv_synic_cleanup - Cleanup routine for hv_synic_init().
*/
......@@ -477,11 +495,17 @@ void hv_synic_cleanup(void *arg)
union hv_synic_sint shared_sint;
union hv_synic_simp simp;
union hv_synic_siefp siefp;
union hv_synic_scontrol sctrl;
int cpu = smp_processor_id();
if (!hv_context.synic_initialized)
return;
/* Turn off clockevent device */
if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
hv_ce_setmode(CLOCK_EVT_MODE_SHUTDOWN,
hv_context.clk_evt[cpu]);
rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
shared_sint.masked = 1;
......@@ -502,6 +526,10 @@ void hv_synic_cleanup(void *arg)
wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
free_page((unsigned long)hv_context.synic_message_page[cpu]);
free_page((unsigned long)hv_context.synic_event_page[cpu]);
/* Disable the global synic bit */
rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
sctrl.enable = 0;
wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
hv_synic_free_cpu(cpu);
}
This diff is collapsed.
......@@ -340,12 +340,8 @@ static int util_probe(struct hv_device *dev,
set_channel_read_state(dev->channel, false);
ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
srv->util_cb, dev->channel);
if (ret)
goto error;
hv_set_drvdata(dev, srv);
/*
* Based on the host; initialize the framework and
* service version numbers we will negotiate.
......@@ -365,6 +361,11 @@ static int util_probe(struct hv_device *dev,
hb_srv_version = HB_VERSION;
}
ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
srv->util_cb, dev->channel);
if (ret)
goto error;
return 0;
error:
......@@ -379,9 +380,9 @@ static int util_remove(struct hv_device *dev)
{
struct hv_util_service *srv = hv_get_drvdata(dev);
vmbus_close(dev->channel);
if (srv->util_deinit)
srv->util_deinit();
vmbus_close(dev->channel);
kfree(srv->recv_buffer);
return 0;
......
......@@ -49,6 +49,17 @@ enum hv_cpuid_function {
HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
};
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE 0x400
#define HV_X64_MSR_CRASH_P0 0x40000100
#define HV_X64_MSR_CRASH_P1 0x40000101
#define HV_X64_MSR_CRASH_P2 0x40000102
#define HV_X64_MSR_CRASH_P3 0x40000103
#define HV_X64_MSR_CRASH_P4 0x40000104
#define HV_X64_MSR_CRASH_CTL 0x40000105
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
/* Define version of the synthetic interrupt controller. */
#define HV_SYNIC_VERSION (1)
......@@ -572,6 +583,8 @@ extern void hv_synic_init(void *irqarg);
extern void hv_synic_cleanup(void *arg);
extern void hv_synic_clockevents_cleanup(void);
/*
* Host version information.
*/
......@@ -672,6 +685,23 @@ struct vmbus_msginfo {
extern struct vmbus_connection vmbus_connection;
enum vmbus_message_handler_type {
/* The related handler can sleep. */
VMHT_BLOCKING = 0,
/* The related handler must NOT sleep. */
VMHT_NON_BLOCKING = 1,
};
struct vmbus_channel_message_table_entry {
enum vmbus_channel_message_type message_type;
enum vmbus_message_handler_type handler_type;
void (*message_handler)(struct vmbus_channel_message_header *msg);
};
extern struct vmbus_channel_message_table_entry
channel_message_table[CHANNELMSG_COUNT];
/* General vmbus interface */
struct hv_device *vmbus_device_create(const uuid_le *type,
......@@ -692,6 +722,7 @@ void vmbus_free_channels(void);
/* Connection interface */
int vmbus_connect(void);
void vmbus_disconnect(void);
int vmbus_post_msg(void *buffer, size_t buflen);
......
......@@ -33,9 +33,12 @@
#include <linux/hyperv.h>
#include <linux/kernel_stat.h>
#include <linux/clockchips.h>
#include <linux/cpu.h>
#include <asm/hyperv.h>
#include <asm/hypervisor.h>
#include <asm/mshyperv.h>
#include <linux/notifier.h>
#include <linux/ptrace.h>
#include "hyperv_vmbus.h"
static struct acpi_device *hv_acpi_dev;
......@@ -44,6 +47,31 @@ static struct tasklet_struct msg_dpc;
static struct completion probe_event;
static int irq;
static int hyperv_panic_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct pt_regs *regs;
regs = current_pt_regs();
wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
/*
* Let Hyper-V know there is crash data available
*/
wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
return NOTIFY_DONE;
}
static struct notifier_block hyperv_panic_block = {
.notifier_call = hyperv_panic_event,
};
struct resource hyperv_mmio = {
.name = "hyperv mmio",
.flags = IORESOURCE_MEM,
......@@ -507,14 +535,26 @@ static int vmbus_probe(struct device *child_device)
*/
static int vmbus_remove(struct device *child_device)
{
struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
struct hv_driver *drv;
struct hv_device *dev = device_to_hv_device(child_device);
if (drv->remove)
drv->remove(dev);
else
pr_err("remove not set for driver %s\n",
dev_name(child_device));
u32 relid = dev->channel->offermsg.child_relid;
if (child_device->driver) {
drv = drv_to_hv_drv(child_device->driver);
if (drv->remove)
drv->remove(dev);
else {
hv_process_channel_removal(dev->channel, relid);
pr_err("remove not set for driver %s\n",
dev_name(child_device));
}
} else {
/*
* We don't have a driver for this device; deal with the
* rescind message by removing the channel.
*/
hv_process_channel_removal(dev->channel, relid);
}
return 0;
}
......@@ -573,6 +613,10 @@ static void vmbus_onmessage_work(struct work_struct *work)
{
struct onmessage_work_context *ctx;
/* Do not process messages if we're in DISCONNECTED state */
if (vmbus_connection.conn_state == DISCONNECTED)
return;
ctx = container_of(work, struct onmessage_work_context,
work);
vmbus_onmessage(&ctx->msg);
......@@ -613,21 +657,36 @@ static void vmbus_on_msg_dpc(unsigned long data)
void *page_addr = hv_context.synic_message_page[cpu];
struct hv_message *msg = (struct hv_message *)page_addr +
VMBUS_MESSAGE_SINT;
struct vmbus_channel_message_header *hdr;
struct vmbus_channel_message_table_entry *entry;
struct onmessage_work_context *ctx;
while (1) {
if (msg->header.message_type == HVMSG_NONE) {
if (msg->header.message_type == HVMSG_NONE)
/* no msg */
break;
} else {
hdr = (struct vmbus_channel_message_header *)msg->u.payload;
if (hdr->msgtype >= CHANNELMSG_COUNT) {
WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
goto msg_handled;
}
entry = &channel_message_table[hdr->msgtype];
if (entry->handler_type == VMHT_BLOCKING) {
ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
if (ctx == NULL)
continue;
INIT_WORK(&ctx->work, vmbus_onmessage_work);
memcpy(&ctx->msg, msg, sizeof(*msg));
queue_work(vmbus_connection.work_queue, &ctx->work);
}
} else
entry->message_handler(hdr);
msg_handled:
msg->header.message_type = HVMSG_NONE;
/*
......@@ -704,6 +763,39 @@ static void vmbus_isr(void)
}
}
#ifdef CONFIG_HOTPLUG_CPU
static int hyperv_cpu_disable(void)
{
return -ENOSYS;
}
static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
{
static void *previous_cpu_disable;
/*
* Offlining a CPU when running on newer hypervisors (WS2012R2, Win8,
* ...) is not supported at this moment as channel interrupts are
* distributed across all of them.
*/
if ((vmbus_proto_version == VERSION_WS2008) ||
(vmbus_proto_version == VERSION_WIN7))
return;
if (vmbus_loaded) {
previous_cpu_disable = smp_ops.cpu_disable;
smp_ops.cpu_disable = hyperv_cpu_disable;
pr_notice("CPU offlining is not supported by hypervisor\n");
} else if (previous_cpu_disable)
smp_ops.cpu_disable = previous_cpu_disable;
}
#else
static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
{
}
#endif
/*
* vmbus_bus_init -Main vmbus driver initialization routine.
*
......@@ -744,6 +836,16 @@ static int vmbus_bus_init(int irq)
if (ret)
goto err_alloc;
hv_cpu_hotplug_quirk(true);
/*
* Only register if the crash MSRs are available
*/
if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
atomic_notifier_chain_register(&panic_notifier_list,
&hyperv_panic_block);
}
vmbus_request_offers();
return 0;
......@@ -840,10 +942,8 @@ int vmbus_device_register(struct hv_device *child_device_obj)
{
int ret = 0;
static atomic_t device_num = ATOMIC_INIT(0);
dev_set_name(&child_device_obj->device, "vmbus_0_%d",
atomic_inc_return(&device_num));
dev_set_name(&child_device_obj->device, "vmbus_%d",
child_device_obj->channel->id);
child_device_obj->device.bus = &hv_bus;
child_device_obj->device.parent = &hv_acpi_dev->dev;
......@@ -992,11 +1092,19 @@ static int __init hv_acpi_init(void)
static void __exit vmbus_exit(void)
{
int cpu;
vmbus_connection.conn_state = DISCONNECTED;
hv_synic_clockevents_cleanup();
hv_remove_vmbus_irq();
vmbus_free_channels();
bus_unregister(&hv_bus);
hv_cleanup();
for_each_online_cpu(cpu)
smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
acpi_bus_unregister_driver(&vmbus_acpi_driver);
hv_cpu_hotplug_quirk(false);
vmbus_disconnect();
}
......
#
# Coresight configuration
#
menuconfig CORESIGHT
bool "CoreSight Tracing Support"
select ARM_AMBA
help
This framework provides a kernel interface for the CoreSight debug
and trace drivers to register themselves with. It's intended to build
a topological view of the CoreSight components based on a DT
specification and configure the right serie of components when a
trace source gets enabled.
if CORESIGHT
config CORESIGHT_LINKS_AND_SINKS
bool "CoreSight Link and Sink drivers"
help
This enables support for CoreSight link and sink drivers that are
responsible for transporting and collecting the trace data
respectively. Link and sinks are dynamically aggregated with a trace
entity at run time to form a complete trace path.
config CORESIGHT_LINK_AND_SINK_TMC
bool "Coresight generic TMC driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Memory Controller driver.
Depending on its configuration the device can act as a link (embedded
trace router - ETR) or sink (embedded trace FIFO). The driver
complies with the generic implementation of the component without
special enhancement or added features.
config CORESIGHT_SINK_TPIU
bool "Coresight generic TPIU driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Port Interface Unit driver,
responsible for bridging the gap between the on-chip coresight
components and a trace for bridging the gap between the on-chip
coresight components and a trace port collection engine, typically
connected to an external host for use case capturing more traces than
the on-board coresight memory can handle.
config CORESIGHT_SINK_ETBV10
bool "Coresight ETBv1.0 driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Embedded Trace Buffer version 1.0 driver
that complies with the generic implementation of the component without
special enhancement or added features.
config CORESIGHT_SOURCE_ETM3X
bool "CoreSight Embedded Trace Macrocell 3.x driver"
depends on !ARM64
select CORESIGHT_LINKS_AND_SINKS
help
This driver provides support for processor ETM3.x and PTM1.x modules,
which allows tracing the instructions that a processor is executing
This is primarily useful for instruction level tracing. Depending
the ETM version data tracing may also be available.
endif
......@@ -313,8 +313,8 @@ static ssize_t etb_read(struct file *file, char __user *data,
*ppos += len;
dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
__func__, len, (int) (depth * 4 - *ppos));
dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
__func__, len, (int)(depth * 4 - *ppos));
return len;
}
......
......@@ -107,7 +107,7 @@ static int replicator_remove(struct platform_device *pdev)
return 0;
}
static struct of_device_id replicator_match[] = {
static const struct of_device_id replicator_match[] = {
{.compatible = "arm,coresight-replicator"},
{}
};
......
......@@ -533,8 +533,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
*ppos += len;
dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
__func__, len, (int) (drvdata->size - *ppos));
dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
__func__, len, (int)(drvdata->size - *ppos));
return len;
}
......@@ -565,6 +565,59 @@ static const struct file_operations tmc_fops = {
.llseek = no_llseek,
};
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
unsigned long flags;
u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
u32 devid;
struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
ret = clk_prepare_enable(drvdata->clk);
if (ret)
goto out;
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ);
tmc_sts = readl_relaxed(drvdata->base + TMC_STS);
tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP);
tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP);
tmc_trg = readl_relaxed(drvdata->base + TMC_TRG);
tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL);
tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR);
tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
tmc_mode = readl_relaxed(drvdata->base + TMC_MODE);
tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR);
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
clk_disable_unprepare(drvdata->clk);
return sprintf(buf,
"Depth:\t\t0x%x\n"
"Status:\t\t0x%x\n"
"RAM read ptr:\t0x%x\n"
"RAM wrt ptr:\t0x%x\n"
"Trigger cnt:\t0x%x\n"
"Control:\t0x%x\n"
"Flush status:\t0x%x\n"
"Flush ctrl:\t0x%x\n"
"Mode:\t\t0x%x\n"
"PSRC:\t\t0x%x\n"
"DEVID:\t\t0x%x\n",
tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
out:
return -EINVAL;
}
static DEVICE_ATTR_RO(status);
static ssize_t trigger_cntr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
......@@ -593,18 +646,21 @@ static DEVICE_ATTR_RW(trigger_cntr);
static struct attribute *coresight_etb_attrs[] = {
&dev_attr_trigger_cntr.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(coresight_etb);
static struct attribute *coresight_etr_attrs[] = {
&dev_attr_trigger_cntr.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(coresight_etr);
static struct attribute *coresight_etf_attrs[] = {
&dev_attr_trigger_cntr.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(coresight_etf);
......
......@@ -305,7 +305,9 @@ static int coresight_build_paths(struct coresight_device *csdev,
list_add(&csdev->path_link, path);
if (csdev->type == CORESIGHT_DEV_TYPE_SINK && csdev->activated) {
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
csdev->activated) {
if (enable)
ret = coresight_enable_path(path);
else
......
......@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/coresight.h>
#include <linux/cpumask.h>
#include <asm/smp_plat.h>
......@@ -104,7 +105,7 @@ static int of_coresight_alloc_memory(struct device *dev,
struct coresight_platform_data *of_get_coresight_platform_data(
struct device *dev, struct device_node *node)
{
int i = 0, ret = 0;
int i = 0, ret = 0, cpu;
struct coresight_platform_data *pdata;
struct of_endpoint endpoint, rendpoint;
struct device *rdev;
......@@ -178,17 +179,10 @@ struct coresight_platform_data *of_get_coresight_platform_data(
/* Affinity defaults to CPU0 */
pdata->cpu = 0;
dn = of_parse_phandle(node, "cpu", 0);
if (dn) {
const u32 *cell;
int len, index;
u64 hwid;
cell = of_get_property(dn, "reg", &len);
if (cell) {
hwid = of_read_number(cell, of_n_addr_cells(dn));
index = get_logical_index(hwid);
if (index != -EINVAL)
pdata->cpu = index;
for (cpu = 0; dn && cpu < nr_cpu_ids; cpu++) {
if (dn == of_get_cpu_node(cpu, NULL)) {
pdata->cpu = cpu;
break;
}
}
......
......@@ -56,9 +56,9 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE,
KBUILD_MODNAME);
if (IS_ERR(res)) {
if (!res) {
dev_err(&pdev->dev, "Failed to request PCI memory\n");
ret = PTR_ERR(res);
ret = -EBUSY;
goto out_disable;
}
......
......@@ -83,6 +83,15 @@ config FSL_IFC
bool
depends on FSL_SOC
config JZ4780_NEMC
bool "Ingenic JZ4780 SoC NEMC driver"
default y
depends on MACH_JZ4780
help
This driver is for the NAND/External Memory Controller (NEMC) in
the Ingenic JZ4780. This controller is used to handle external
memory devices such as NAND and SRAM.
source "drivers/memory/tegra/Kconfig"
endif
......@@ -13,5 +13,6 @@ obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
obj-$(CONFIG_TEGRA_MC) += tegra/
This diff is collapsed.
......@@ -230,6 +230,8 @@ static const struct i2c_device_id bh1780_id[] = {
{ },
};
MODULE_DEVICE_TABLE(i2c, bh1780_id);
#ifdef CONFIG_OF
static const struct of_device_id of_bh1780_match[] = {
{ .compatible = "rohm,bh1780gli", },
......
......@@ -479,6 +479,7 @@ static int fpga_program_block(struct fpga_dev *priv, void *buf, size_t count)
static noinline int fpga_program_cpu(struct fpga_dev *priv)
{
int ret;
unsigned long timeout;
/* Disable the programmer */
fpga_programmer_disable(priv);
......@@ -497,8 +498,8 @@ static noinline int fpga_program_cpu(struct fpga_dev *priv)
goto out_disable_controller;
/* Wait for the interrupt handler to signal that programming finished */
ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
if (!ret) {
timeout = wait_for_completion_timeout(&priv->completion, 2 * HZ);
if (!timeout) {
dev_err(priv->dev, "Timed out waiting for completion\n");
ret = -ETIMEDOUT;
goto out_disable_controller;
......@@ -536,6 +537,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
struct sg_table table;
dma_cookie_t cookie;
int ret, i;
unsigned long timeout;
/* Disable the programmer */
fpga_programmer_disable(priv);
......@@ -623,8 +625,8 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
dev_dbg(priv->dev, "enabled the controller\n");
/* Wait for the interrupt handler to signal that programming finished */
ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
if (!ret) {
timeout = wait_for_completion_timeout(&priv->completion, 2 * HZ);
if (!timeout) {
dev_err(priv->dev, "Timed out waiting for completion\n");
ret = -ETIMEDOUT;
goto out_disable_controller;
......@@ -1142,7 +1144,7 @@ static int fpga_of_probe(struct platform_device *op)
return ret;
}
static struct of_device_id fpga_of_match[] = {
static const struct of_device_id fpga_of_match[] = {
{ .compatible = "carma,fpga-programmer", },
{},
};
......
......@@ -1486,7 +1486,7 @@ static int data_of_remove(struct platform_device *op)
return 0;
}
static struct of_device_id data_of_match[] = {
static const struct of_device_id data_of_match[] = {
{ .compatible = "carma,carma-fpga", },
{},
};
......
......@@ -950,6 +950,7 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
struct lis3lv02d_platform_data *pdata;
struct device_node *np = lis3->of_node;
u32 val;
s32 sval;
if (!lis3->of_node)
return 0;
......@@ -1031,6 +1032,23 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO;
if (of_get_property(np, "st,wakeup-z-hi", NULL))
pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI;
if (of_get_property(np, "st,wakeup-threshold", &val))
pdata->wakeup_thresh = val;
if (of_get_property(np, "st,wakeup2-x-lo", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_X_LO;
if (of_get_property(np, "st,wakeup2-x-hi", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_X_HI;
if (of_get_property(np, "st,wakeup2-y-lo", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_LO;
if (of_get_property(np, "st,wakeup2-y-hi", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_HI;
if (of_get_property(np, "st,wakeup2-z-lo", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_LO;
if (of_get_property(np, "st,wakeup2-z-hi", NULL))
pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_HI;
if (of_get_property(np, "st,wakeup2-threshold", &val))
pdata->wakeup_thresh2 = val;
if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) {
switch (val) {
......@@ -1054,29 +1072,29 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
if (of_get_property(np, "st,hipass2-disable", NULL))
pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE;
if (of_get_property(np, "st,axis-x", &val))
pdata->axis_x = val;
if (of_get_property(np, "st,axis-y", &val))
pdata->axis_y = val;
if (of_get_property(np, "st,axis-z", &val))
pdata->axis_z = val;
if (of_property_read_s32(np, "st,axis-x", &sval) == 0)
pdata->axis_x = sval;
if (of_property_read_s32(np, "st,axis-y", &sval) == 0)
pdata->axis_y = sval;
if (of_property_read_s32(np, "st,axis-z", &sval) == 0)
pdata->axis_z = sval;
if (of_get_property(np, "st,default-rate", NULL))
pdata->default_rate = val;
if (of_get_property(np, "st,min-limit-x", &val))
pdata->st_min_limits[0] = val;
if (of_get_property(np, "st,min-limit-y", &val))
pdata->st_min_limits[1] = val;
if (of_get_property(np, "st,min-limit-z", &val))
pdata->st_min_limits[2] = val;
if (of_get_property(np, "st,max-limit-x", &val))
pdata->st_max_limits[0] = val;
if (of_get_property(np, "st,max-limit-y", &val))
pdata->st_max_limits[1] = val;
if (of_get_property(np, "st,max-limit-z", &val))
pdata->st_max_limits[2] = val;
if (of_property_read_s32(np, "st,min-limit-x", &sval) == 0)
pdata->st_min_limits[0] = sval;
if (of_property_read_s32(np, "st,min-limit-y", &sval) == 0)
pdata->st_min_limits[1] = sval;
if (of_property_read_s32(np, "st,min-limit-z", &sval) == 0)
pdata->st_min_limits[2] = sval;
if (of_property_read_s32(np, "st,max-limit-x", &sval) == 0)
pdata->st_max_limits[0] = sval;
if (of_property_read_s32(np, "st,max-limit-y", &sval) == 0)
pdata->st_max_limits[1] = sval;
if (of_property_read_s32(np, "st,max-limit-z", &sval) == 0)
pdata->st_max_limits[2] = sval;
lis3->pdata = pdata;
......
......@@ -106,7 +106,7 @@ static union axis_conversion lis3lv02d_axis_map =
{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
#ifdef CONFIG_OF
static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
static const struct of_device_id lis3lv02d_i2c_dt_ids[] = {
{ .compatible = "st,lis3lv02d" },
{}
};
......
......@@ -61,7 +61,7 @@ static union axis_conversion lis3lv02d_axis_normal =
{ .as_array = { 1, 2, 3 } };
#ifdef CONFIG_OF
static struct of_device_id lis302dl_spi_dt_ids[] = {
static const struct of_device_id lis302dl_spi_dt_ids[] = {
{ .compatible = "st,lis302dl-spi" },
{}
};
......
......@@ -21,3 +21,6 @@ mei-me-objs += hw-me.o
obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
mei-txe-objs := pci-txe.o
mei-txe-objs += hw-txe.o
mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
CFLAGS_mei-trace.o = -I$(src)
This diff is collapsed.
......@@ -238,7 +238,7 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
dev = cl->dev;
mutex_lock(&dev->device_lock);
if (cl->state != MEI_FILE_CONNECTED) {
if (!mei_cl_is_connected(cl)) {
rets = -ENODEV;
goto out;
}
......@@ -255,17 +255,13 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
goto out;
}
cb = mei_io_cb_init(cl, NULL);
cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
if (!cb) {
rets = -ENOMEM;
goto out;
}
rets = mei_io_cb_alloc_req_buf(cb, length);
if (rets < 0)
goto out;
memcpy(cb->request_buffer.data, buf, length);
memcpy(cb->buf.data, buf, length);
rets = mei_cl_write(cl, cb, blocking);
......@@ -292,20 +288,21 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
mutex_lock(&dev->device_lock);
if (!cl->read_cb) {
rets = mei_cl_read_start(cl, length);
if (rets < 0)
goto out;
}
cb = mei_cl_read_cb(cl, NULL);
if (cb)
goto copy;
if (cl->reading_state != MEI_READ_COMPLETE &&
!waitqueue_active(&cl->rx_wait)) {
rets = mei_cl_read_start(cl, length, NULL);
if (rets && rets != -EBUSY)
goto out;
if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
mutex_unlock(&dev->device_lock);
if (wait_event_interruptible(cl->rx_wait,
cl->reading_state == MEI_READ_COMPLETE ||
mei_cl_is_transitioning(cl))) {
(!list_empty(&cl->rd_completed)) ||
(!mei_cl_is_connected(cl)))) {
if (signal_pending(current))
return -EINTR;
......@@ -313,23 +310,31 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
}
mutex_lock(&dev->device_lock);
}
cb = cl->read_cb;
if (!mei_cl_is_connected(cl)) {
rets = -EBUSY;
goto out;
}
}
if (cl->reading_state != MEI_READ_COMPLETE) {
cb = mei_cl_read_cb(cl, NULL);
if (!cb) {
rets = 0;
goto out;
}
copy:
if (cb->status) {
rets = cb->status;
goto free;
}
r_length = min_t(size_t, length, cb->buf_idx);
memcpy(buf, cb->response_buffer.data, r_length);
memcpy(buf, cb->buf.data, r_length);
rets = r_length;
free:
mei_io_cb_free(cb);
cl->reading_state = MEI_IDLE;
cl->read_cb = NULL;
out:
mutex_unlock(&dev->device_lock);
......@@ -386,7 +391,7 @@ static void mei_bus_event_work(struct work_struct *work)
device->events = 0;
/* Prepare for the next read */
mei_cl_read_start(device->cl, 0);
mei_cl_read_start(device->cl, 0, NULL);
}
int mei_cl_register_event_cb(struct mei_cl_device *device,
......@@ -400,7 +405,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *device,
device->event_context = context;
INIT_WORK(&device->event_work, mei_bus_event_work);
mei_cl_read_start(device->cl, 0);
mei_cl_read_start(device->cl, 0, NULL);
return 0;
}
......@@ -441,8 +446,8 @@ int mei_cl_enable_device(struct mei_cl_device *device)
mutex_unlock(&dev->device_lock);
if (device->event_cb && !cl->read_cb)
mei_cl_read_start(device->cl, 0);
if (device->event_cb)
mei_cl_read_start(device->cl, 0, NULL);
if (!device->ops || !device->ops->enable)
return 0;
......@@ -462,54 +467,34 @@ int mei_cl_disable_device(struct mei_cl_device *device)
dev = cl->dev;
if (device->ops && device->ops->disable)
device->ops->disable(device);
device->event_cb = NULL;
mutex_lock(&dev->device_lock);
if (cl->state != MEI_FILE_CONNECTED) {
mutex_unlock(&dev->device_lock);
if (!mei_cl_is_connected(cl)) {
dev_err(dev->dev, "Already disconnected");
return 0;
err = 0;
goto out;
}
cl->state = MEI_FILE_DISCONNECTING;
err = mei_cl_disconnect(cl);
if (err < 0) {
mutex_unlock(&dev->device_lock);
dev_err(dev->dev,
"Could not disconnect from the ME client");
return err;
dev_err(dev->dev, "Could not disconnect from the ME client");
goto out;
}
/* Flush queues and remove any pending read */
mei_cl_flush_queues(cl);
if (cl->read_cb) {
struct mei_cl_cb *cb = NULL;
cb = mei_cl_find_read_cb(cl);
/* Remove entry from read list */
if (cb)
list_del(&cb->list);
cb = cl->read_cb;
cl->read_cb = NULL;
if (cb) {
mei_io_cb_free(cb);
cb = NULL;
}
}
device->event_cb = NULL;
mei_cl_flush_queues(cl, NULL);
out:
mutex_unlock(&dev->device_lock);
return err;
if (!device->ops || !device->ops->disable)
return 0;
return device->ops->disable(device);
}
EXPORT_SYMBOL_GPL(mei_cl_disable_device);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -71,8 +71,8 @@ extern const struct mei_cfg mei_me_pch8_sps_cfg;
struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
const struct mei_cfg *cfg);
int mei_me_pg_set_sync(struct mei_device *dev);
int mei_me_pg_unset_sync(struct mei_device *dev);
int mei_me_pg_enter_sync(struct mei_device *dev);
int mei_me_pg_exit_sync(struct mei_device *dev);
irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
......
......@@ -412,7 +412,7 @@ static void mei_txe_intr_disable(struct mei_device *dev)
mei_txe_br_reg_write(hw, HIER_REG, 0);
}
/**
* mei_txe_intr_disable - enable all interrupts
* mei_txe_intr_enable - enable all interrupts
*
* @dev: the device structure
*/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -363,8 +363,6 @@ static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
{
int rc;
pci_msi_off(pdev);
/* Enable intx */
pci_intx(pdev, 1);
rc = mic_setup_callbacks(mdev);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment