Commit 4c257ec3 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull char/misc updates from Greg KH:
 "Here's the big set of char/misc patches for 4.5-rc1.

  Nothing major, lots of different driver subsystem updates, full
  details in the shortlog.  All of these have been in linux-next for a
  while"

* tag 'char-misc-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (71 commits)
  mei: fix fasync return value on error
  parport: avoid assignment in if
  parport: remove unneeded space
  parport: change style of NULL comparison
  parport: remove unnecessary out of memory message
  parport: remove braces
  parport: quoted strings should not be split
  parport: code indent should use tabs
  parport: fix coding style
  parport: EXPORT_SYMBOL should follow function
  parport: remove trailing white space
  parport: fix a trivial typo
  coresight: Fix a typo in Kconfig
  coresight: checking for NULL string in coresight_name_match()
  Drivers: hv: vmbus: Treat Fibre Channel devices as performance critical
  Drivers: hv: utils: fix hvt_op_poll() return value on transport destroy
  Drivers: hv: vmbus: fix the building warning with hyperv-keyboard
  extcon: add Maxim MAX3355 driver
  Drivers: hv: ring_buffer: eliminate hv_ringbuffer_peek()
  Drivers: hv: remove code duplication between vmbus_recvpacket()/vmbus_recvpacket_raw()
  ...
