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

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

Pull char/misc patches from Greg KH:
 "Here is the big char/misc driver pull request for 3.12-rc1

  Lots of driver updates all over the char/misc tree, full details in
  the shortlog"

* tag 'char-misc-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (62 commits)
  drivers: uio: Kconfig: add MMU dependancy for UIO
  drivers: uio: Add driver for Humusoft MF624 DAQ PCI card
  drivers: uio_pdrv_genirq: use dev_get_platdata()
  drivers: uio_pruss: use dev_get_platdata()
  drivers: uio_dmem_genirq: use dev_get_platdata()
  drivers: parport: Kconfig: exclude h8300 for PARPORT_PC
  drivers: misc: ti-st: fix potential race if st_kim_start fails
  Drivers: hv: vmbus: Do not attempt to negoatiate a new version prematurely
  misc: vmw_balloon: Remove braces to fix build for clang.
  Drivers: hv: vmbus: Fix a bug in the handling of channel offers
  vme: vme_ca91cx42.c: fix to pass correct device identity to free_irq()
  VMCI: Add support for virtual IOMMU
  VMCI: Remove non-blocking/pinned queuepair support
  uio: uio_pruss: remove unnecessary platform_set_drvdata()
  parport: amiga: remove unnecessary platform_set_drvdata()
  vme: vme_vmivme7805.c: add missing __iomem annotation
  vme: vme_ca91cx42.c: add missing __iomem annotation
  vme: vme_tsi148.c: add missing __iomem annotation
  drivers/misc/hpilo: Correct panic when an AUX iLO is detected
  uio: drop unused vma_count member in uio_device struct
  ...