parents 39272dde ed6dc538
......@@ -13,3 +13,63 @@ Optional properties:
ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR
If this node is not mentioned or if the value is unknown, then
headphone detection mode is set to HPDETL.
- wlf,use-jd2 : Use the additional JD input along with JD1 for dual pin jack
detection.
- wlf,use-jd2-nopull : Internal pull on JD2 is disabled when used for
jack detection.
- wlf,jd-invert : Invert the polarity of the jack detection switch
- wlf,micd-software-compare : Use a software comparison to determine mic
presence
- wlf,micd-detect-debounce : Additional software microphone detection
debounce specified in milliseconds.
- wlf,micd-pol-gpio : GPIO specifier for the GPIO controlling the headset
polarity if one exists.
- wlf,micd-bias-start-time : Time allowed for MICBIAS to startup prior to
performing microphone detection, specified as per the ARIZONA_MICD_TIME_XXX
defines.
- wlf,micd-rate : Delay between successive microphone detection measurements,
specified as per the ARIZONA_MICD_TIME_XXX defines.
- wlf,micd-dbtime : Microphone detection hardware debounces specified as the
number of measurements to take, valid values being 2 and 4.
- wlf,micd-timeout-ms : Timeout for microphone detection, specified in
milliseconds.
- wlf,micd-force-micbias : Force MICBIAS continuously on during microphone
detection.
- wlf,micd-configs : Headset polarity configurations (generally used for
detection of CTIA / OMTP headsets), the field can be of variable length
but should always be a multiple of 3 cells long, each three cell group
represents one polarity configuration.
The first cell defines the accessory detection pin, zero will use MICDET1
and all other values will use MICDET2.
The second cell represents the MICBIAS to be used.
The third cell represents the value of the micd-pol-gpio pin.
- wlf,gpsw : Settings for the general purpose switch
Example:
codec: wm8280@0 {
compatible = "wlf,wm8280";
reg = <0>;
...
wlf,use-jd2;
wlf,use-jd2-nopull;
wlf,jd-invert;
wlf,micd-software-compare;
wlf,micd-detect-debounce = <0>;
wlf,micd-pol-gpio = <&codec 2 0>;
wlf,micd-rate = <ARIZONA_MICD_TIME_8MS>;
wlf,micd-dbtime = <4>;
wlf,micd-timeout-ms = <100>;
wlf,micd-force-micbias;
wlf,micd-configs = <
0 1 0 /* MICDET1 MICBIAS1 GPIO=low */
1 2 1 /* MICDET2 MICBIAS2 GPIO=high */
>;
wlf,gpsw = <0>;
};
Maxim Integrated MAX3355 USB OTG chip
-------------------------------------
MAX3355 integrates a charge pump and comparators to enable a system with an
integrated USB OTG dual-role transceiver to function as a USB OTG dual-role
device.
Required properties:
- compatible: should be "maxim,max3355";
- maxim,shdn-gpios: should contain a phandle and GPIO specifier for the GPIO pin
connected to the MAX3355's SHDN# pin;
- id-gpios: should contain a phandle and GPIO specifier for the GPIO pin
connected to the MAX3355's ID_OUT pin.
Example:
usb-otg {
compatible = "maxim,max3355";
maxim,shdn-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
id-gpios = <&gpio5 31 GPIO_ACTIVE_HIGH>;
};
......@@ -52,6 +52,15 @@ config EXTCON_MAX14577
Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory
detector and switch.
config EXTCON_MAX3355
tristate "Maxim MAX3355 USB OTG EXTCON Support"
depends on GPIOLIB || COMPILE_TEST
help
If you say yes here you get support for the USB OTG role detection by
MAX3355. The MAX3355 chip integrates a charge pump and comparators to
enable a system with an integrated USB OTG dual-role transceiver to
function as an USB OTG dual-role device.
config EXTCON_MAX77693
tristate "Maxim MAX77693 EXTCON Support"
depends on MFD_MAX77693 && INPUT
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX3355) += extcon-max3355.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
......
......@@ -1201,10 +1201,58 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
regmap_update_bits(arizona->regmap, reg, mask, level);
}
static int arizona_extcon_device_get_pdata(struct arizona *arizona)
static int arizona_extcon_get_micd_configs(struct device *dev,
struct arizona *arizona)
{
const char * const prop = "wlf,micd-configs";
const int entries_per_config = 3;
struct arizona_micd_config *micd_configs;
int nconfs, ret;
int i, j;
u32 *vals;
nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0);
if (nconfs <= 0)
return 0;
vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
if (!vals)
return -ENOMEM;
ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
if (ret < 0)
goto out;
nconfs /= entries_per_config;
micd_configs = devm_kzalloc(dev,
nconfs * sizeof(struct arizona_micd_range),
GFP_KERNEL);
if (!micd_configs) {
ret = -ENOMEM;
goto out;
}
for (i = 0, j = 0; i < nconfs; ++i) {
micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
micd_configs[i].bias = vals[j++];
micd_configs[i].gpio = vals[j++];
}
arizona->pdata.micd_configs = micd_configs;
arizona->pdata.num_micd_configs = nconfs;
out:
kfree(vals);
return ret;
}
static int arizona_extcon_device_get_pdata(struct device *dev,
struct arizona *arizona)
{
struct arizona_pdata *pdata = &arizona->pdata;
unsigned int val = ARIZONA_ACCDET_MODE_HPL;
int ret;
device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
switch (val) {
......@@ -1230,12 +1278,29 @@ static int arizona_extcon_device_get_pdata(struct arizona *arizona)
device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
&pdata->micd_dbtime);
device_property_read_u32(arizona->dev, "wlf,micd-timeout",
device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
&pdata->micd_timeout);
pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
"wlf,micd-force-micbias");
pdata->micd_software_compare = device_property_read_bool(arizona->dev,
"wlf,micd-software-compare");
pdata->jd_invert = device_property_read_bool(arizona->dev,
"wlf,jd-invert");
device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
"wlf,use-jd2");
pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
"wlf,use-jd2-nopull");
ret = arizona_extcon_get_micd_configs(dev, arizona);
if (ret < 0)
dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
return 0;
}
......@@ -1257,7 +1322,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
if (!dev_get_platdata(arizona->dev))
arizona_extcon_device_get_pdata(arizona);
arizona_extcon_device_get_pdata(&pdev->dev, arizona);
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
if (IS_ERR(info->micvdd)) {
......
......@@ -692,7 +692,7 @@ static int max14577_muic_probe(struct platform_device *pdev)
/* Support irq domain for max14577 MUIC device */
for (i = 0; i < info->muic_irqs_num; i++) {
struct max14577_muic_irq *muic_irq = &info->muic_irqs[i];
unsigned int virq = 0;
int virq = 0;
virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq);
if (virq <= 0)
......
/*
* Maxim Integrated MAX3355 USB OTG chip extcon driver
*
* Copyright (C) 2014-2015 Cogent Embedded, Inc.
* Author: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*/
#include <linux/extcon.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct max3355_data {
struct extcon_dev *edev;
struct gpio_desc *id_gpiod;
struct gpio_desc *shdn_gpiod;
};
static const unsigned int max3355_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
EXTCON_NONE,
};
static irqreturn_t max3355_id_irq(int irq, void *dev_id)
{
struct max3355_data *data = dev_id;
int id = gpiod_get_value_cansleep(data->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_(data->edev, EXTCON_USB_HOST, false);
extcon_set_cable_state_(data->edev, EXTCON_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_(data->edev, EXTCON_USB, false);
extcon_set_cable_state_(data->edev, EXTCON_USB_HOST, true);
}
return IRQ_HANDLED;
}
static int max3355_probe(struct platform_device *pdev)
{
struct max3355_data *data;
struct gpio_desc *gpiod;
int irq, err;
data = devm_kzalloc(&pdev->dev, sizeof(struct max3355_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
if (IS_ERR(gpiod)) {
dev_err(&pdev->dev, "failed to get ID_OUT GPIO\n");
return PTR_ERR(gpiod);
}
data->id_gpiod = gpiod;
gpiod = devm_gpiod_get(&pdev->dev, "maxim,shdn", GPIOD_OUT_HIGH);
if (IS_ERR(gpiod)) {
dev_err(&pdev->dev, "failed to get SHDN# GPIO\n");
return PTR_ERR(gpiod);
}
data->shdn_gpiod = gpiod;
data->edev = devm_extcon_dev_allocate(&pdev->dev, max3355_cable);
if (IS_ERR(data->edev)) {
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return PTR_ERR(data->edev);
}
err = devm_extcon_dev_register(&pdev->dev, data->edev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register extcon device\n");
return err;
}
irq = gpiod_to_irq(data->id_gpiod);
if (irq < 0) {
dev_err(&pdev->dev, "failed to translate ID_OUT GPIO to IRQ\n");
return irq;
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL, max3355_id_irq,
IRQF_ONESHOT | IRQF_NO_SUSPEND |
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
pdev->name, data);
if (err < 0) {
dev_err(&pdev->dev, "failed to request ID_OUT IRQ\n");
return err;
}
platform_set_drvdata(pdev, data);
/* Perform initial detection */
max3355_id_irq(irq, data);
return 0;
}
static int max3355_remove(struct platform_device *pdev)
{
struct max3355_data *data = platform_get_drvdata(pdev);
gpiod_set_value_cansleep(data->shdn_gpiod, 0);
return 0;
}
static const struct of_device_id max3355_match_table[] = {
{ .compatible = "maxim,max3355", },
{ }
};
MODULE_DEVICE_TABLE(of, max3355_match_table);
static struct platform_driver max3355_driver = {
.probe = max3355_probe,
.remove = max3355_remove,
.driver = {
.name = "extcon-max3355",
.of_match_table = max3355_match_table,
},
};
module_platform_driver(max3355_driver);
MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
MODULE_DESCRIPTION("Maxim MAX3355 extcon driver");
MODULE_LICENSE("GPL v2");
......@@ -1127,11 +1127,11 @@ static int max77693_muic_probe(struct platform_device *pdev)
/* Support irq domain for MAX77693 MUIC device */
for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
struct max77693_muic_irq *muic_irq = &muic_irqs[i];
unsigned int virq = 0;
int virq;
virq = regmap_irq_get_virq(max77693->irq_data_muic,
muic_irq->irq);
if (!virq)
if (virq <= 0)
return -EINVAL;
muic_irq->virq = virq;
......
......@@ -811,7 +811,7 @@ static int max77843_muic_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
unsigned int virq = 0;
int virq = 0;
virq = regmap_irq_get_virq(max77843->irq_data_muic,
muic_irq->irq);
......
......@@ -603,7 +603,7 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
ret = devm_request_threaded_irq(info->dev, virq, NULL,
rt8973a_muic_irq_handler,
IRQF_NO_SUSPEND,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
muic_irq->name, info);
if (ret) {
dev_err(info->dev,
......
......@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/hyperv.h>
#include <linux/uio.h>
#include <linux/interrupt.h>
#include "hyperv_vmbus.h"
......@@ -496,8 +497,33 @@ static void reset_channel_cb(void *arg)
static int vmbus_close_internal(struct vmbus_channel *channel)
{
struct vmbus_channel_close_channel *msg;
struct tasklet_struct *tasklet;
int ret;
/*
* process_chn_event(), running in the tasklet, can race
* with vmbus_close_internal() in the case of SMP guest, e.g., when
* the former is accessing channel->inbound.ring_buffer, the latter
* could be freeing the ring_buffer pages.
*
* To resolve the race, we can serialize them by disabling the
* tasklet when the latter is running here.
*/
tasklet = hv_context.event_dpc[channel->target_cpu];
tasklet_disable(tasklet);
/*
* In case a device driver's probe() fails (e.g.,
* util_probe() -> vmbus_open() returns -ENOMEM) and the device is
* rescinded later (e.g., we dynamically disble an Integrated Service
* in Hyper-V Manager), the driver's remove() invokes vmbus_close():
* here we should skip most of the below cleanup work.
*/
if (channel->state != CHANNEL_OPENED_STATE) {
ret = -EINVAL;
goto out;
}
channel->state = CHANNEL_OPEN_STATE;
channel->sc_creation_callback = NULL;
/* Stop callback and cancel the timer asap */
......@@ -525,7 +551,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
* If we failed to post the close msg,
* it is perhaps better to leak memory.
*/
return ret;
goto out;
}
/* Tear down the gpadl for the channel's ring buffer */
......@@ -538,7 +564,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
* If we failed to teardown gpadl,
* it is perhaps better to leak memory.
*/
return ret;
goto out;
}
}
......@@ -549,12 +575,9 @@ 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);
out:
tasklet_enable(tasklet);
return ret;
}
......@@ -630,10 +653,19 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
* on the ring. We will not signal if more data is
* to be placed.
*
* Based on the channel signal state, we will decide
* which signaling policy will be applied.
*
* 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 (channel->signal_policy)
signal = true;
else
kick_q = true;
if (((ret == 0) && kick_q && signal) || (ret))
vmbus_setevent(channel);
......@@ -733,10 +765,19 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
* on the ring. We will not signal if more data is
* to be placed.
*
* Based on the channel signal state, we will decide
* which signaling policy will be applied.
*
* 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 (channel->signal_policy)
signal = true;
else
kick_q = true;
if (((ret == 0) && kick_q && signal) || (ret))
vmbus_setevent(channel);
......@@ -881,46 +922,29 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
*
* Mainly used by Hyper-V drivers.
*/
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
static inline int
__vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
bool raw)
{
struct vmpacket_descriptor desc;
u32 packetlen;
u32 userlen;
int ret;
bool signal = false;
*buffer_actual_len = 0;
*requestid = 0;
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
if (ret != 0)
return 0;
packetlen = desc.len8 << 3;
userlen = packetlen - (desc.offset8 << 3);
*buffer_actual_len = userlen;
if (userlen > bufferlen) {
pr_err("Buffer too small - got %d needs %d\n",
bufferlen, userlen);
return -ETOOSMALL;
}
*requestid = desc.trans_id;
/* Copy over the packet to the user buffer */
ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
(desc.offset8 << 3), &signal);
ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen,
buffer_actual_len, requestid, &signal, raw);
if (signal)
vmbus_setevent(channel);
return 0;
return ret;
}
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u32 *buffer_actual_len,
u64 *requestid)
{
return __vmbus_recvpacket(channel, buffer, bufferlen,
buffer_actual_len, requestid, false);
}
EXPORT_SYMBOL(vmbus_recvpacket);
......@@ -931,37 +955,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
u32 bufferlen, u32 *buffer_actual_len,
u64 *requestid)
{
struct vmpacket_descriptor desc;
u32 packetlen;
int ret;
bool signal = false;
*buffer_actual_len = 0;
*requestid = 0;
ret = hv_ringbuffer_peek(&channel->inbound, &desc,
sizeof(struct vmpacket_descriptor));
if (ret != 0)
return 0;
packetlen = desc.len8 << 3;
*buffer_actual_len = packetlen;
if (packetlen > bufferlen)
return -ENOBUFS;
*requestid = desc.trans_id;
/* Copy over the entire packet to the user buffer */
ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
&signal);
if (signal)
vmbus_setevent(channel);
return ret;
return __vmbus_recvpacket(channel, buffer, bufferlen,
buffer_actual_len, requestid, true);
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
......@@ -177,19 +177,24 @@ static void percpu_channel_deq(void *arg)
}
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
static void vmbus_release_relid(u32 relid)
{
struct vmbus_channel_relid_released msg;
unsigned long flags;
struct vmbus_channel *primary_channel;
memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
msg.child_relid = relid;
msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
}
if (channel == NULL)
return;
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
{
unsigned long flags;
struct vmbus_channel *primary_channel;