parents b3b49114 3cc1f952
EXTCON FOR TWL CHIPS EXTCON FOR PALMAS/TWL CHIPS
PALMAS USB COMPARATOR PALMAS USB COMPARATOR
Required Properties: Required Properties:
- compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb" - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb"
- vbus-supply : phandle to the regulator device tree node.
Optional Properties: Optional Properties:
- ti,wakeup : To enable the wakeup comparator in probe - ti,wakeup : To enable the wakeup comparator in probe
- ti,enable-id-detection: Perform ID detection.
- ti,enable-vbus-detection: Perform VBUS detection.
palmas-usb { palmas-usb {
compatible = "ti,twl6035-usb", "ti,palmas-usb"; compatible = "ti,twl6035-usb", "ti,palmas-usb";
vbus-supply = <&smps10_reg>;
ti,wakeup; ti,wakeup;
}; };
...@@ -53,6 +53,11 @@ OMAP DWC3 GLUE ...@@ -53,6 +53,11 @@ OMAP DWC3 GLUE
It should be set to "1" for HW mode and "2" for SW mode. It should be set to "1" for HW mode and "2" for SW mode.
- ranges: the child address space are mapped 1:1 onto the parent address space - ranges: the child address space are mapped 1:1 onto the parent address space
Optional Properties:
- extcon : phandle for the extcon device omap dwc3 uses to detect
connect/disconnect events.
- vbus-supply : phandle to the regulator device tree node if needed.
Sub-nodes: Sub-nodes:
The dwc3 core should be added as subnode to omap dwc3 glue. The dwc3 core should be added as subnode to omap dwc3 glue.
- dwc3 : - dwc3 :
......
...@@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) ...@@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
} }
count++; count++;
if (gis & (BIT1 + BIT0)) { if (gis & (BIT1 | BIT0)) {
isr = read_reg16(info, CHB + ISR); isr = read_reg16(info, CHB + ISR);
if (isr & IRQ_DCD) if (isr & IRQ_DCD)
dcd_change(info, tty); dcd_change(info, tty);
if (isr & IRQ_CTS) if (isr & IRQ_CTS)
cts_change(info, tty); cts_change(info, tty);
} }
if (gis & (BIT3 + BIT2)) if (gis & (BIT3 | BIT2))
{ {
isr = read_reg16(info, CHA + ISR); isr = read_reg16(info, CHA + ISR);
if (isr & IRQ_TIMER) { if (isr & IRQ_TIMER) {
...@@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) ...@@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
if (isr & IRQ_RXTIME) { if (isr & IRQ_RXTIME) {
issue_command(info, CHA, CMD_RXFIFO_READ); issue_command(info, CHA, CMD_RXFIFO_READ);
} }
if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) { if (isr & (IRQ_RXEOM | IRQ_RXFIFO)) {
if (info->params.mode == MGSL_MODE_HDLC) if (info->params.mode == MGSL_MODE_HDLC)
rx_ready_hdlc(info, isr & IRQ_RXEOM); rx_ready_hdlc(info, isr & IRQ_RXEOM);
else else
...@@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info) ...@@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info)
unsigned char val; unsigned char val;
/* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */ /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */
val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0); val = read_reg(info, CHA + CCR1) | (BIT2 | BIT1 | BIT0);
write_reg(info, CHA + CCR1, val); write_reg(info, CHA + CCR1, val);
/* CCR2:04 SSEL Clock source select, 1=submode b */ /* CCR2:04 SSEL Clock source select, 1=submode b */
val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5); val = read_reg(info, CHA + CCR2) | (BIT4 | BIT5);
write_reg(info, CHA + CCR2, val); write_reg(info, CHA + CCR2, val);
/* set LinkSpeed if available, otherwise default to 2Mbps */ /* set LinkSpeed if available, otherwise default to 2Mbps */
...@@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info) ...@@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info)
val |= BIT4; val |= BIT4;
break; // FM0 break; // FM0
case HDLC_ENCODING_BIPHASE_MARK: case HDLC_ENCODING_BIPHASE_MARK:
val |= BIT4 + BIT2; val |= BIT4 | BIT2;
break; // FM1 break; // FM1
case HDLC_ENCODING_BIPHASE_LEVEL: case HDLC_ENCODING_BIPHASE_LEVEL:
val |= BIT4 + BIT3; val |= BIT4 | BIT3;
break; // Manchester break; // Manchester
} }
write_reg(info, CHA + CCR0, val); write_reg(info, CHA + CCR0, val);
...@@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info) ...@@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
*/ */
val = 0x00; val = 0x00;
if (info->params.crc_type == HDLC_CRC_NONE) if (info->params.crc_type == HDLC_CRC_NONE)
val |= BIT2 + BIT1; val |= BIT2 | BIT1;
if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
val |= BIT5; val |= BIT5;
switch (info->params.preamble_length) switch (info->params.preamble_length)
...@@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info) ...@@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info)
val |= BIT6; val |= BIT6;
break; break;
case HDLC_PREAMBLE_LENGTH_64BITS: case HDLC_PREAMBLE_LENGTH_64BITS:
val |= BIT7 + BIT6; val |= BIT7 | BIT6;
break; break;
} }
write_reg(info, CHA + CCR3, val); write_reg(info, CHA + CCR3, val);
...@@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info) ...@@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info)
clear_reg_bits(info, CHA + PVR, BIT3); clear_reg_bits(info, CHA + PVR, BIT3);
irq_enable(info, CHA, irq_enable(info, CHA,
IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT + IRQ_RXEOM | IRQ_RXFIFO | IRQ_ALLSENT |
IRQ_UNDERRUN + IRQ_TXFIFO); IRQ_UNDERRUN | IRQ_TXFIFO);
issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
wait_command_complete(info, CHA); wait_command_complete(info, CHA);
read_reg16(info, CHA + ISR); /* clear pending IRQs */ read_reg16(info, CHA + ISR); /* clear pending IRQs */
...@@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info) ...@@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info)
} else } else
clear_reg_bits(info, CHA + PVR, BIT3); clear_reg_bits(info, CHA + PVR, BIT3);
irq_enable(info, CHA, irq_enable(info, CHA,
IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME + IRQ_RXEOM | IRQ_RXFIFO | IRQ_BREAK_ON | IRQ_RXTIME |
IRQ_ALLSENT + IRQ_TXFIFO); IRQ_ALLSENT | IRQ_TXFIFO);
issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET);
wait_command_complete(info, CHA); wait_command_complete(info, CHA);
read_reg16(info, CHA + ISR); /* clear pending IRQs */ read_reg16(info, CHA + ISR); /* clear pending IRQs */
......
...@@ -14,6 +14,10 @@ if EXTCON ...@@ -14,6 +14,10 @@ if EXTCON
comment "Extcon Device Drivers" comment "Extcon Device Drivers"
config OF_EXTCON
def_tristate y
depends on OF
config EXTCON_GPIO config EXTCON_GPIO
tristate "GPIO extcon support" tristate "GPIO extcon support"
depends on GPIOLIB depends on GPIOLIB
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# Makefile for external connector class (extcon) devices # Makefile for external connector class (extcon) devices
# #
obj-$(CONFIG_OF_EXTCON) += of_extcon.o
obj-$(CONFIG_EXTCON) += extcon-class.o obj-$(CONFIG_EXTCON) += extcon-class.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
......
...@@ -87,7 +87,8 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data) ...@@ -87,7 +87,8 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
{ {
struct adc_jack_data *data = _data; struct adc_jack_data *data = _data;
schedule_delayed_work(&data->handler, data->handling_delay); queue_delayed_work(system_power_efficient_wq,
&data->handler, data->handling_delay);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -890,8 +890,9 @@ static void arizona_micd_detect(struct work_struct *work) ...@@ -890,8 +890,9 @@ static void arizona_micd_detect(struct work_struct *work)
handled: handled:
if (info->detecting) if (info->detecting)
schedule_delayed_work(&info->micd_timeout_work, queue_delayed_work(system_power_efficient_wq,
msecs_to_jiffies(info->micd_timeout)); &info->micd_timeout_work,
msecs_to_jiffies(info->micd_timeout));
pm_runtime_mark_last_busy(info->dev); pm_runtime_mark_last_busy(info->dev);
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
...@@ -912,8 +913,9 @@ static irqreturn_t arizona_micdet(int irq, void *data) ...@@ -912,8 +913,9 @@ static irqreturn_t arizona_micdet(int irq, void *data)
mutex_unlock(&info->lock); mutex_unlock(&info->lock);
if (debounce) if (debounce)
schedule_delayed_work(&info->micd_detect_work, queue_delayed_work(system_power_efficient_wq,
msecs_to_jiffies(debounce)); &info->micd_detect_work,
msecs_to_jiffies(debounce));
else else
arizona_micd_detect(&info->micd_detect_work.work); arizona_micd_detect(&info->micd_detect_work.work);
...@@ -967,12 +969,14 @@ static irqreturn_t arizona_jackdet(int irq, void *data) ...@@ -967,12 +969,14 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
if (val == info->last_jackdet) { if (val == info->last_jackdet) {
dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n"); dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
if (cancelled_hp) if (cancelled_hp)
schedule_delayed_work(&info->hpdet_work, queue_delayed_work(system_power_efficient_wq,
msecs_to_jiffies(HPDET_DEBOUNCE)); &info->hpdet_work,
msecs_to_jiffies(HPDET_DEBOUNCE));
if (cancelled_mic) if (cancelled_mic)
schedule_delayed_work(&info->micd_timeout_work, queue_delayed_work(system_power_efficient_wq,
msecs_to_jiffies(info->micd_timeout)); &info->micd_timeout_work,
msecs_to_jiffies(info->micd_timeout));
goto out; goto out;
} }
...@@ -994,8 +998,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data) ...@@ -994,8 +998,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
arizona_start_mic(info); arizona_start_mic(info);
} else { } else {
schedule_delayed_work(&info->hpdet_work, queue_delayed_work(system_power_efficient_wq,
msecs_to_jiffies(HPDET_DEBOUNCE)); &info->hpdet_work,
msecs_to_jiffies(HPDET_DEBOUNCE));
} }
regmap_update_bits(arizona->regmap, regmap_update_bits(arizona->regmap,
......
...@@ -602,7 +602,8 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) ...@@ -602,7 +602,8 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
edev->dev->class = extcon_class; edev->dev->class = extcon_class;
edev->dev->release = extcon_dev_release; edev->dev->release = extcon_dev_release;
dev_set_name(edev->dev, "%s", edev->name ? edev->name : dev_name(dev)); edev->name = edev->name ? edev->name : dev_name(dev);
dev_set_name(edev->dev, "%s", edev->name);
if (edev->max_supported) { if (edev->max_supported) {
char buf[10]; char buf[10];
......
...@@ -56,7 +56,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) ...@@ -56,7 +56,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{ {
struct gpio_extcon_data *extcon_data = dev_id; struct gpio_extcon_data *extcon_data = dev_id;
schedule_delayed_work(&extcon_data->work, queue_delayed_work(system_power_efficient_wq, &extcon_data->work,
extcon_data->debounce_jiffies); extcon_data->debounce_jiffies);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) ...@@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
extcon_set_cable_state(&palmas_usb->edev, "USB", true); extcon_set_cable_state(&palmas_usb->edev, "USB", true);
dev_info(palmas_usb->dev, "USB cable is attached\n");
} else { } else {
dev_dbg(palmas_usb->dev, dev_dbg(palmas_usb->dev,
"Spurious connect event detected\n"); "Spurious connect event detected\n");
...@@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) ...@@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
extcon_set_cable_state(&palmas_usb->edev, "USB", false); extcon_set_cable_state(&palmas_usb->edev, "USB", false);
dev_info(palmas_usb->dev, "USB cable is detached\n");
} else { } else {
dev_dbg(palmas_usb->dev, dev_dbg(palmas_usb->dev,
"Spurious disconnect event detected\n"); "Spurious disconnect event detected\n");
...@@ -83,29 +85,24 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) ...@@ -83,29 +85,24 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
PALMAS_USB_ID_INT_LATCH_SET, &set); PALMAS_USB_ID_INT_LATCH_SET, &set);
if (set & PALMAS_USB_ID_INT_SRC_ID_GND) { if (set & PALMAS_USB_ID_INT_SRC_ID_GND) {
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_SET,
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_LATCH_CLR, PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
palmas_usb->linkstat = PALMAS_USB_STATE_ID; palmas_usb->linkstat = PALMAS_USB_STATE_ID;
extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
} else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) { } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) {
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_SET,
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_LATCH_CLR, PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
(!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -122,13 +119,17 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb) ...@@ -122,13 +119,17 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_SET, PALMAS_USB_ID_INT_EN_HI_SET,
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND); PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); if (palmas_usb->enable_vbus_detection)
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
/* cold plug for host mode needs this delay */ /* cold plug for host mode needs this delay */
msleep(30); if (palmas_usb->enable_id_detection) {
palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb); msleep(30);
palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
}
} }
static int palmas_usb_probe(struct platform_device *pdev) static int palmas_usb_probe(struct platform_device *pdev)
...@@ -139,21 +140,25 @@ static int palmas_usb_probe(struct platform_device *pdev) ...@@ -139,21 +140,25 @@ static int palmas_usb_probe(struct platform_device *pdev)
struct palmas_usb *palmas_usb; struct palmas_usb *palmas_usb;
int status; int status;
if (node && !pdata) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->wakeup = of_property_read_bool(node, "ti,wakeup");
} else if (!pdata) {
return -EINVAL;
}
palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL);
if (!palmas_usb) if (!palmas_usb)
return -ENOMEM; return -ENOMEM;
if (node && !pdata) {
palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup");
palmas_usb->enable_id_detection = of_property_read_bool(node,
"ti,enable-id-detection");
palmas_usb->enable_vbus_detection = of_property_read_bool(node,
"ti,enable-vbus-detection");
} else {
palmas_usb->wakeup = true;
palmas_usb->enable_id_detection = true;
palmas_usb->enable_vbus_detection = true;
if (pdata)
palmas_usb->wakeup = pdata->wakeup;
}
palmas->usb = palmas_usb; palmas->usb = palmas_usb;
palmas_usb->palmas = palmas; palmas_usb->palmas = palmas;
...@@ -168,11 +173,10 @@ static int palmas_usb_probe(struct platform_device *pdev) ...@@ -168,11 +173,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
PALMAS_VBUS_IRQ); PALMAS_VBUS_IRQ);
palmas_usb_wakeup(palmas, pdata->wakeup); palmas_usb_wakeup(palmas, palmas_usb->wakeup);
platform_set_drvdata(pdev, palmas_usb); platform_set_drvdata(pdev, palmas_usb);
palmas_usb->edev.name = "palmas-usb";
palmas_usb->edev.supported_cable = palmas_extcon_cable; palmas_usb->edev.supported_cable = palmas_extcon_cable;
palmas_usb->edev.mutually_exclusive = mutually_exclusive; palmas_usb->edev.mutually_exclusive = mutually_exclusive;
...@@ -182,28 +186,36 @@ static int palmas_usb_probe(struct platform_device *pdev) ...@@ -182,28 +186,36 @@ static int palmas_usb_probe(struct platform_device *pdev)
return status; return status;
} }
status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, if (palmas_usb->enable_id_detection) {
NULL, palmas_id_irq_handler, status = devm_request_threaded_irq(palmas_usb->dev,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, palmas_usb->id_irq,
"palmas_usb_id", palmas_usb); NULL, palmas_id_irq_handler,
if (status < 0) { IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", IRQF_ONESHOT | IRQF_EARLY_RESUME,
"palmas_usb_id", palmas_usb);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->id_irq, status); palmas_usb->id_irq, status);
goto fail_extcon; goto fail_extcon;
}
} }
status = devm_request_threaded_irq(palmas_usb->dev, if (palmas_usb->enable_vbus_detection) {
palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, status = devm_request_threaded_irq(palmas_usb->dev,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, palmas_usb->vbus_irq, NULL,
"palmas_usb_vbus", palmas_usb); palmas_vbus_irq_handler,
if (status < 0) { IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", IRQF_ONESHOT | IRQF_EARLY_RESUME,
"palmas_usb_vbus", palmas_usb);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->vbus_irq, status); palmas_usb->vbus_irq, status);
goto fail_extcon; goto fail_extcon;
}
} }
palmas_enable_irq(palmas_usb); palmas_enable_irq(palmas_usb);
device_set_wakeup_capable(&pdev->dev, true);
return 0; return 0;
fail_extcon: fail_extcon:
...@@ -221,6 +233,39 @@ static int palmas_usb_remove(struct platform_device *pdev) ...@@ -221,6 +233,39 @@ static int palmas_usb_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int palmas_usb_suspend(struct device *dev)
{
struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (palmas_usb->enable_vbus_detection)
enable_irq_wake(palmas_usb->vbus_irq);
if (palmas_usb->enable_id_detection)
enable_irq_wake(palmas_usb->id_irq);
}
return 0;
}
static int palmas_usb_resume(struct device *dev)
{
struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
if (palmas_usb->enable_vbus_detection)
disable_irq_wake(palmas_usb->vbus_irq);
if (palmas_usb->enable_id_detection)
disable_irq_wake(palmas_usb->id_irq);
}
return 0;
};
#endif
static const struct dev_pm_ops palmas_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(palmas_usb_suspend,
palmas_usb_resume)
};
static struct of_device_id of_palmas_match_tbl[] = { static struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas-usb", }, { .compatible = "ti,palmas-usb", },
{ .compatible = "ti,twl6035-usb", }, { .compatible = "ti,twl6035-usb", },
...@@ -234,6 +279,7 @@ static struct platform_driver palmas_usb_driver = { ...@@ -234,6 +279,7 @@ static struct platform_driver palmas_usb_driver = {
.name = "palmas-usb", .name = "palmas-usb",
.of_match_table = of_palmas_match_tbl, .of_match_table = of_palmas_match_tbl,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &palmas_pm_ops,
}, },
}; };
......
/*
* OF helpers for External connector (extcon) framework
*
* Copyright (C) 2013 Texas Instruments, Inc.
* Kishon Vijay Abraham I <kishon@ti.com>
*
* Copyright (C) 2013 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/extcon.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/extcon/of_extcon.h>
/*
* of_extcon_get_extcon_dev - Get the name of extcon device from devicetree
* @dev - instance to the given device
* @index - index into list of extcon_dev
*
* return the instance of extcon device
*/
struct extcon_dev *of_extcon_get_extcon_dev(struct device *dev, int index)
{
struct device_node *node;
struct extcon_dev *edev;
struct platform_device *extcon_parent_dev;
if (!dev->of_node) {
dev_dbg(dev, "device does not have a device node entry\n");
return ERR_PTR(-EINVAL);
}
node = of_parse_phandle(dev->of_node, "extcon", index);
if (!node) {
dev_dbg(dev, "failed to get phandle in %s node\n",
dev->of_node->full_name);
return ERR_PTR(-ENODEV);
}
extcon_parent_dev = of_find_device_by_node(node);
if (!extcon_parent_dev) {
dev_dbg(dev, "unable to find device by node\n");
return ERR_PTR(-EPROBE_DEFER);
}
edev = extcon_get_extcon_dev(dev_name(&extcon_parent_dev->dev));
if (!edev) {
dev_dbg(dev, "unable to get extcon device : %s\n",
dev_name(&extcon_parent_dev->dev));
return ERR_PTR(-ENODEV);
}
return edev;
}
EXPORT_SYMBOL_GPL(of_extcon_get_extcon_dev);
...@@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc) ...@@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc)
fc->misc.fops = &fc_fops; fc->misc.fops = &fc_fops;
fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL);
spin_lock(&fc_lock);
ret = misc_register(&fc->misc); ret = misc_register(&fc->misc);
if (ret < 0) if (ret < 0)
goto err_unlock; goto out;
spin_lock(&fc_lock);
list_add(&fc->list, &fc_devices); list_add(&fc->list, &fc_devices);
spin_unlock(&fc_lock); spin_unlock(&fc_lock);
dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n",
fc->misc.name); fc->misc.name);
return 0; return 0;
err_unlock: out:
spin_unlock(&fc_lock);
kfree(fc->misc.name); kfree(fc->misc.name);
kfree(fc); kfree(fc);
return ret; return ret;
...@@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc) ...@@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc)
spin_lock(&fc_lock); spin_lock(&fc_lock);
list_del(&fc->list); list_del(&fc->list);
spin_unlock(&fc_lock);
misc_deregister(&fc->misc); misc_deregister(&fc->misc);
kfree(fc->misc.name); kfree(fc->misc.name);
kfree(fc); kfree(fc);
spin_unlock(&fc_lock);
return 0; return 0;
} }
......
...@@ -103,7 +103,7 @@ static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s) ...@@ -103,7 +103,7 @@ static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s)
* difficult to know in advance when probing the first card if others * difficult to know in advance when probing the first card if others
* are there. * are there.
*/ */
int fwe_probe(struct fmc_device *fmc) static int fwe_probe(struct fmc_device *fmc)
{ {
int err, index = 0; int err, index = 0;
const struct firmware *fw; const struct firmware *fw;
...@@ -144,7 +144,7 @@ int fwe_probe(struct fmc_device *fmc) ...@@ -144,7 +144,7 @@ int fwe_probe(struct fmc_device *fmc)
return 0; return 0;
} }
int fwe_remove(struct fmc_device *fmc) static int fwe_remove(struct fmc_device *fmc)
{ {
return 0; return 0;
} }
......
...@@ -590,6 +590,5 @@ static void __exit mousevsc_exit(void) ...@@ -590,6 +590,5 @@ static void __exit mousevsc_exit(void)
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
module_init(mousevsc_init); module_init(mousevsc_init);
module_exit(mousevsc_exit); module_exit(mousevsc_exit);
...@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry { ...@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry {
* @negop is of type &struct icmsg_negotiate. * @negop is of type &struct icmsg_negotiate.
* Set up and fill in default negotiate response message. * Set up and fill in default negotiate response message.
* *
* The max_fw_version specifies the maximum framework version that * The fw_version specifies the framework version that
* we can support and max _srv_version specifies the maximum service * we can support and srv_version specifies the service
* version we can support. A special value MAX_SRV_VER can be * version we can support.
* specified to indicate that we can handle the maximum version
* exposed by the host.
* *
* Mainly used by Hyper-V drivers. * Mainly used by Hyper-V drivers.
*/ */
void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
struct icmsg_negotiate *negop, u8 *buf, struct icmsg_negotiate *negop, u8 *buf,
int max_fw_version, int max_srv_version) int fw_version, int srv_version)
{ {
int icframe_vercnt; int icframe_major, icframe_minor;
int icmsg_vercnt; int icmsg_major, icmsg_minor;
int fw_major, fw_minor;
int srv_major, srv_minor;
int i; int i;
bool found_match = false;
icmsghdrp->icmsgsize = 0x10; icmsghdrp->icmsgsize = 0x10;
fw_major = (fw_version >> 16);
fw_minor = (fw_version & 0xFFFF);
srv_major = (srv_version >> 16);
srv_minor = (srv_version & 0xFFFF);
negop = (struct icmsg_negotiate *)&buf[ negop = (struct icmsg_negotiate *)&buf[
sizeof(struct vmbuspipe_hdr) + sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)]; sizeof(struct icmsg_hdr)];
icframe_vercnt = negop->icframe_vercnt; icframe_major = negop->icframe_vercnt;
icmsg_vercnt = negop->icmsg_vercnt; icframe_minor = 0;
icmsg_major = negop->icmsg_vercnt;
icmsg_minor = 0;
/* /*
* Select the framework version number we will * Select the framework version number we will
...@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, ...@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
*/ */
for (i = 0; i < negop->icframe_vercnt; i++) { for (i = 0; i < negop->icframe_vercnt; i++) {
if (negop->icversion_data[i].major <= max_fw_version) if ((negop->icversion_data[i].major == fw_major) &&
icframe_vercnt = negop->icversion_data[i].major; (negop->icversion_data[i].minor == fw_minor)) {
icframe_major = negop->icversion_data[i].major;
icframe_minor = negop->icversion_data[i].minor;
found_match = true;
}
} }
if (!found_match)
goto fw_error;
found_match = false;
for (i = negop->icframe_vercnt; for (i = negop->icframe_vercnt;
(i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) {
if (negop->icversion_data[i].major <= max_srv_version) if ((negop->icversion_data[i].major == srv_major) &&
icmsg_vercnt = negop->icversion_data[i].major; (negop->icversion_data[i].minor == srv_minor)) {
icmsg_major = negop->icversion_data[i].major;
icmsg_minor = negop->icversion_data[i].minor;
found_match = true;
}
} }
/* /*
* Respond with the maximum framework and service * Respond with the framework and service
* version numbers we can support. * version numbers we can support.
*/ */
negop->icframe_vercnt = 1;
negop->icmsg_vercnt = 1; fw_error:
negop->icversion_data[0].major = icframe_vercnt; if (!found_match) {
negop->icversion_data[0].minor = 0; negop->icframe_vercnt = 0;
negop->icversion_data[1].major = icmsg_vercnt; negop->icmsg_vercnt = 0;
negop->icversion_data[1].minor = 0; } else {
negop->icframe_vercnt = 1;
negop->icmsg_vercnt = 1;
}
negop->icversion_data[0].major = icframe_major;
negop->icversion_data[0].minor = icframe_minor;
negop->icversion_data[1].major = icmsg_major;
negop->icversion_data[1].minor = icmsg_minor;
return found_match;
} }
EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
...@@ -261,6 +292,13 @@ static void vmbus_process_offer(struct work_struct *work) ...@@ -261,6 +292,13 @@ static void vmbus_process_offer(struct work_struct *work)
return; return;
} }
/*
* This state is used to indicate a successful open
* so that when we do close the channel normally, we
* can cleanup properly
*/
newchannel->state = CHANNEL_OPEN_STATE;
/* /*
* Start the process of binding this offer to the driver * Start the process of binding this offer to the driver
* We need to set the DeviceObject field before calling * We need to set the DeviceObject field before calling
...@@ -287,13 +325,6 @@ static void vmbus_process_offer(struct work_struct *work) ...@@ -287,13 +325,6 @@ static void vmbus_process_offer(struct work_struct *work)
kfree(newchannel->device_obj); kfree(newchannel->device_obj);
free_channel(newchannel); free_channel(newchannel);
} else {
/*
* This state is used to indicate a successful open
* so that when we do close the channel normally, we
* can cleanup properly
*/
newchannel->state = CHANNEL_OPEN_STATE;
} }
} }
......
...@@ -195,7 +195,10 @@ int vmbus_connect(void) ...@@ -195,7 +195,10 @@ int vmbus_connect(void)
do { do {
ret = vmbus_negotiate_version(msginfo, version); ret = vmbus_negotiate_version(msginfo, version);
if (ret == 0) if (ret)
goto cleanup;
if (vmbus_connection.conn_state == CONNECTED)
break; break;
version = vmbus_get_next_version(version); version = vmbus_get_next_version(version);
......
...@@ -825,7 +825,6 @@ static void hot_add_req(struct work_struct *dummy) ...@@ -825,7 +825,6 @@ static void hot_add_req(struct work_struct *dummy)
memset(&resp, 0, sizeof(struct dm_hot_add_response)); memset(&resp, 0, sizeof(struct dm_hot_add_response));
resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE; resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE;
resp.hdr.size = sizeof(struct dm_hot_add_response); resp.hdr.size = sizeof(struct dm_hot_add_response);
resp.hdr.trans_id = atomic_inc_return(&trans_id);
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG
pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; pg_start = dm->ha_wrk.ha_page_range.finfo.start_page;
...@@ -887,6 +886,7 @@ static void hot_add_req(struct work_struct *dummy) ...@@ -887,6 +886,7 @@ static void hot_add_req(struct work_struct *dummy)
pr_info("Memory hot add failed\n"); pr_info("Memory hot add failed\n");
dm->state = DM_INITIALIZED; dm->state = DM_INITIALIZED;
resp.hdr.trans_id = atomic_inc_return(&trans_id);
vmbus_sendpacket(dm->dev->channel, &resp, vmbus_sendpacket(dm->dev->channel, &resp,
sizeof(struct dm_hot_add_response), sizeof(struct dm_hot_add_response),
(unsigned long)NULL, (unsigned long)NULL,
...@@ -1081,7 +1081,6 @@ static void balloon_up(struct work_struct *dummy) ...@@ -1081,7 +1081,6 @@ static void balloon_up(struct work_struct *dummy)
bl_resp = (struct dm_balloon_response *)send_buffer; bl_resp = (struct dm_balloon_response *)send_buffer;
memset(send_buffer, 0, PAGE_SIZE); memset(send_buffer, 0, PAGE_SIZE);
bl_resp->hdr.type = DM_BALLOON_RESPONSE; bl_resp->hdr.type = DM_BALLOON_RESPONSE;
bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
bl_resp->hdr.size = sizeof(struct dm_balloon_response); bl_resp->hdr.size = sizeof(struct dm_balloon_response);
bl_resp->more_pages = 1; bl_resp->more_pages = 1;
...@@ -1109,6 +1108,7 @@ static void balloon_up(struct work_struct *dummy) ...@@ -1109,6 +1108,7 @@ static void balloon_up(struct work_struct *dummy)
*/ */
do { do {
bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
ret = vmbus_sendpacket(dm_device.dev->channel, ret = vmbus_sendpacket(dm_device.dev->channel,
bl_resp, bl_resp,
bl_resp->hdr.size, bl_resp->hdr.size,
...@@ -1526,5 +1526,4 @@ static int __init init_balloon_drv(void) ...@@ -1526,5 +1526,4 @@ static int __init init_balloon_drv(void)
module_init(init_balloon_drv); module_init(init_balloon_drv);
MODULE_DESCRIPTION("Hyper-V Balloon"); MODULE_DESCRIPTION("Hyper-V Balloon");
MODULE_VERSION(HV_DRV_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -29,6 +29,16 @@ ...@@ -29,6 +29,16 @@
#include <linux/hyperv.h> #include <linux/hyperv.h>
/*
* Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
*/
#define WIN7_SRV_MAJOR 3
#define WIN7_SRV_MINOR 0
#define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
#define WIN8_SRV_MAJOR 4
#define WIN8_SRV_MINOR 0
#define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
/* /*
* Global state maintained for transaction that is being processed. * Global state maintained for transaction that is being processed.
...@@ -76,7 +86,9 @@ static u8 *recv_buffer; ...@@ -76,7 +86,9 @@ static u8 *recv_buffer;
/* /*
* Register the kernel component with the user-level daemon. * Register the kernel component with the user-level daemon.
* As part of this registration, pass the LIC version number. * As part of this registration, pass the LIC version number.
* This number has no meaning, it satisfies the registration protocol.
*/ */
#define HV_DRV_VERSION "3.1"
static void static void
kvp_register(int reg_value) kvp_register(int reg_value)
...@@ -593,8 +605,19 @@ void hv_kvp_onchannelcallback(void *context) ...@@ -593,8 +605,19 @@ void hv_kvp_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)]; sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
/*
* We start with win8 version and if the host cannot
* support that we use the previous version.
*/
if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
recv_buffer, UTIL_FW_MAJOR_MINOR,
WIN8_SRV_MAJOR_MINOR))
goto done;
vmbus_prep_negotiate_resp(icmsghdrp, negop, vmbus_prep_negotiate_resp(icmsghdrp, negop,
recv_buffer, MAX_SRV_VER, MAX_SRV_VER); recv_buffer, UTIL_FW_MAJOR_MINOR,
WIN7_SRV_MAJOR_MINOR);
} else { } else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) + sizeof(struct vmbuspipe_hdr) +
...@@ -626,6 +649,7 @@ void hv_kvp_onchannelcallback(void *context) ...@@ -626,6 +649,7 @@ void hv_kvp_onchannelcallback(void *context)
return; return;
} }
done:
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE; | ICMSGHDRFLAG_RESPONSE;
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/hyperv.h> #include <linux/hyperv.h>
#define VSS_MAJOR 5
#define VSS_MINOR 0
#define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR)
/* /*
...@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context) ...@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, negop, vmbus_prep_negotiate_resp(icmsghdrp, negop,
recv_buffer, MAX_SRV_VER, MAX_SRV_VER); recv_buffer, UTIL_FW_MAJOR_MINOR,
/* VSS_MAJOR_MINOR);
* We currently negotiate the highest number the
* host has presented. If this version is not
* atleast 5.0, reject.
*/
negop = (struct icmsg_negotiate *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)];
if (negop->icversion_data[1].major < 5)
negop->icframe_vercnt = 0;
} else { } else {
vss_msg = (struct hv_vss_msg *)&recv_buffer[ vss_msg = (struct hv_vss_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) + sizeof(struct vmbuspipe_hdr) +
......
...@@ -28,6 +28,18 @@ ...@@ -28,6 +28,18 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/hyperv.h> #include <linux/hyperv.h>
#define SHUTDOWN_MAJOR 3
#define SHUTDOWN_MINOR 0
#define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR)
#define TIMESYNCH_MAJOR 3
#define TIMESYNCH_MINOR 0
#define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR)
#define HEARTBEAT_MAJOR 3
#define HEARTBEAT_MINOR 0
#define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR)
static void shutdown_onchannelcallback(void *context); static void shutdown_onchannelcallback(void *context);
static struct hv_util_service util_shutdown = { static struct hv_util_service util_shutdown = {
.util_cb = shutdown_onchannelcallback, .util_cb = shutdown_onchannelcallback,
...@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context) ...@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, negop, vmbus_prep_negotiate_resp(icmsghdrp, negop,
shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); shut_txf_buf, UTIL_FW_MAJOR_MINOR,
SHUTDOWN_MAJOR_MINOR);
} else { } else {
shutdown_msg = shutdown_msg =
(struct shutdown_msg_data *)&shut_txf_buf[ (struct shutdown_msg_data *)&shut_txf_buf[
...@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context) ...@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
MAX_SRV_VER, MAX_SRV_VER); UTIL_FW_MAJOR_MINOR,
TIMESYNCH_MAJOR_MINOR);
} else { } else {
timedatap = (struct ictimesync_data *)&time_txf_buf[ timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) + sizeof(struct vmbuspipe_hdr) +
...@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context) ...@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, NULL, vmbus_prep_negotiate_resp(icmsghdrp, NULL,
hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); hbeat_txf_buf, UTIL_FW_MAJOR_MINOR,
HEARTBEAT_MAJOR_MINOR);
} else { } else {
heartbeat_msg = heartbeat_msg =
(struct heartbeat_msg_data *)&hbeat_txf_buf[ (struct heartbeat_msg_data *)&hbeat_txf_buf[
...@@ -380,5 +395,4 @@ module_init(init_hyperv_utils); ...@@ -380,5 +395,4 @@ module_init(init_hyperv_utils);
module_exit(exit_hyperv_utils); module_exit(exit_hyperv_utils);
MODULE_DESCRIPTION("Hyper-V Utilities"); MODULE_DESCRIPTION("Hyper-V Utilities");
MODULE_VERSION(HV_DRV_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -816,7 +816,6 @@ static void __exit vmbus_exit(void) ...@@ -816,7 +816,6 @@ static void __exit vmbus_exit(void)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
subsys_initcall(hv_acpi_init); subsys_initcall(hv_acpi_init);
module_exit(vmbus_exit); module_exit(vmbus_exit);
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/consumer.h>
/* Serialize access to ssc_list and user count */ /* Serialize access to ssc_list and user count */
static DEFINE_SPINLOCK(user_lock); static DEFINE_SPINLOCK(user_lock);
...@@ -137,13 +136,6 @@ static int ssc_probe(struct platform_device *pdev) ...@@ -137,13 +136,6 @@ static int ssc_probe(struct platform_device *pdev)
struct resource *regs; struct resource *regs;
struct ssc_device *ssc; struct ssc_device *ssc;
const struct atmel_ssc_platform_data *plat_dat; const struct atmel_ssc_platform_data *plat_dat;
struct pinctrl *pinctrl;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
dev_err(&pdev->dev, "Failed to request pinctrl\n");
return PTR_ERR(pinctrl);
}
ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
if (!ssc) { if (!ssc) {
......
...@@ -759,7 +759,7 @@ static int ilo_probe(struct pci_dev *pdev, ...@@ -759,7 +759,7 @@ static int ilo_probe(struct pci_dev *pdev,
/* Ignore subsystem_device = 0x1979 (set by BIOS) */ /* Ignore subsystem_device = 0x1979 (set by BIOS) */
if (pdev->subsystem_device == 0x1979) if (pdev->subsystem_device == 0x1979)
goto out; return 0;
if (max_ccb > MAX_CCB) if (max_ccb > MAX_CCB)
max_ccb = MAX_CCB; max_ccb = MAX_CCB;
...@@ -899,7 +899,7 @@ static void __exit ilo_exit(void) ...@@ -899,7 +899,7 @@ static void __exit ilo_exit(void)
class_destroy(ilo_class); class_destroy(ilo_class);
} }
MODULE_VERSION("1.4"); MODULE_VERSION("1.4.1");
MODULE_ALIAS(ILO_NAME); MODULE_ALIAS(ILO_NAME);
MODULE_DESCRIPTION(ILO_NAME); MODULE_DESCRIPTION(ILO_NAME);
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/vmalloc.h>
#ifdef CONFIG_IDE #ifdef CONFIG_IDE
#include <linux/ide.h> #include <linux/ide.h>
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
#define DEFAULT_COUNT 10 #define DEFAULT_COUNT 10
#define REC_NUM_DEFAULT 10 #define REC_NUM_DEFAULT 10
#define EXEC_SIZE 64
enum cname { enum cname {
CN_INVALID, CN_INVALID,
...@@ -68,6 +70,7 @@ enum ctype { ...@@ -68,6 +70,7 @@ enum ctype {
CT_NONE, CT_NONE,
CT_PANIC, CT_PANIC,
CT_BUG, CT_BUG,
CT_WARNING,
CT_EXCEPTION, CT_EXCEPTION,
CT_LOOP, CT_LOOP,
CT_OVERFLOW, CT_OVERFLOW,
...@@ -77,7 +80,12 @@ enum ctype { ...@@ -77,7 +80,12 @@ enum ctype {
CT_WRITE_AFTER_FREE, CT_WRITE_AFTER_FREE,
CT_SOFTLOCKUP, CT_SOFTLOCKUP,
CT_HARDLOCKUP, CT_HARDLOCKUP,
CT_SPINLOCKUP,
CT_HUNG_TASK, CT_HUNG_TASK,
CT_EXEC_DATA,
CT_EXEC_STACK,
CT_EXEC_KMALLOC,
CT_EXEC_VMALLOC,
}; };
static char* cp_name[] = { static char* cp_name[] = {
...@@ -95,6 +103,7 @@ static char* cp_name[] = { ...@@ -95,6 +103,7 @@ static char* cp_name[] = {
static char* cp_type[] = { static char* cp_type[] = {
"PANIC", "PANIC",
"BUG", "BUG",
"WARNING",
"EXCEPTION", "EXCEPTION",
"LOOP", "LOOP",
"OVERFLOW", "OVERFLOW",
...@@ -104,7 +113,12 @@ static char* cp_type[] = { ...@@ -104,7 +113,12 @@ static char* cp_type[] = {
"WRITE_AFTER_FREE", "WRITE_AFTER_FREE",
"SOFTLOCKUP", "SOFTLOCKUP",
"HARDLOCKUP", "HARDLOCKUP",
"SPINLOCKUP",
"HUNG_TASK", "HUNG_TASK",
"EXEC_DATA",
"EXEC_STACK",
"EXEC_KMALLOC",
"EXEC_VMALLOC",
}; };
static struct jprobe lkdtm; static struct jprobe lkdtm;
...@@ -121,6 +135,9 @@ static enum cname cpoint = CN_INVALID; ...@@ -121,6 +135,9 @@ static enum cname cpoint = CN_INVALID;
static enum ctype cptype = CT_NONE; static enum ctype cptype = CT_NONE;
static int count = DEFAULT_COUNT; static int count = DEFAULT_COUNT;
static DEFINE_SPINLOCK(count_lock); static DEFINE_SPINLOCK(count_lock);
static DEFINE_SPINLOCK(lock_me_up);
static u8 data_area[EXEC_SIZE];
module_param(recur_count, int, 0644); module_param(recur_count, int, 0644);
MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
...@@ -275,6 +292,19 @@ static int recursive_loop(int a) ...@@ -275,6 +292,19 @@ static int recursive_loop(int a)
return recursive_loop(a); return recursive_loop(a);
} }
static void do_nothing(void)
{
return;
}
static void execute_location(void *dst)
{
void (*func)(void) = dst;
memcpy(dst, do_nothing, EXEC_SIZE);
func();
}
static void lkdtm_do_action(enum ctype which) static void lkdtm_do_action(enum ctype which)
{ {
switch (which) { switch (which) {
...@@ -284,6 +314,9 @@ static void lkdtm_do_action(enum ctype which) ...@@ -284,6 +314,9 @@ static void lkdtm_do_action(enum ctype which)
case CT_BUG: case CT_BUG:
BUG(); BUG();
break; break;
case CT_WARNING:
WARN_ON(1);
break;
case CT_EXCEPTION: case CT_EXCEPTION:
*((int *) 0) = 0; *((int *) 0) = 0;
break; break;
...@@ -295,10 +328,10 @@ static void lkdtm_do_action(enum ctype which) ...@@ -295,10 +328,10 @@ static void lkdtm_do_action(enum ctype which)
(void) recursive_loop(0); (void) recursive_loop(0);
break; break;
case CT_CORRUPT_STACK: { case CT_CORRUPT_STACK: {
volatile u32 data[8]; /* Make sure the compiler creates and uses an 8 char array. */
volatile u32 *p = data; volatile char data[8];
p[12] = 0x12345678; memset((void *)data, 0, 64);
break; break;
} }
case CT_UNALIGNED_LOAD_STORE_WRITE: { case CT_UNALIGNED_LOAD_STORE_WRITE: {
...@@ -340,10 +373,34 @@ static void lkdtm_do_action(enum ctype which) ...@@ -340,10 +373,34 @@ static void lkdtm_do_action(enum ctype which)
for (;;) for (;;)
cpu_relax(); cpu_relax();
break; break;
case CT_SPINLOCKUP:
/* Must be called twice to trigger. */
spin_lock(&lock_me_up);
break;
case CT_HUNG_TASK: case CT_HUNG_TASK:
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule(); schedule();
break; break;
case CT_EXEC_DATA:
execute_location(data_area);
break;
case CT_EXEC_STACK: {
u8 stack_area[EXEC_SIZE];
execute_location(stack_area);
break;
}
case CT_EXEC_KMALLOC: {
u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL);
execute_location(kmalloc_area);
kfree(kmalloc_area);
break;
}
case CT_EXEC_VMALLOC: {
u32 *vmalloc_area = vmalloc(EXEC_SIZE);
execute_location(vmalloc_area);
vfree(vmalloc_area);
break;
}
case CT_NONE: case CT_NONE:
default: default:
break; break;
......
...@@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev, ...@@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
struct file *file, poll_table *wait) struct file *file, poll_table *wait)
{ {
unsigned int mask = 0; unsigned int mask = 0;
mutex_unlock(&dev->device_lock);
poll_wait(file, &dev->iamthif_cl.wait, wait); poll_wait(file, &dev->iamthif_cl.wait, wait);
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && if (!mei_cl_is_connected(&dev->iamthif_cl)) {
dev->iamthif_file_object == file) {
mask = POLLERR;
} else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
dev->iamthif_file_object == file) {
mask |= (POLLIN | POLLRDNORM); mask |= (POLLIN | POLLRDNORM);
dev_dbg(&dev->pdev->dev, "run next amthif cb\n"); dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
mei_amthif_run_next_cmd(dev); mei_amthif_run_next_cmd(dev);
} }
mutex_unlock(&dev->device_lock);
return mask; return mask;
} }
......
...@@ -47,7 +47,7 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv) ...@@ -47,7 +47,7 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
id = driver->id_table; id = driver->id_table;
while (id->name[0]) { while (id->name[0]) {
if (!strcmp(dev_name(dev), id->name)) if (!strncmp(dev_name(dev), id->name, sizeof(id->name)))
return 1; return 1;
id++; id++;
...@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev) ...@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev)
dev_dbg(dev, "Device probe\n"); dev_dbg(dev, "Device probe\n");
strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE); strncpy(id.name, dev_name(dev), sizeof(id.name));
return driver->probe(device, &id); return driver->probe(device, &id);
} }
......
...@@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) ...@@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
dev = cl->dev; dev = cl->dev;
if (cl->state != MEI_FILE_CONNECTED) if (!mei_cl_is_connected(cl))
return -ENODEV;
if (dev->dev_state != MEI_DEV_ENABLED)
return -ENODEV; return -ENODEV;
if (cl->read_cb) { if (cl->read_cb) {
...@@ -892,18 +889,22 @@ void mei_cl_all_disconnect(struct mei_device *dev) ...@@ -892,18 +889,22 @@ void mei_cl_all_disconnect(struct mei_device *dev)
/** /**
* mei_cl_all_read_wakeup - wake up all readings so they can be interrupted * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted
* *
* @dev - mei device * @dev - mei device
*/ */
void mei_cl_all_read_wakeup(struct mei_device *dev) void mei_cl_all_wakeup(struct mei_device *dev)
{ {
struct mei_cl *cl, *next; struct mei_cl *cl, *next;
list_for_each_entry_safe(cl, next, &dev->file_list, link) { list_for_each_entry_safe(cl, next, &dev->file_list, link) {
if (waitqueue_active(&cl->rx_wait)) { if (waitqueue_active(&cl->rx_wait)) {
dev_dbg(&dev->pdev->dev, "Waking up client!\n"); dev_dbg(&dev->pdev->dev, "Waking up reading client!\n");
wake_up_interruptible(&cl->rx_wait); wake_up_interruptible(&cl->rx_wait);
} }
if (waitqueue_active(&cl->tx_wait)) {
dev_dbg(&dev->pdev->dev, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
} }
} }
......
...@@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); ...@@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
/* /*
* MEI input output function prototype * MEI input output function prototype
*/ */
static inline bool mei_cl_is_connected(struct mei_cl *cl)
{
return (cl->dev &&
cl->dev->dev_state == MEI_DEV_ENABLED &&
cl->state == MEI_FILE_CONNECTED);
}
bool mei_cl_is_other_connecting(struct mei_cl *cl); bool mei_cl_is_other_connecting(struct mei_cl *cl);
int mei_cl_disconnect(struct mei_cl *cl); int mei_cl_disconnect(struct mei_cl *cl);
int mei_cl_connect(struct mei_cl *cl, struct file *file); int mei_cl_connect(struct mei_cl *cl, struct file *file);
...@@ -99,7 +106,7 @@ void mei_host_client_init(struct work_struct *work); ...@@ -99,7 +106,7 @@ void mei_host_client_init(struct work_struct *work);
void mei_cl_all_disconnect(struct mei_device *dev); void mei_cl_all_disconnect(struct mei_device *dev);
void mei_cl_all_read_wakeup(struct mei_device *dev); void mei_cl_all_wakeup(struct mei_device *dev);
void mei_cl_all_write_clear(struct mei_device *dev); void mei_cl_all_write_clear(struct mei_device *dev);
#endif /* _MEI_CLIENT_H_ */ #endif /* _MEI_CLIENT_H_ */
...@@ -176,21 +176,18 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) ...@@ -176,21 +176,18 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
struct mei_me_hw *hw = to_me_hw(dev); struct mei_me_hw *hw = to_me_hw(dev);
u32 hcsr = mei_hcsr_read(hw); u32 hcsr = mei_hcsr_read(hw);
dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); hcsr |= H_RST | H_IG | H_IS;
hcsr |= (H_RST | H_IG);
if (intr_enable) if (intr_enable)
hcsr |= H_IE; hcsr |= H_IE;
else else
hcsr |= ~H_IE; hcsr &= ~H_IE;
mei_hcsr_set(hw, hcsr); mei_me_reg_write(hw, H_CSR, hcsr);
if (dev->dev_state == MEI_DEV_POWER_DOWN) if (dev->dev_state == MEI_DEV_POWER_DOWN)
mei_me_hw_reset_release(dev); mei_me_hw_reset_release(dev);
dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw));
return 0; return 0;
} }
......
...@@ -154,8 +154,14 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -154,8 +154,14 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->dev_state != MEI_DEV_POWER_DOWN) dev->dev_state != MEI_DEV_POWER_DOWN)
dev->dev_state = MEI_DEV_RESETTING; dev->dev_state = MEI_DEV_RESETTING;
/* remove all waiting requests */
mei_cl_all_write_clear(dev);
mei_cl_all_disconnect(dev); mei_cl_all_disconnect(dev);
/* wake up all readings so they can be interrupted */
mei_cl_all_wakeup(dev);
/* remove entry if already in list */ /* remove entry if already in list */
dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
mei_cl_unlink(&dev->wd_cl); mei_cl_unlink(&dev->wd_cl);
...@@ -196,11 +202,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -196,11 +202,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
mei_hbm_start_req(dev); mei_hbm_start_req(dev);
/* wake up all readings so they can be interrupted */
mei_cl_all_read_wakeup(dev);
/* remove all waiting requests */
mei_cl_all_write_clear(dev);
} }
EXPORT_SYMBOL_GPL(mei_reset); EXPORT_SYMBOL_GPL(mei_reset);
......
...@@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) ...@@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
unsigned int mask = 0; unsigned int mask = 0;
if (WARN_ON(!cl || !cl->dev)) if (WARN_ON(!cl || !cl->dev))
return mask; return POLLERR;
dev = cl->dev; dev = cl->dev;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->dev_state != MEI_DEV_ENABLED) if (!mei_cl_is_connected(cl)) {
goto out; mask = POLLERR;
if (cl == &dev->iamthif_cl) {
mask = mei_amthif_poll(dev, file, wait);
goto out; goto out;
} }
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
if (cl == &dev->iamthif_cl)
return mei_amthif_poll(dev, file, wait);
poll_wait(file, &cl->tx_wait, wait); poll_wait(file, &cl->tx_wait, wait);
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (!mei_cl_is_connected(cl)) {
mask = POLLERR;
goto out;
}
if (MEI_WRITE_COMPLETE == cl->writing_state) if (MEI_WRITE_COMPLETE == cl->writing_state)
mask |= (POLLIN | POLLRDNORM); mask |= (POLLIN | POLLRDNORM);
......
...@@ -68,7 +68,8 @@ static int sram_probe(struct platform_device *pdev) ...@@ -68,7 +68,8 @@ static int sram_probe(struct platform_device *pdev)
ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base, ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base,
res->start, size, -1); res->start, size, -1);
if (ret < 0) { if (ret < 0) {
gen_pool_destroy(sram->pool); if (sram->clk)
clk_disable_unprepare(sram->clk);
return ret; return ret;
} }
......
...@@ -562,7 +562,9 @@ long st_register(struct st_proto_s *new_proto) ...@@ -562,7 +562,9 @@ long st_register(struct st_proto_s *new_proto)
if ((st_gdata->protos_registered != ST_EMPTY) && if ((st_gdata->protos_registered != ST_EMPTY) &&
(test_bit(ST_REG_PENDING, &st_gdata->st_state))) { (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
pr_err(" KIM failure complete callback "); pr_err(" KIM failure complete callback ");
spin_lock_irqsave(&st_gdata->lock, flags);
st_reg_complete(st_gdata, err); st_reg_complete(st_gdata, err);
spin_unlock_irqrestore(&st_gdata->lock, flags);
clear_bit(ST_REG_PENDING, &st_gdata->st_state); clear_bit(ST_REG_PENDING, &st_gdata->st_state);
} }
return -EINVAL; return -EINVAL;
......
...@@ -133,7 +133,7 @@ MODULE_LICENSE("GPL"); ...@@ -133,7 +133,7 @@ MODULE_LICENSE("GPL");
#define VMWARE_BALLOON_CMD(cmd, data, result) \ #define VMWARE_BALLOON_CMD(cmd, data, result) \
({ \ ({ \
unsigned long __stat, __dummy1, __dummy2; \ unsigned long __stat, __dummy1, __dummy2; \
__asm__ __volatile__ ("inl (%%dx)" : \ __asm__ __volatile__ ("inl %%dx" : \
"=a"(__stat), \ "=a"(__stat), \
"=c"(__dummy1), \ "=c"(__dummy1), \
"=d"(__dummy2), \ "=d"(__dummy2), \
......
...@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit); ...@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit);
MODULE_AUTHOR("VMware, Inc."); MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface."); MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
MODULE_VERSION("1.0.0.0-k"); MODULE_VERSION("1.1.0.0-k");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -35,6 +35,13 @@ struct vmci_obj { ...@@ -35,6 +35,13 @@ struct vmci_obj {
enum vmci_obj_type type; enum vmci_obj_type type;
}; };
/*
* Needed by other components of this module. It's okay to have one global
* instance of this because there can only ever be one VMCI device. Our
* virtual hardware enforces this.
*/
extern struct pci_dev *vmci_pdev;
u32 vmci_get_context_id(void); u32 vmci_get_context_id(void);
int vmci_send_datagram(struct vmci_datagram *dg); int vmci_send_datagram(struct vmci_datagram *dg);
......
...@@ -65,9 +65,11 @@ struct vmci_guest_device { ...@@ -65,9 +65,11 @@ struct vmci_guest_device {
void *data_buffer; void *data_buffer;
void *notification_bitmap; void *notification_bitmap;
dma_addr_t notification_base;
}; };
/* vmci_dev singleton device and supporting data*/ /* vmci_dev singleton device and supporting data*/
struct pci_dev *vmci_pdev;
static struct vmci_guest_device *vmci_dev_g; static struct vmci_guest_device *vmci_dev_g;
static DEFINE_SPINLOCK(vmci_dev_spinlock); static DEFINE_SPINLOCK(vmci_dev_spinlock);
...@@ -528,7 +530,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, ...@@ -528,7 +530,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
* well. * well.
*/ */
if (capabilities & VMCI_CAPS_NOTIFICATIONS) { if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
vmci_dev->notification_bitmap = vmalloc(PAGE_SIZE); vmci_dev->notification_bitmap = dma_alloc_coherent(
&pdev->dev, PAGE_SIZE, &vmci_dev->notification_base,
GFP_KERNEL);
if (!vmci_dev->notification_bitmap) { if (!vmci_dev->notification_bitmap) {
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"Unable to allocate notification bitmap\n"); "Unable to allocate notification bitmap\n");
...@@ -546,6 +550,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, ...@@ -546,6 +550,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
/* Set up global device so that we can start sending datagrams */ /* Set up global device so that we can start sending datagrams */
spin_lock_irq(&vmci_dev_spinlock); spin_lock_irq(&vmci_dev_spinlock);
vmci_dev_g = vmci_dev; vmci_dev_g = vmci_dev;
vmci_pdev = pdev;
spin_unlock_irq(&vmci_dev_spinlock); spin_unlock_irq(&vmci_dev_spinlock);
/* /*
...@@ -553,9 +558,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, ...@@ -553,9 +558,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
* used. * used.
*/ */
if (capabilities & VMCI_CAPS_NOTIFICATIONS) { if (capabilities & VMCI_CAPS_NOTIFICATIONS) {
struct page *page = unsigned long bitmap_ppn =
vmalloc_to_page(vmci_dev->notification_bitmap); vmci_dev->notification_base >> PAGE_SHIFT;
unsigned long bitmap_ppn = page_to_pfn(page);
if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) { if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) {
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"VMCI device unable to register notification bitmap with PPN 0x%x\n", "VMCI device unable to register notification bitmap with PPN 0x%x\n",
...@@ -665,11 +669,14 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, ...@@ -665,11 +669,14 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
if (vmci_dev->notification_bitmap) { if (vmci_dev->notification_bitmap) {
iowrite32(VMCI_CONTROL_RESET, iowrite32(VMCI_CONTROL_RESET,
vmci_dev->iobase + VMCI_CONTROL_ADDR); vmci_dev->iobase + VMCI_CONTROL_ADDR);
vfree(vmci_dev->notification_bitmap); dma_free_coherent(&pdev->dev, PAGE_SIZE,
vmci_dev->notification_bitmap,
vmci_dev->notification_base);
} }
err_remove_vmci_dev_g: err_remove_vmci_dev_g:
spin_lock_irq(&vmci_dev_spinlock); spin_lock_irq(&vmci_dev_spinlock);
vmci_pdev = NULL;
vmci_dev_g = NULL; vmci_dev_g = NULL;
spin_unlock_irq(&vmci_dev_spinlock); spin_unlock_irq(&vmci_dev_spinlock);
...@@ -699,6 +706,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) ...@@ -699,6 +706,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
spin_lock_irq(&vmci_dev_spinlock); spin_lock_irq(&vmci_dev_spinlock);
vmci_dev_g = NULL; vmci_dev_g = NULL;
vmci_pdev = NULL;
spin_unlock_irq(&vmci_dev_spinlock); spin_unlock_irq(&vmci_dev_spinlock);
dev_dbg(&pdev->dev, "Resetting vmci device\n"); dev_dbg(&pdev->dev, "Resetting vmci device\n");
...@@ -727,7 +735,9 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) ...@@ -727,7 +735,9 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
* device, so we can safely free it here. * device, so we can safely free it here.
*/ */
vfree(vmci_dev->notification_bitmap); dma_free_coherent(&pdev->dev, PAGE_SIZE,
vmci_dev->notification_bitmap,
vmci_dev->notification_base);
} }
vfree(vmci_dev->data_buffer); vfree(vmci_dev->data_buffer);
......
This diff is collapsed.
...@@ -146,24 +146,6 @@ VMCI_QP_PAGESTORE_IS_WELLFORMED(struct vmci_qp_page_store *page_store) ...@@ -146,24 +146,6 @@ VMCI_QP_PAGESTORE_IS_WELLFORMED(struct vmci_qp_page_store *page_store)
return page_store->len >= 2; return page_store->len >= 2;
} }
/*
* Helper function to check if the non-blocking flag
* is set for a given queue pair.
*/
static inline bool vmci_can_block(u32 flags)
{
return !(flags & VMCI_QPFLAG_NONBLOCK);
}
/*
* Helper function to check if the queue pair is pinned
* into memory.
*/
static inline bool vmci_qp_pinned(u32 flags)
{
return flags & VMCI_QPFLAG_PINNED;
}
void vmci_qp_broker_exit(void); void vmci_qp_broker_exit(void);
int vmci_qp_broker_alloc(struct vmci_handle handle, u32 peer, int vmci_qp_broker_alloc(struct vmci_handle handle, u32 peer,
u32 flags, u32 priv_flags, u32 flags, u32 priv_flags,
......
...@@ -306,7 +306,6 @@ static void netvsc_get_drvinfo(struct net_device *net, ...@@ -306,7 +306,6 @@ static void netvsc_get_drvinfo(struct net_device *net,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, HV_DRV_VERSION, sizeof(info->version));
strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
} }
...@@ -529,7 +528,6 @@ static int __init netvsc_drv_init(void) ...@@ -529,7 +528,6 @@ static int __init netvsc_drv_init(void)
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); MODULE_DESCRIPTION("Microsoft Hyper-V network driver");
module_init(netvsc_drv_init); module_init(netvsc_drv_init);
......
...@@ -37,7 +37,7 @@ config PARPORT_PC ...@@ -37,7 +37,7 @@ config PARPORT_PC
tristate "PC-style hardware" tristate "PC-style hardware"
depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \ depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \
(!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \ (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \
!XTENSA && !CRIS !XTENSA && !CRIS && !H8300
---help--- ---help---
You should say Y here if you have a PC-style parallel port. All You should say Y here if you have a PC-style parallel port. All
......
...@@ -232,7 +232,6 @@ static int __exit amiga_parallel_remove(struct platform_device *pdev) ...@@ -232,7 +232,6 @@ static int __exit amiga_parallel_remove(struct platform_device *pdev)
if (port->irq != PARPORT_IRQ_NONE) if (port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, port); free_irq(IRQ_AMIGA_CIAA_FLG, port);
parport_put_port(port); parport_put_port(port);
platform_set_drvdata(pdev, NULL);
return 0; return 0;
} }
......
...@@ -1879,7 +1879,6 @@ static void __exit storvsc_drv_exit(void) ...@@ -1879,7 +1879,6 @@ static void __exit storvsc_drv_exit(void)
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver");
module_init(storvsc_drv_init); module_init(storvsc_drv_init);
module_exit(storvsc_drv_exit); module_exit(storvsc_drv_exit);
menuconfig UIO menuconfig UIO
tristate "Userspace I/O drivers" tristate "Userspace I/O drivers"
depends on MMU
help help
Enable this to allow the userspace driver core code to be Enable this to allow the userspace driver core code to be
built. This code allows userspace programs easy access to built. This code allows userspace programs easy access to
...@@ -23,13 +24,6 @@ config UIO_CIF ...@@ -23,13 +24,6 @@ config UIO_CIF
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called uio_cif. will be called uio_cif.
config UIO_PDRV
tristate "Userspace I/O platform driver"
help
Generic platform driver for Userspace I/O devices.
If you don't know what to do here, say N.
config UIO_PDRV_GENIRQ config UIO_PDRV_GENIRQ
tristate "Userspace I/O platform driver with generic IRQ handling" tristate "Userspace I/O platform driver with generic IRQ handling"
help help
...@@ -128,4 +122,17 @@ config UIO_PRUSS ...@@ -128,4 +122,17 @@ config UIO_PRUSS
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called uio_pruss. will be called uio_pruss.
config UIO_MF624
tristate "Humusoft MF624 DAQ PCI card driver"
depends on PCI
help
Userspace I/O interface for the Humusoft MF624 PCI card.
A sample userspace application using this driver is available
(among other MF624 related information and software components)
for download in a git repository:
git clone git://rtime.felk.cvut.cz/mf6xx.git
If you compile this as a module, it will be called uio_mf624.
endif endif
obj-$(CONFIG_UIO) += uio.o obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_CIF) += uio_cif.o
obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o
obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_AEC) += uio_aec.o
...@@ -8,3 +7,4 @@ obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o ...@@ -8,3 +7,4 @@ obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
obj-$(CONFIG_UIO_NETX) += uio_netx.o obj-$(CONFIG_UIO_NETX) += uio_netx.o
obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
obj-$(CONFIG_UIO_MF624) += uio_mf624.o
...@@ -35,7 +35,6 @@ struct uio_device { ...@@ -35,7 +35,6 @@ struct uio_device {
atomic_t event; atomic_t event;
struct fasync_struct *async_queue; struct fasync_struct *async_queue;
wait_queue_head_t wait; wait_queue_head_t wait;
int vma_count;
struct uio_info *info; struct uio_info *info;
struct kobject *map_dir; struct kobject *map_dir;
struct kobject *portio_dir; struct kobject *portio_dir;
...@@ -593,18 +592,6 @@ static int uio_find_mem_index(struct vm_area_struct *vma) ...@@ -593,18 +592,6 @@ static int uio_find_mem_index(struct vm_area_struct *vma)
return -1; return -1;
} }
static void uio_vma_open(struct vm_area_struct *vma)
{
struct uio_device *idev = vma->vm_private_data;
idev->vma_count++;
}
static void uio_vma_close(struct vm_area_struct *vma)
{
struct uio_device *idev = vma->vm_private_data;
idev->vma_count--;
}
static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct uio_device *idev = vma->vm_private_data; struct uio_device *idev = vma->vm_private_data;
...@@ -630,12 +617,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -630,12 +617,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return 0; return 0;
} }
static const struct vm_operations_struct uio_vm_ops = { static const struct vm_operations_struct uio_logical_vm_ops = {
.open = uio_vma_open,
.close = uio_vma_close,
.fault = uio_vma_fault, .fault = uio_vma_fault,
}; };
static int uio_mmap_logical(struct vm_area_struct *vma)
{
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = &uio_logical_vm_ops;
return 0;
}
static const struct vm_operations_struct uio_physical_vm_ops = {
#ifdef CONFIG_HAVE_IOREMAP_PROT
.access = generic_access_phys,
#endif
};
static int uio_mmap_physical(struct vm_area_struct *vma) static int uio_mmap_physical(struct vm_area_struct *vma)
{ {
struct uio_device *idev = vma->vm_private_data; struct uio_device *idev = vma->vm_private_data;
...@@ -643,6 +641,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma) ...@@ -643,6 +641,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
if (mi < 0) if (mi < 0)
return -EINVAL; return -EINVAL;
vma->vm_ops = &uio_physical_vm_ops;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return remap_pfn_range(vma, return remap_pfn_range(vma,
...@@ -652,14 +652,6 @@ static int uio_mmap_physical(struct vm_area_struct *vma) ...@@ -652,14 +652,6 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
vma->vm_page_prot); vma->vm_page_prot);
} }
static int uio_mmap_logical(struct vm_area_struct *vma)
{
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = &uio_vm_ops;
uio_vma_open(vma);
return 0;
}
static int uio_mmap(struct file *filep, struct vm_area_struct *vma) static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
{ {
struct uio_listener *listener = filep->private_data; struct uio_listener *listener = filep->private_data;
......
...@@ -146,7 +146,7 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) ...@@ -146,7 +146,7 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
static int uio_dmem_genirq_probe(struct platform_device *pdev) static int uio_dmem_genirq_probe(struct platform_device *pdev)
{ {
struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data; struct uio_dmem_genirq_pdata *pdata = dev_get_platdata(&pdev->dev);
struct uio_info *uioinfo = &pdata->uioinfo; struct uio_info *uioinfo = &pdata->uioinfo;
struct uio_dmem_genirq_platdata *priv; struct uio_dmem_genirq_platdata *priv;
struct uio_mem *uiomem; struct uio_mem *uiomem;
......
/*
* UIO driver fo Humusoft MF624 DAQ card.
* Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>,
* Czech Technical University in Prague
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/uio_driver.h>
#define PCI_VENDOR_ID_HUMUSOFT 0x186c
#define PCI_DEVICE_ID_MF624 0x0624
#define PCI_SUBVENDOR_ID_HUMUSOFT 0x186c
#define PCI_SUBDEVICE_DEVICE 0x0624
/* BAR0 Interrupt control/status register */
#define INTCSR 0x4C
#define INTCSR_ADINT_ENABLE (1 << 0)
#define INTCSR_CTR4INT_ENABLE (1 << 3)
#define INTCSR_PCIINT_ENABLE (1 << 6)
#define INTCSR_ADINT_STATUS (1 << 2)
#define INTCSR_CTR4INT_STATUS (1 << 5)
enum mf624_interrupt_source {ADC, CTR4, ALL};
void mf624_disable_interrupt(enum mf624_interrupt_source source,
struct uio_info *info)
{
void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
switch (source) {
case ADC:
iowrite32(ioread32(INTCSR_reg)
& ~(INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE),
INTCSR_reg);
break;
case CTR4:
iowrite32(ioread32(INTCSR_reg)
& ~(INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE),
INTCSR_reg);
break;
case ALL:
default:
iowrite32(ioread32(INTCSR_reg)
& ~(INTCSR_ADINT_ENABLE | INTCSR_CTR4INT_ENABLE
| INTCSR_PCIINT_ENABLE),
INTCSR_reg);
break;
}
}
void mf624_enable_interrupt(enum mf624_interrupt_source source,
struct uio_info *info)
{
void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
switch (source) {
case ADC:
iowrite32(ioread32(INTCSR_reg)
| INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE,
INTCSR_reg);
break;
case CTR4:
iowrite32(ioread32(INTCSR_reg)
| INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE,
INTCSR_reg);
break;
case ALL:
default:
iowrite32(ioread32(INTCSR_reg)
| INTCSR_ADINT_ENABLE | INTCSR_CTR4INT_ENABLE
| INTCSR_PCIINT_ENABLE,
INTCSR_reg);
break;
}
}
static irqreturn_t mf624_irq_handler(int irq, struct uio_info *info)
{
void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
if ((ioread32(INTCSR_reg) & INTCSR_ADINT_ENABLE)
&& (ioread32(INTCSR_reg) & INTCSR_ADINT_STATUS)) {
mf624_disable_interrupt(ADC, info);
return IRQ_HANDLED;
}
if ((ioread32(INTCSR_reg) & INTCSR_CTR4INT_ENABLE)
&& (ioread32(INTCSR_reg) & INTCSR_CTR4INT_STATUS)) {
mf624_disable_interrupt(CTR4, info);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static int mf624_irqcontrol(struct uio_info *info, s32 irq_on)
{
if (irq_on == 0)
mf624_disable_interrupt(ALL, info);
else if (irq_on == 1)
mf624_enable_interrupt(ALL, info);
return 0;
}
static int mf624_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct uio_info *info;
info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if (pci_enable_device(dev))
goto out_free;
if (pci_request_regions(dev, "mf624"))
goto out_disable;
info->name = "mf624";
info->version = "0.0.1";
/* Note: Datasheet says device uses BAR0, BAR1, BAR2 -- do not trust it */
/* BAR0 */
info->mem[0].name = "PCI chipset, interrupts, status "
"bits, special functions";
info->mem[0].addr = pci_resource_start(dev, 0);
if (!info->mem[0].addr)
goto out_release;
info->mem[0].size = pci_resource_len(dev, 0);
info->mem[0].memtype = UIO_MEM_PHYS;
info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
if (!info->mem[0].internal_addr)
goto out_release;
/* BAR2 */
info->mem[1].name = "ADC, DAC, DIO";
info->mem[1].addr = pci_resource_start(dev, 2);
if (!info->mem[1].addr)
goto out_unmap0;
info->mem[1].size = pci_resource_len(dev, 2);
info->mem[1].memtype = UIO_MEM_PHYS;
info->mem[1].internal_addr = pci_ioremap_bar(dev, 2);
if (!info->mem[1].internal_addr)
goto out_unmap0;
/* BAR4 */
info->mem[2].name = "Counter/timer chip";
info->mem[2].addr = pci_resource_start(dev, 4);
if (!info->mem[2].addr)
goto out_unmap1;
info->mem[2].size = pci_resource_len(dev, 4);
info->mem[2].memtype = UIO_MEM_PHYS;
info->mem[2].internal_addr = pci_ioremap_bar(dev, 4);
if (!info->mem[2].internal_addr)
goto out_unmap1;
info->irq = dev->irq;
info->irq_flags = IRQF_SHARED;
info->handler = mf624_irq_handler;
info->irqcontrol = mf624_irqcontrol;
if (uio_register_device(&dev->dev, info))
goto out_unmap2;
pci_set_drvdata(dev, info);
return 0;
out_unmap2:
iounmap(info->mem[2].internal_addr);
out_unmap1:
iounmap(info->mem[1].internal_addr);
out_unmap0:
iounmap(info->mem[0].internal_addr);
out_release:
pci_release_regions(dev);
out_disable:
pci_disable_device(dev);
out_free:
kfree(info);
return -ENODEV;
}
static void mf624_pci_remove(struct pci_dev *dev)
{
struct uio_info *info = pci_get_drvdata(dev);
mf624_disable_interrupt(ALL, info);
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
iounmap(info->mem[1].internal_addr);
iounmap(info->mem[2].internal_addr);
kfree(info);
}
static DEFINE_PCI_DEVICE_TABLE(mf624_pci_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF624) },
{ 0, }
};
static struct pci_driver mf624_pci_driver = {
.name = "mf624",
.id_table = mf624_pci_id,
.probe = mf624_pci_probe,
.remove = mf624_pci_remove,
};
MODULE_DEVICE_TABLE(pci, mf624_pci_id);
module_pci_driver(mf624_pci_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");
/*
* drivers/uio/uio_pdrv.c
*
* Copyright (C) 2008 by Digi International Inc.
* All rights reserved.
*
* 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.
*/
#include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/stringify.h>
#include <linux/module.h>
#include <linux/slab.h>
#define DRIVER_NAME "uio_pdrv"
struct uio_platdata {
struct uio_info *uioinfo;
};
static int uio_pdrv_probe(struct platform_device *pdev)
{
struct uio_info *uioinfo = pdev->dev.platform_data;
struct uio_platdata *pdata;
struct uio_mem *uiomem;
int ret = -ENODEV;
int i;
if (!uioinfo || !uioinfo->name || !uioinfo->version) {
dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
goto err_uioinfo;
}
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
goto err_alloc_pdata;
}
pdata->uioinfo = uioinfo;
uiomem = &uioinfo->mem[0];
for (i = 0; i < pdev->num_resources; ++i) {
struct resource *r = &pdev->resource[i];
if (r->flags != IORESOURCE_MEM)
continue;
if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
dev_warn(&pdev->dev, "device has more than "
__stringify(MAX_UIO_MAPS)
" I/O memory resources.\n");
break;
}
uiomem->memtype = UIO_MEM_PHYS;
uiomem->addr = r->start;
uiomem->size = resource_size(r);
uiomem->name = r->name;
++uiomem;
}
while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
uiomem->size = 0;
++uiomem;
}
pdata->uioinfo->priv = pdata;
ret = uio_register_device(&pdev->dev, pdata->uioinfo);
if (ret) {
kfree(pdata);
err_alloc_pdata:
err_uioinfo:
return ret;
}
platform_set_drvdata(pdev, pdata);
return 0;
}
static int uio_pdrv_remove(struct platform_device *pdev)
{
struct uio_platdata *pdata = platform_get_drvdata(pdev);
uio_unregister_device(pdata->uioinfo);
kfree(pdata);
return 0;
}
static struct platform_driver uio_pdrv = {
.probe = uio_pdrv_probe,
.remove = uio_pdrv_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
module_platform_driver(uio_pdrv);
MODULE_AUTHOR("Uwe Kleine-Koenig");
MODULE_DESCRIPTION("Userspace I/O platform driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
...@@ -104,7 +104,7 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) ...@@ -104,7 +104,7 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
static int uio_pdrv_genirq_probe(struct platform_device *pdev) static int uio_pdrv_genirq_probe(struct platform_device *pdev)
{ {
struct uio_info *uioinfo = pdev->dev.platform_data; struct uio_info *uioinfo = dev_get_platdata(&pdev->dev);
struct uio_pdrv_genirq_platdata *priv; struct uio_pdrv_genirq_platdata *priv;
struct uio_mem *uiomem; struct uio_mem *uiomem;
int ret = -EINVAL; int ret = -EINVAL;
......
...@@ -121,7 +121,7 @@ static int pruss_probe(struct platform_device *dev) ...@@ -121,7 +121,7 @@ static int pruss_probe(struct platform_device *dev)
struct uio_pruss_dev *gdev; struct uio_pruss_dev *gdev;
struct resource *regs_prussio; struct resource *regs_prussio;
int ret = -ENODEV, cnt = 0, len; int ret = -ENODEV, cnt = 0, len;
struct uio_pruss_pdata *pdata = dev->dev.platform_data; struct uio_pruss_pdata *pdata = dev_get_platdata(&dev->dev);
gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
if (!gdev) if (!gdev)
...@@ -224,7 +224,6 @@ static int pruss_remove(struct platform_device *dev) ...@@ -224,7 +224,6 @@ static int pruss_remove(struct platform_device *dev)
struct uio_pruss_dev *gdev = platform_get_drvdata(dev); struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
pruss_cleanup(dev, gdev); pruss_cleanup(dev, gdev);
platform_set_drvdata(dev, NULL);
return 0; return 0;
} }
......
config USB_DWC3 config USB_DWC3
tristate "DesignWare USB3 DRD Core Support" tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
depends on EXTCON
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help help
Say Y or M here if your system has a Dual Role SuperSpeed Say Y or M here if your system has a Dual Role SuperSpeed
......
...@@ -23,13 +23,15 @@ ...@@ -23,13 +23,15 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/dwc3-omap.h> #include <linux/platform_data/dwc3-omap.h>
#include <linux/usb/dwc3-omap.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/extcon.h>
#include <linux/extcon/of_extcon.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
...@@ -135,9 +137,21 @@ struct dwc3_omap { ...@@ -135,9 +137,21 @@ struct dwc3_omap {
u32 revision; u32 revision;
u32 dma_status:1; u32 dma_status:1;
struct extcon_specific_cable_nb extcon_vbus_dev;
struct extcon_specific_cable_nb extcon_id_dev;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
struct regulator *vbus_reg;
}; };
static struct dwc3_omap *_omap; enum omap_dwc3_vbus_id_status {
OMAP_DWC3_ID_FLOAT,
OMAP_DWC3_ID_GROUND,
OMAP_DWC3_VBUS_OFF,
OMAP_DWC3_VBUS_VALID,
};
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{ {
...@@ -201,18 +215,24 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) ...@@ -201,18 +215,24 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
omap->irq0_offset, value); omap->irq0_offset, value);
} }
int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
enum omap_dwc3_vbus_id_status status)
{ {
u32 val; int ret;
struct dwc3_omap *omap = _omap; u32 val;
if (!omap)
return -EPROBE_DEFER;
switch (status) { switch (status) {
case OMAP_DWC3_ID_GROUND: case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n"); dev_dbg(omap->dev, "ID GND\n");
if (omap->vbus_reg) {
ret = regulator_enable(omap->vbus_reg);
if (ret) {
dev_dbg(omap->dev, "regulator enable failed\n");
return;
}
}
val = dwc3_omap_read_utmi_status(omap); val = dwc3_omap_read_utmi_status(omap);
val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
...@@ -235,6 +255,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) ...@@ -235,6 +255,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
break; break;
case OMAP_DWC3_ID_FLOAT: case OMAP_DWC3_ID_FLOAT:
if (omap->vbus_reg)
regulator_disable(omap->vbus_reg);
case OMAP_DWC3_VBUS_OFF: case OMAP_DWC3_VBUS_OFF:
dev_dbg(omap->dev, "VBUS Disconnect\n"); dev_dbg(omap->dev, "VBUS Disconnect\n");
...@@ -248,12 +271,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) ...@@ -248,12 +271,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
break; break;
default: default:
dev_dbg(omap->dev, "ID float\n"); dev_dbg(omap->dev, "invalid state\n");
} }
return 0;
} }
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{ {
...@@ -346,6 +366,32 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) ...@@ -346,6 +366,32 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
static int dwc3_omap_id_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb);
if (event)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
return NOTIFY_DONE;
}
static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb);
if (event)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
return NOTIFY_DONE;
}
static int dwc3_omap_probe(struct platform_device *pdev) static int dwc3_omap_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
...@@ -353,6 +399,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -353,6 +399,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
struct dwc3_omap *omap; struct dwc3_omap *omap;
struct resource *res; struct resource *res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct extcon_dev *edev;
struct regulator *vbus_reg = NULL;
int ret = -ENOMEM; int ret = -ENOMEM;
int irq; int irq;
...@@ -393,19 +441,22 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -393,19 +441,22 @@ static int dwc3_omap_probe(struct platform_device *pdev)
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
if (of_property_read_bool(node, "vbus-supply")) {
vbus_reg = devm_regulator_get(dev, "vbus");
if (IS_ERR(vbus_reg)) {
dev_err(dev, "vbus init failed\n");
return PTR_ERR(vbus_reg);
}
}
spin_lock_init(&omap->lock); spin_lock_init(&omap->lock);
omap->dev = dev; omap->dev = dev;
omap->irq = irq; omap->irq = irq;
omap->base = base; omap->base = base;
omap->vbus_reg = vbus_reg;
dev->dma_mask = &dwc3_omap_dma_mask; dev->dma_mask = &dwc3_omap_dma_mask;
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_omap = omap;
pm_runtime_enable(dev); pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev); ret = pm_runtime_get_sync(dev);
if (ret < 0) { if (ret < 0) {
...@@ -480,14 +531,46 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -480,14 +531,46 @@ static int dwc3_omap_probe(struct platform_device *pdev)
dwc3_omap_enable_irqs(omap); dwc3_omap_enable_irqs(omap);
if (of_property_read_bool(node, "extcon")) {
edev = of_extcon_get_extcon_dev(dev, 0);
if (IS_ERR(edev)) {
dev_vdbg(dev, "couldn't get extcon device\n");
ret = PTR_ERR(edev);
goto err2;
}
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
ret = extcon_register_interest(&omap->extcon_vbus_dev,
edev->name, "USB", &omap->vbus_nb);
if (ret < 0)
dev_vdbg(dev, "failed to register notifier for USB\n");
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
"USB-HOST", &omap->id_nb);
if (ret < 0)
dev_vdbg(dev,
"failed to register notifier for USB-HOST\n");
if (extcon_get_cable_state(edev, "USB") == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
if (extcon_get_cable_state(edev, "USB-HOST") == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
}
ret = of_platform_populate(node, NULL, NULL, dev); ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to create dwc3 core\n"); dev_err(&pdev->dev, "failed to create dwc3 core\n");
goto err2; goto err3;
} }
return 0; return 0;
err3:
if (omap->extcon_vbus_dev.edev)
extcon_unregister_interest(&omap->extcon_vbus_dev);
if (omap->extcon_id_dev.edev)
extcon_unregister_interest(&omap->extcon_id_dev);
err2: err2:
dwc3_omap_disable_irqs(omap); dwc3_omap_disable_irqs(omap);
...@@ -504,6 +587,10 @@ static int dwc3_omap_remove(struct platform_device *pdev) ...@@ -504,6 +587,10 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{ {
struct dwc3_omap *omap = platform_get_drvdata(pdev); struct dwc3_omap *omap = platform_get_drvdata(pdev);
if (omap->extcon_vbus_dev.edev)
extcon_unregister_interest(&omap->extcon_vbus_dev);
if (omap->extcon_id_dev.edev)
extcon_unregister_interest(&omap->extcon_id_dev);
dwc3_omap_disable_irqs(omap); dwc3_omap_disable_irqs(omap);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -825,5 +825,4 @@ module_init(hvfb_drv_init); ...@@ -825,5 +825,4 @@ module_init(hvfb_drv_init);
module_exit(hvfb_drv_exit); module_exit(hvfb_drv_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(HV_DRV_VERSION);
MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver"); MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver");
...@@ -23,7 +23,7 @@ static int vmic_probe(struct pci_dev *, const struct pci_device_id *); ...@@ -23,7 +23,7 @@ static int vmic_probe(struct pci_dev *, const struct pci_device_id *);
static void vmic_remove(struct pci_dev *); static void vmic_remove(struct pci_dev *);
/** Base address to access FPGA register */ /** Base address to access FPGA register */
static void *vmic_base; static void __iomem *vmic_base;
static const char driver_name[] = "vmivme_7805"; static const char driver_name[] = "vmivme_7805";
......
...@@ -243,6 +243,8 @@ static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) ...@@ -243,6 +243,8 @@ static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge)
static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
struct vme_bridge *ca91cx42_bridge;
/* Disable interrupts from PCI to VME */ /* Disable interrupts from PCI to VME */
iowrite32(0, bridge->base + VINT_EN); iowrite32(0, bridge->base + VINT_EN);
...@@ -251,7 +253,9 @@ static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, ...@@ -251,7 +253,9 @@ static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
/* Clear Any Pending PCI Interrupts */ /* Clear Any Pending PCI Interrupts */
iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
free_irq(pdev->irq, pdev); ca91cx42_bridge = container_of((void *)bridge, struct vme_bridge,
driver_priv);
free_irq(pdev->irq, ca91cx42_bridge);
} }
static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level)
...@@ -856,7 +860,7 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, ...@@ -856,7 +860,7 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
void *buf, size_t count, loff_t offset) void *buf, size_t count, loff_t offset)
{ {
ssize_t retval; ssize_t retval;
void *addr = image->kern_base + offset; void __iomem *addr = image->kern_base + offset;
unsigned int done = 0; unsigned int done = 0;
unsigned int count32; unsigned int count32;
...@@ -916,7 +920,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, ...@@ -916,7 +920,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
void *buf, size_t count, loff_t offset) void *buf, size_t count, loff_t offset)
{ {
ssize_t retval; ssize_t retval;
void *addr = image->kern_base + offset; void __iomem *addr = image->kern_base + offset;
unsigned int done = 0; unsigned int done = 0;
unsigned int count32; unsigned int count32;
......
...@@ -1267,7 +1267,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, ...@@ -1267,7 +1267,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
u32 aspace, cycle, dwidth; u32 aspace, cycle, dwidth;
struct vme_bus_error *vme_err = NULL; struct vme_bus_error *vme_err = NULL;
struct vme_bridge *tsi148_bridge; struct vme_bridge *tsi148_bridge;
void *addr = image->kern_base + offset; void __iomem *addr = image->kern_base + offset;
unsigned int done = 0; unsigned int done = 0;
unsigned int count32; unsigned int count32;
...@@ -1348,7 +1348,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, ...@@ -1348,7 +1348,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
int retval = 0, enabled; int retval = 0, enabled;
unsigned long long vme_base, size; unsigned long long vme_base, size;
u32 aspace, cycle, dwidth; u32 aspace, cycle, dwidth;
void *addr = image->kern_base + offset; void __iomem *addr = image->kern_base + offset;
unsigned int done = 0; unsigned int done = 0;
unsigned int count32; unsigned int count32;
......
/*
* OF helpers for External connector (extcon) framework
*
* Copyright (C) 2013 Texas Instruments, Inc.
* Kishon Vijay Abraham I <kishon@ti.com>
*
* Copyright (C) 2013 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __LINUX_OF_EXTCON_H
#define __LINUX_OF_EXTCON_H
#include <linux/err.h>
#if IS_ENABLED(CONFIG_OF_EXTCON)
extern struct extcon_dev
*of_extcon_get_extcon_dev(struct device *dev, int index);
#else
static inline struct extcon_dev
*of_extcon_get_extcon_dev(struct device *dev, int index)
{
return ERR_PTR(-ENOSYS);
}
#endif /* CONFIG_OF_EXTCON */
#endif /* __LINUX_OF_EXTCON_H */
...@@ -27,6 +27,14 @@ ...@@ -27,6 +27,14 @@
#include <linux/types.h> #include <linux/types.h>
/*
* Framework version for util services.
*/
#define UTIL_FW_MAJOR 3
#define UTIL_FW_MINOR 0
#define UTIL_FW_MAJOR_MINOR (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
/* /*
* Implementation of host controlled snapshot of the guest. * Implementation of host controlled snapshot of the guest.
...@@ -455,27 +463,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, ...@@ -455,27 +463,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
*read = dsize - *write; *read = dsize - *write;
} }
/*
* We use the same version numbering for all Hyper-V modules.
*
* Definition of versioning is as follows;
*
* Major Number Changes for these scenarios;
* 1. When a new version of Windows Hyper-V
* is released.
* 2. A Major change has occurred in the
* Linux IC's.
* (For example the merge for the first time
* into the kernel) Every time the Major Number
* changes, the Revision number is reset to 0.
* Minor Number Changes when new functionality is added
* to the Linux IC's that is not a bug fix.
*
* 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync
*/
#define HV_DRV_VERSION "3.1"
/* /*
* VMBUS version is 32 bit entity broken up into * VMBUS version is 32 bit entity broken up into
* two 16 bit quantities: major_number. minor_number. * two 16 bit quantities: major_number. minor_number.
...@@ -1494,7 +1481,7 @@ struct hyperv_service_callback { ...@@ -1494,7 +1481,7 @@ struct hyperv_service_callback {
}; };
#define MAX_SRV_VER 0x7ffffff #define MAX_SRV_VER 0x7ffffff
extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
struct icmsg_negotiate *, u8 *, int, struct icmsg_negotiate *, u8 *, int,
int); int);
......
...@@ -372,17 +372,15 @@ struct palmas_usb { ...@@ -372,17 +372,15 @@ struct palmas_usb {
struct extcon_dev edev; struct extcon_dev edev;
/* used to set vbus, in atomic path */
struct work_struct set_vbus_work;
int id_otg_irq; int id_otg_irq;
int id_irq; int id_irq;
int vbus_otg_irq; int vbus_otg_irq;
int vbus_irq; int vbus_irq;
int vbus_enable;
enum palmas_usb_state linkstat; enum palmas_usb_state linkstat;
int wakeup;
bool enable_vbus_detection;
bool enable_id_detection;
}; };
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
......
/*
* Copyright (C) 2013 by Texas Instruments
*
* The Inventra Controller Driver for Linux 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.
*/
#ifndef __DWC3_OMAP_H__
#define __DWC3_OMAP_H__
enum omap_dwc3_vbus_id_status {
OMAP_DWC3_UNKNOWN = 0,
OMAP_DWC3_ID_GROUND,
OMAP_DWC3_ID_FLOAT,
OMAP_DWC3_VBUS_VALID,
OMAP_DWC3_VBUS_OFF,
};
#if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
#else
static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
{
return -ENODEV;
}
#endif
#endif /* __DWC3_OMAP_H__ */
...@@ -4079,6 +4079,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, ...@@ -4079,6 +4079,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
return len; return len;
} }
EXPORT_SYMBOL_GPL(generic_access_phys);
#endif #endif
/* /*
......
...@@ -79,8 +79,6 @@ enum { ...@@ -79,8 +79,6 @@ enum {
DNS DNS
}; };
static char kvp_send_buffer[4096];
static char kvp_recv_buffer[4096 * 2];
static struct sockaddr_nl addr; static struct sockaddr_nl addr;
static int in_hand_shake = 1; static int in_hand_shake = 1;
...@@ -1301,6 +1299,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) ...@@ -1301,6 +1299,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
} }
error = kvp_write_file(file, "HWADDR", "", mac_addr); error = kvp_write_file(file, "HWADDR", "", mac_addr);
free(mac_addr);
if (error) if (error)
goto setval_error; goto setval_error;
...@@ -1346,7 +1345,6 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) ...@@ -1346,7 +1345,6 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
goto setval_error; goto setval_error;
setval_done: setval_done:
free(mac_addr);
fclose(file); fclose(file);
/* /*
...@@ -1355,12 +1353,15 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) ...@@ -1355,12 +1353,15 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
*/ */
snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file);
system(cmd); if (system(cmd)) {
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
cmd, errno, strerror(errno));
return HV_E_FAIL;
}
return 0; return 0;
setval_error: setval_error:
syslog(LOG_ERR, "Failed to write config file"); syslog(LOG_ERR, "Failed to write config file");
free(mac_addr);
fclose(file); fclose(file);
return error; return error;
} }
...@@ -1391,23 +1392,18 @@ kvp_get_domain_name(char *buffer, int length) ...@@ -1391,23 +1392,18 @@ kvp_get_domain_name(char *buffer, int length)
static int static int
netlink_send(int fd, struct cn_msg *msg) netlink_send(int fd, struct cn_msg *msg)
{ {
struct nlmsghdr *nlh; struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE };
unsigned int size; unsigned int size;
struct msghdr message; struct msghdr message;
char buffer[64];
struct iovec iov[2]; struct iovec iov[2];
size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); size = sizeof(struct cn_msg) + msg->len;
nlh = (struct nlmsghdr *)buffer; nlh.nlmsg_pid = getpid();
nlh->nlmsg_seq = 0; nlh.nlmsg_len = NLMSG_LENGTH(size);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
nlh->nlmsg_flags = 0;
iov[0].iov_base = nlh; iov[0].iov_base = &nlh;
iov[0].iov_len = sizeof(*nlh); iov[0].iov_len = sizeof(nlh);
iov[1].iov_base = msg; iov[1].iov_base = msg;
iov[1].iov_len = size; iov[1].iov_len = size;
...@@ -1437,10 +1433,22 @@ int main(void) ...@@ -1437,10 +1433,22 @@ int main(void)
int pool; int pool;
char *if_name; char *if_name;
struct hv_kvp_ipaddr_value *kvp_ip_val; struct hv_kvp_ipaddr_value *kvp_ip_val;
char *kvp_send_buffer;
char *kvp_recv_buffer;
size_t kvp_recv_buffer_len;
daemon(1, 0); if (daemon(1, 0))
return 1;
openlog("KVP", 0, LOG_USER); openlog("KVP", 0, LOG_USER);
syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
kvp_send_buffer = calloc(1, kvp_recv_buffer_len);
kvp_recv_buffer = calloc(1, kvp_recv_buffer_len);
if (!(kvp_send_buffer && kvp_recv_buffer)) {
syslog(LOG_ERR, "Failed to allocate netlink buffers");
exit(EXIT_FAILURE);
}
/* /*
* Retrieve OS release information. * Retrieve OS release information.
*/ */
...@@ -1514,7 +1522,7 @@ int main(void) ...@@ -1514,7 +1522,7 @@ int main(void)
continue; continue;
} }
len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0,
addr_p, &addr_l); addr_p, &addr_l);
if (len < 0) { if (len < 0) {
......
...@@ -38,8 +38,6 @@ ...@@ -38,8 +38,6 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <syslog.h> #include <syslog.h>
static char vss_recv_buffer[4096];
static char vss_send_buffer[4096];
static struct sockaddr_nl addr; static struct sockaddr_nl addr;
#ifndef SOL_NETLINK #ifndef SOL_NETLINK
...@@ -107,23 +105,18 @@ static int vss_operate(int operation) ...@@ -107,23 +105,18 @@ static int vss_operate(int operation)
static int netlink_send(int fd, struct cn_msg *msg) static int netlink_send(int fd, struct cn_msg *msg)
{ {
struct nlmsghdr *nlh; struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE };
unsigned int size; unsigned int size;
struct msghdr message; struct msghdr message;
char buffer[64];
struct iovec iov[2]; struct iovec iov[2];
size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); size = sizeof(struct cn_msg) + msg->len;
nlh = (struct nlmsghdr *)buffer; nlh.nlmsg_pid = getpid();
nlh->nlmsg_seq = 0; nlh.nlmsg_len = NLMSG_LENGTH(size);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
nlh->nlmsg_flags = 0;
iov[0].iov_base = nlh; iov[0].iov_base = &nlh;
iov[0].iov_len = sizeof(*nlh); iov[0].iov_len = sizeof(nlh);
iov[1].iov_base = msg; iov[1].iov_base = msg;
iov[1].iov_len = size; iov[1].iov_len = size;
...@@ -147,6 +140,9 @@ int main(void) ...@@ -147,6 +140,9 @@ int main(void)
struct cn_msg *incoming_cn_msg; struct cn_msg *incoming_cn_msg;
int op; int op;
struct hv_vss_msg *vss_msg; struct hv_vss_msg *vss_msg;
char *vss_send_buffer;
char *vss_recv_buffer;
size_t vss_recv_buffer_len;
if (daemon(1, 0)) if (daemon(1, 0))
return 1; return 1;
...@@ -154,9 +150,18 @@ int main(void) ...@@ -154,9 +150,18 @@ int main(void)
openlog("Hyper-V VSS", 0, LOG_USER); openlog("Hyper-V VSS", 0, LOG_USER);
syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
vss_send_buffer = calloc(1, vss_recv_buffer_len);
vss_recv_buffer = calloc(1, vss_recv_buffer_len);
if (!(vss_send_buffer && vss_recv_buffer)) {
syslog(LOG_ERR, "Failed to allocate netlink buffers");
exit(EXIT_FAILURE);
}
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
if (fd < 0) { if (fd < 0) {
syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); syslog(LOG_ERR, "netlink socket creation failed; error:%d %s",
errno, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
addr.nl_family = AF_NETLINK; addr.nl_family = AF_NETLINK;
...@@ -167,12 +172,16 @@ int main(void) ...@@ -167,12 +172,16 @@ int main(void)
error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (error < 0) { if (error < 0) {
syslog(LOG_ERR, "bind failed; error:%d", error); syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno));
close(fd); close(fd);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
nl_group = CN_VSS_IDX; nl_group = CN_VSS_IDX;
setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) {
syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
/* /*
* Register ourselves with the kernel. * Register ourselves with the kernel.
*/ */
...@@ -187,7 +196,7 @@ int main(void) ...@@ -187,7 +196,7 @@ int main(void)
len = netlink_send(fd, message); len = netlink_send(fd, message);
if (len < 0) { if (len < 0) {
syslog(LOG_ERR, "netlink_send failed; error:%d", len); syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno));
close(fd); close(fd);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -199,9 +208,18 @@ int main(void) ...@@ -199,9 +208,18 @@ int main(void)
socklen_t addr_l = sizeof(addr); socklen_t addr_l = sizeof(addr);
pfd.events = POLLIN; pfd.events = POLLIN;
pfd.revents = 0; pfd.revents = 0;
poll(&pfd, 1, -1);
len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0, if (poll(&pfd, 1, -1) < 0) {
syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
if (errno == EINVAL) {
close(fd);
exit(EXIT_FAILURE);
}
else
continue;
}
len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0,
addr_p, &addr_l); addr_p, &addr_l);
if (len < 0) { if (len < 0) {
...@@ -241,7 +259,8 @@ int main(void) ...@@ -241,7 +259,8 @@ int main(void)
vss_msg->error = error; vss_msg->error = error;
len = netlink_send(fd, incoming_cn_msg); len = netlink_send(fd, incoming_cn_msg);
if (len < 0) { if (len < 0) {
syslog(LOG_ERR, "net_link send failed; error:%d", len); syslog(LOG_ERR, "net_link send failed; error:%d %s",
errno, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
......
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