diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 14:36:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 14:36:27 -0400 |
commit | 1d1fdd95df681f0c065d90ffaafa215a0e8825e2 (patch) | |
tree | 19016e131bb5c7eb280a4cc8dff864ba36e53be4 | |
parent | b3b49114c80e799af8b08c0c6d1ff886ea843f03 (diff) | |
parent | 3cc1f95283a125cf54ccf1e25065321d4385133b (diff) |
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
...
64 files changed, 1093 insertions, 674 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-twl.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt index 58f531ab4df3..7dab6a8f4a0e 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-twl.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt | |||
@@ -1,15 +1,15 @@ | |||
1 | EXTCON FOR TWL CHIPS | 1 | EXTCON FOR PALMAS/TWL CHIPS |
2 | 2 | ||
3 | PALMAS USB COMPARATOR | 3 | PALMAS USB COMPARATOR |
4 | Required Properties: | 4 | Required Properties: |
5 | - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb" | 5 | - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb" |
6 | - vbus-supply : phandle to the regulator device tree node. | ||
7 | 6 | ||
8 | Optional Properties: | 7 | Optional Properties: |
9 | - ti,wakeup : To enable the wakeup comparator in probe | 8 | - ti,wakeup : To enable the wakeup comparator in probe |
9 | - ti,enable-id-detection: Perform ID detection. | ||
10 | - ti,enable-vbus-detection: Perform VBUS detection. | ||
10 | 11 | ||
11 | palmas-usb { | 12 | palmas-usb { |
12 | compatible = "ti,twl6035-usb", "ti,palmas-usb"; | 13 | compatible = "ti,twl6035-usb", "ti,palmas-usb"; |
13 | vbus-supply = <&smps10_reg>; | ||
14 | ti,wakeup; | 14 | ti,wakeup; |
15 | }; | 15 | }; |
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt index 57e71f6817d0..9088ab09e200 100644 --- a/Documentation/devicetree/bindings/usb/omap-usb.txt +++ b/Documentation/devicetree/bindings/usb/omap-usb.txt | |||
@@ -53,6 +53,11 @@ OMAP DWC3 GLUE | |||
53 | It should be set to "1" for HW mode and "2" for SW mode. | 53 | It should be set to "1" for HW mode and "2" for SW mode. |
54 | - ranges: the child address space are mapped 1:1 onto the parent address space | 54 | - ranges: the child address space are mapped 1:1 onto the parent address space |
55 | 55 | ||
56 | Optional Properties: | ||
57 | - extcon : phandle for the extcon device omap dwc3 uses to detect | ||
58 | connect/disconnect events. | ||
59 | - vbus-supply : phandle to the regulator device tree node if needed. | ||
60 | |||
56 | Sub-nodes: | 61 | Sub-nodes: |
57 | The dwc3 core should be added as subnode to omap dwc3 glue. | 62 | The dwc3 core should be added as subnode to omap dwc3 glue. |
58 | - dwc3 : | 63 | - dwc3 : |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 5c5cc00ebb07..d39cca659a3f 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1182 | } | 1182 | } |
1183 | count++; | 1183 | count++; |
1184 | 1184 | ||
1185 | if (gis & (BIT1 + BIT0)) { | 1185 | if (gis & (BIT1 | BIT0)) { |
1186 | isr = read_reg16(info, CHB + ISR); | 1186 | isr = read_reg16(info, CHB + ISR); |
1187 | if (isr & IRQ_DCD) | 1187 | if (isr & IRQ_DCD) |
1188 | dcd_change(info, tty); | 1188 | dcd_change(info, tty); |
1189 | if (isr & IRQ_CTS) | 1189 | if (isr & IRQ_CTS) |
1190 | cts_change(info, tty); | 1190 | cts_change(info, tty); |
1191 | } | 1191 | } |
1192 | if (gis & (BIT3 + BIT2)) | 1192 | if (gis & (BIT3 | BIT2)) |
1193 | { | 1193 | { |
1194 | isr = read_reg16(info, CHA + ISR); | 1194 | isr = read_reg16(info, CHA + ISR); |
1195 | if (isr & IRQ_TIMER) { | 1195 | if (isr & IRQ_TIMER) { |
@@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1210 | if (isr & IRQ_RXTIME) { | 1210 | if (isr & IRQ_RXTIME) { |
1211 | issue_command(info, CHA, CMD_RXFIFO_READ); | 1211 | issue_command(info, CHA, CMD_RXFIFO_READ); |
1212 | } | 1212 | } |
1213 | if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) { | 1213 | if (isr & (IRQ_RXEOM | IRQ_RXFIFO)) { |
1214 | if (info->params.mode == MGSL_MODE_HDLC) | 1214 | if (info->params.mode == MGSL_MODE_HDLC) |
1215 | rx_ready_hdlc(info, isr & IRQ_RXEOM); | 1215 | rx_ready_hdlc(info, isr & IRQ_RXEOM); |
1216 | else | 1216 | else |
@@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info) | |||
3031 | unsigned char val; | 3031 | unsigned char val; |
3032 | 3032 | ||
3033 | /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */ | 3033 | /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */ |
3034 | val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0); | 3034 | val = read_reg(info, CHA + CCR1) | (BIT2 | BIT1 | BIT0); |
3035 | write_reg(info, CHA + CCR1, val); | 3035 | write_reg(info, CHA + CCR1, val); |
3036 | 3036 | ||
3037 | /* CCR2:04 SSEL Clock source select, 1=submode b */ | 3037 | /* CCR2:04 SSEL Clock source select, 1=submode b */ |
3038 | val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5); | 3038 | val = read_reg(info, CHA + CCR2) | (BIT4 | BIT5); |
3039 | write_reg(info, CHA + CCR2, val); | 3039 | write_reg(info, CHA + CCR2, val); |
3040 | 3040 | ||
3041 | /* set LinkSpeed if available, otherwise default to 2Mbps */ | 3041 | /* set LinkSpeed if available, otherwise default to 2Mbps */ |
@@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info) | |||
3125 | val |= BIT4; | 3125 | val |= BIT4; |
3126 | break; // FM0 | 3126 | break; // FM0 |
3127 | case HDLC_ENCODING_BIPHASE_MARK: | 3127 | case HDLC_ENCODING_BIPHASE_MARK: |
3128 | val |= BIT4 + BIT2; | 3128 | val |= BIT4 | BIT2; |
3129 | break; // FM1 | 3129 | break; // FM1 |
3130 | case HDLC_ENCODING_BIPHASE_LEVEL: | 3130 | case HDLC_ENCODING_BIPHASE_LEVEL: |
3131 | val |= BIT4 + BIT3; | 3131 | val |= BIT4 | BIT3; |
3132 | break; // Manchester | 3132 | break; // Manchester |
3133 | } | 3133 | } |
3134 | write_reg(info, CHA + CCR0, val); | 3134 | write_reg(info, CHA + CCR0, val); |
@@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info) | |||
3185 | */ | 3185 | */ |
3186 | val = 0x00; | 3186 | val = 0x00; |
3187 | if (info->params.crc_type == HDLC_CRC_NONE) | 3187 | if (info->params.crc_type == HDLC_CRC_NONE) |
3188 | val |= BIT2 + BIT1; | 3188 | val |= BIT2 | BIT1; |
3189 | if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) | 3189 | if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) |
3190 | val |= BIT5; | 3190 | val |= BIT5; |
3191 | switch (info->params.preamble_length) | 3191 | switch (info->params.preamble_length) |
@@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info) | |||
3197 | val |= BIT6; | 3197 | val |= BIT6; |
3198 | break; | 3198 | break; |
3199 | case HDLC_PREAMBLE_LENGTH_64BITS: | 3199 | case HDLC_PREAMBLE_LENGTH_64BITS: |
3200 | val |= BIT7 + BIT6; | 3200 | val |= BIT7 | BIT6; |
3201 | break; | 3201 | break; |
3202 | } | 3202 | } |
3203 | write_reg(info, CHA + CCR3, val); | 3203 | write_reg(info, CHA + CCR3, val); |
@@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info) | |||
3264 | clear_reg_bits(info, CHA + PVR, BIT3); | 3264 | clear_reg_bits(info, CHA + PVR, BIT3); |
3265 | 3265 | ||
3266 | irq_enable(info, CHA, | 3266 | irq_enable(info, CHA, |
3267 | IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT + | 3267 | IRQ_RXEOM | IRQ_RXFIFO | IRQ_ALLSENT | |
3268 | IRQ_UNDERRUN + IRQ_TXFIFO); | 3268 | IRQ_UNDERRUN | IRQ_TXFIFO); |
3269 | issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); | 3269 | issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); |
3270 | wait_command_complete(info, CHA); | 3270 | wait_command_complete(info, CHA); |
3271 | read_reg16(info, CHA + ISR); /* clear pending IRQs */ | 3271 | read_reg16(info, CHA + ISR); /* clear pending IRQs */ |
@@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info) | |||
3582 | } else | 3582 | } else |
3583 | clear_reg_bits(info, CHA + PVR, BIT3); | 3583 | clear_reg_bits(info, CHA + PVR, BIT3); |
3584 | irq_enable(info, CHA, | 3584 | irq_enable(info, CHA, |
3585 | IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME + | 3585 | IRQ_RXEOM | IRQ_RXFIFO | IRQ_BREAK_ON | IRQ_RXTIME | |
3586 | IRQ_ALLSENT + IRQ_TXFIFO); | 3586 | IRQ_ALLSENT | IRQ_TXFIFO); |
3587 | issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); | 3587 | issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); |
3588 | wait_command_complete(info, CHA); | 3588 | wait_command_complete(info, CHA); |
3589 | read_reg16(info, CHA + ISR); /* clear pending IRQs */ | 3589 | read_reg16(info, CHA + ISR); /* clear pending IRQs */ |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 63f454e20576..f1d54a3985bd 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -14,6 +14,10 @@ if EXTCON | |||
14 | 14 | ||
15 | comment "Extcon Device Drivers" | 15 | comment "Extcon Device Drivers" |
16 | 16 | ||
17 | config OF_EXTCON | ||
18 | def_tristate y | ||
19 | depends on OF | ||
20 | |||
17 | config EXTCON_GPIO | 21 | config EXTCON_GPIO |
18 | tristate "GPIO extcon support" | 22 | tristate "GPIO extcon support" |
19 | depends on GPIOLIB | 23 | depends on GPIOLIB |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 540e2c3a4431..759fdae46f95 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for external connector class (extcon) devices | 2 | # Makefile for external connector class (extcon) devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_OF_EXTCON) += of_extcon.o | ||
6 | |||
5 | obj-$(CONFIG_EXTCON) += extcon-class.o | 7 | obj-$(CONFIG_EXTCON) += extcon-class.o |
6 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o | 8 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o |
7 | obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o | 9 | obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o |
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index d0233cd18ffa..5985807e52c9 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c | |||
@@ -87,7 +87,8 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data) | |||
87 | { | 87 | { |
88 | struct adc_jack_data *data = _data; | 88 | struct adc_jack_data *data = _data; |
89 | 89 | ||
90 | schedule_delayed_work(&data->handler, data->handling_delay); | 90 | queue_delayed_work(system_power_efficient_wq, |
91 | &data->handler, data->handling_delay); | ||
91 | return IRQ_HANDLED; | 92 | return IRQ_HANDLED; |
92 | } | 93 | } |
93 | 94 | ||
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 7a1b4a7791ba..e55713083c78 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -890,8 +890,9 @@ static void arizona_micd_detect(struct work_struct *work) | |||
890 | 890 | ||
891 | handled: | 891 | handled: |
892 | if (info->detecting) | 892 | if (info->detecting) |
893 | schedule_delayed_work(&info->micd_timeout_work, | 893 | queue_delayed_work(system_power_efficient_wq, |
894 | msecs_to_jiffies(info->micd_timeout)); | 894 | &info->micd_timeout_work, |
895 | msecs_to_jiffies(info->micd_timeout)); | ||
895 | 896 | ||
896 | pm_runtime_mark_last_busy(info->dev); | 897 | pm_runtime_mark_last_busy(info->dev); |
897 | mutex_unlock(&info->lock); | 898 | mutex_unlock(&info->lock); |
@@ -912,8 +913,9 @@ static irqreturn_t arizona_micdet(int irq, void *data) | |||
912 | mutex_unlock(&info->lock); | 913 | mutex_unlock(&info->lock); |
913 | 914 | ||
914 | if (debounce) | 915 | if (debounce) |
915 | schedule_delayed_work(&info->micd_detect_work, | 916 | queue_delayed_work(system_power_efficient_wq, |
916 | msecs_to_jiffies(debounce)); | 917 | &info->micd_detect_work, |
918 | msecs_to_jiffies(debounce)); | ||
917 | else | 919 | else |
918 | arizona_micd_detect(&info->micd_detect_work.work); | 920 | arizona_micd_detect(&info->micd_detect_work.work); |
919 | 921 | ||
@@ -967,12 +969,14 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
967 | if (val == info->last_jackdet) { | 969 | if (val == info->last_jackdet) { |
968 | dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n"); | 970 | dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n"); |
969 | if (cancelled_hp) | 971 | if (cancelled_hp) |
970 | schedule_delayed_work(&info->hpdet_work, | 972 | queue_delayed_work(system_power_efficient_wq, |
971 | msecs_to_jiffies(HPDET_DEBOUNCE)); | 973 | &info->hpdet_work, |
974 | msecs_to_jiffies(HPDET_DEBOUNCE)); | ||
972 | 975 | ||
973 | if (cancelled_mic) | 976 | if (cancelled_mic) |
974 | schedule_delayed_work(&info->micd_timeout_work, | 977 | queue_delayed_work(system_power_efficient_wq, |
975 | msecs_to_jiffies(info->micd_timeout)); | 978 | &info->micd_timeout_work, |
979 | msecs_to_jiffies(info->micd_timeout)); | ||
976 | 980 | ||
977 | goto out; | 981 | goto out; |
978 | } | 982 | } |
@@ -994,8 +998,9 @@ static irqreturn_t arizona_jackdet(int irq, void *data) | |||
994 | 998 | ||
995 | arizona_start_mic(info); | 999 | arizona_start_mic(info); |
996 | } else { | 1000 | } else { |
997 | schedule_delayed_work(&info->hpdet_work, | 1001 | queue_delayed_work(system_power_efficient_wq, |
998 | msecs_to_jiffies(HPDET_DEBOUNCE)); | 1002 | &info->hpdet_work, |
1003 | msecs_to_jiffies(HPDET_DEBOUNCE)); | ||
999 | } | 1004 | } |
1000 | 1005 | ||
1001 | regmap_update_bits(arizona->regmap, | 1006 | regmap_update_bits(arizona->regmap, |
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 18ccadef43fd..1446152bf2e9 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c | |||
@@ -602,7 +602,8 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) | |||
602 | edev->dev->class = extcon_class; | 602 | edev->dev->class = extcon_class; |
603 | edev->dev->release = extcon_dev_release; | 603 | edev->dev->release = extcon_dev_release; |
604 | 604 | ||
605 | dev_set_name(edev->dev, "%s", edev->name ? edev->name : dev_name(dev)); | 605 | edev->name = edev->name ? edev->name : dev_name(dev); |
606 | dev_set_name(edev->dev, "%s", edev->name); | ||
606 | 607 | ||
607 | if (edev->max_supported) { | 608 | if (edev->max_supported) { |
608 | char buf[10]; | 609 | char buf[10]; |
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 02bec32adde4..f874c30ddbff 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c | |||
@@ -56,7 +56,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | |||
56 | { | 56 | { |
57 | struct gpio_extcon_data *extcon_data = dev_id; | 57 | struct gpio_extcon_data *extcon_data = dev_id; |
58 | 58 | ||
59 | schedule_delayed_work(&extcon_data->work, | 59 | queue_delayed_work(system_power_efficient_wq, &extcon_data->work, |
60 | extcon_data->debounce_jiffies); | 60 | extcon_data->debounce_jiffies); |
61 | return IRQ_HANDLED; | 61 | return IRQ_HANDLED; |
62 | } | 62 | } |
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index b752a0ad7b63..89fdd05c5fd6 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c | |||
@@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) | |||
57 | if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { | 57 | if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { |
58 | palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; | 58 | palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; |
59 | extcon_set_cable_state(&palmas_usb->edev, "USB", true); | 59 | extcon_set_cable_state(&palmas_usb->edev, "USB", true); |
60 | dev_info(palmas_usb->dev, "USB cable is attached\n"); | ||
60 | } else { | 61 | } else { |
61 | dev_dbg(palmas_usb->dev, | 62 | dev_dbg(palmas_usb->dev, |
62 | "Spurious connect event detected\n"); | 63 | "Spurious connect event detected\n"); |
@@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) | |||
65 | if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { | 66 | if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { |
66 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | 67 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; |
67 | extcon_set_cable_state(&palmas_usb->edev, "USB", false); | 68 | extcon_set_cable_state(&palmas_usb->edev, "USB", false); |
69 | dev_info(palmas_usb->dev, "USB cable is detached\n"); | ||
68 | } else { | 70 | } else { |
69 | dev_dbg(palmas_usb->dev, | 71 | dev_dbg(palmas_usb->dev, |
70 | "Spurious disconnect event detected\n"); | 72 | "Spurious disconnect event detected\n"); |
@@ -84,28 +86,23 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) | |||
84 | 86 | ||
85 | if (set & PALMAS_USB_ID_INT_SRC_ID_GND) { | 87 | if (set & PALMAS_USB_ID_INT_SRC_ID_GND) { |
86 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 88 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
87 | PALMAS_USB_ID_INT_EN_HI_SET, | ||
88 | PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT); | ||
89 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
90 | PALMAS_USB_ID_INT_EN_HI_CLR, | ||
91 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); | ||
92 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
93 | PALMAS_USB_ID_INT_LATCH_CLR, | 89 | PALMAS_USB_ID_INT_LATCH_CLR, |
94 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); | 90 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); |
95 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; | 91 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; |
96 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); | 92 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); |
93 | dev_info(palmas_usb->dev, "USB-HOST cable is attached\n"); | ||
97 | } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) { | 94 | } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) { |
98 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 95 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
99 | PALMAS_USB_ID_INT_EN_HI_SET, | ||
100 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND); | ||
101 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
102 | PALMAS_USB_ID_INT_EN_HI_CLR, | ||
103 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); | ||
104 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
105 | PALMAS_USB_ID_INT_LATCH_CLR, | 96 | PALMAS_USB_ID_INT_LATCH_CLR, |
106 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); | 97 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); |
107 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | 98 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; |
108 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); | 99 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); |
100 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); | ||
101 | } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) && | ||
102 | (!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) { | ||
103 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | ||
104 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); | ||
105 | dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); | ||
109 | } | 106 | } |
110 | 107 | ||
111 | return IRQ_HANDLED; | 108 | return IRQ_HANDLED; |
@@ -122,13 +119,17 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb) | |||
122 | 119 | ||
123 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | 120 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, |
124 | PALMAS_USB_ID_INT_EN_HI_SET, | 121 | PALMAS_USB_ID_INT_EN_HI_SET, |
125 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND); | 122 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND | |
123 | PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT); | ||
126 | 124 | ||
127 | palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); | 125 | if (palmas_usb->enable_vbus_detection) |
126 | palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); | ||
128 | 127 | ||
129 | /* cold plug for host mode needs this delay */ | 128 | /* cold plug for host mode needs this delay */ |
130 | msleep(30); | 129 | if (palmas_usb->enable_id_detection) { |
131 | palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb); | 130 | msleep(30); |
131 | palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb); | ||
132 | } | ||
132 | } | 133 | } |
133 | 134 | ||
134 | static int palmas_usb_probe(struct platform_device *pdev) | 135 | static int palmas_usb_probe(struct platform_device *pdev) |
@@ -139,21 +140,25 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
139 | struct palmas_usb *palmas_usb; | 140 | struct palmas_usb *palmas_usb; |
140 | int status; | 141 | int status; |
141 | 142 | ||
142 | if (node && !pdata) { | ||
143 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
144 | |||
145 | if (!pdata) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | pdata->wakeup = of_property_read_bool(node, "ti,wakeup"); | ||
149 | } else if (!pdata) { | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); | 143 | palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); |
154 | if (!palmas_usb) | 144 | if (!palmas_usb) |
155 | return -ENOMEM; | 145 | return -ENOMEM; |
156 | 146 | ||
147 | if (node && !pdata) { | ||
148 | palmas_usb->wakeup = of_property_read_bool(node, "ti,wakeup"); | ||
149 | palmas_usb->enable_id_detection = of_property_read_bool(node, | ||
150 | "ti,enable-id-detection"); | ||
151 | palmas_usb->enable_vbus_detection = of_property_read_bool(node, | ||
152 | "ti,enable-vbus-detection"); | ||
153 | } else { | ||
154 | palmas_usb->wakeup = true; | ||
155 | palmas_usb->enable_id_detection = true; | ||
156 | palmas_usb->enable_vbus_detection = true; | ||
157 | |||
158 | if (pdata) | ||
159 | palmas_usb->wakeup = pdata->wakeup; | ||
160 | } | ||
161 | |||
157 | palmas->usb = palmas_usb; | 162 | palmas->usb = palmas_usb; |
158 | palmas_usb->palmas = palmas; | 163 | palmas_usb->palmas = palmas; |
159 | 164 | ||
@@ -168,11 +173,10 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
168 | palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, | 173 | palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, |
169 | PALMAS_VBUS_IRQ); | 174 | PALMAS_VBUS_IRQ); |
170 | 175 | ||
171 | palmas_usb_wakeup(palmas, pdata->wakeup); | 176 | palmas_usb_wakeup(palmas, palmas_usb->wakeup); |
172 | 177 | ||
173 | platform_set_drvdata(pdev, palmas_usb); | 178 | platform_set_drvdata(pdev, palmas_usb); |
174 | 179 | ||
175 | palmas_usb->edev.name = "palmas-usb"; | ||
176 | palmas_usb->edev.supported_cable = palmas_extcon_cable; | 180 | palmas_usb->edev.supported_cable = palmas_extcon_cable; |
177 | palmas_usb->edev.mutually_exclusive = mutually_exclusive; | 181 | palmas_usb->edev.mutually_exclusive = mutually_exclusive; |
178 | 182 | ||
@@ -182,28 +186,36 @@ static int palmas_usb_probe(struct platform_device *pdev) | |||
182 | return status; | 186 | return status; |
183 | } | 187 | } |
184 | 188 | ||
185 | status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, | 189 | if (palmas_usb->enable_id_detection) { |
186 | NULL, palmas_id_irq_handler, | 190 | status = devm_request_threaded_irq(palmas_usb->dev, |
187 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 191 | palmas_usb->id_irq, |
188 | "palmas_usb_id", palmas_usb); | 192 | NULL, palmas_id_irq_handler, |
189 | if (status < 0) { | 193 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | |
190 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 194 | IRQF_ONESHOT | IRQF_EARLY_RESUME, |
195 | "palmas_usb_id", palmas_usb); | ||
196 | if (status < 0) { | ||
197 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
191 | palmas_usb->id_irq, status); | 198 | palmas_usb->id_irq, status); |
192 | goto fail_extcon; | 199 | goto fail_extcon; |
200 | } | ||
193 | } | 201 | } |
194 | 202 | ||
195 | status = devm_request_threaded_irq(palmas_usb->dev, | 203 | if (palmas_usb->enable_vbus_detection) { |
196 | palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, | 204 | status = devm_request_threaded_irq(palmas_usb->dev, |
197 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 205 | palmas_usb->vbus_irq, NULL, |
198 | "palmas_usb_vbus", palmas_usb); | 206 | palmas_vbus_irq_handler, |
199 | if (status < 0) { | 207 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | |
200 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 208 | IRQF_ONESHOT | IRQF_EARLY_RESUME, |
209 | "palmas_usb_vbus", palmas_usb); | ||
210 | if (status < 0) { | ||
211 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
201 | palmas_usb->vbus_irq, status); | 212 | palmas_usb->vbus_irq, status); |
202 | goto fail_extcon; | 213 | goto fail_extcon; |
214 | } | ||
203 | } | 215 | } |
204 | 216 | ||
205 | palmas_enable_irq(palmas_usb); | 217 | palmas_enable_irq(palmas_usb); |
206 | 218 | device_set_wakeup_capable(&pdev->dev, true); | |
207 | return 0; | 219 | return 0; |
208 | 220 | ||
209 | fail_extcon: | 221 | fail_extcon: |
@@ -221,6 +233,39 @@ static int palmas_usb_remove(struct platform_device *pdev) | |||
221 | return 0; | 233 | return 0; |
222 | } | 234 | } |
223 | 235 | ||
236 | #ifdef CONFIG_PM_SLEEP | ||
237 | static int palmas_usb_suspend(struct device *dev) | ||
238 | { | ||
239 | struct palmas_usb *palmas_usb = dev_get_drvdata(dev); | ||
240 | |||
241 | if (device_may_wakeup(dev)) { | ||
242 | if (palmas_usb->enable_vbus_detection) | ||
243 | enable_irq_wake(palmas_usb->vbus_irq); | ||
244 | if (palmas_usb->enable_id_detection) | ||
245 | enable_irq_wake(palmas_usb->id_irq); | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int palmas_usb_resume(struct device *dev) | ||
251 | { | ||
252 | struct palmas_usb *palmas_usb = dev_get_drvdata(dev); | ||
253 | |||
254 | if (device_may_wakeup(dev)) { | ||
255 | if (palmas_usb->enable_vbus_detection) | ||
256 | disable_irq_wake(palmas_usb->vbus_irq); | ||
257 | if (palmas_usb->enable_id_detection) | ||
258 | disable_irq_wake(palmas_usb->id_irq); | ||
259 | } | ||
260 | return 0; | ||
261 | }; | ||
262 | #endif | ||
263 | |||
264 | static const struct dev_pm_ops palmas_pm_ops = { | ||
265 | SET_SYSTEM_SLEEP_PM_OPS(palmas_usb_suspend, | ||
266 | palmas_usb_resume) | ||
267 | }; | ||
268 | |||
224 | static struct of_device_id of_palmas_match_tbl[] = { | 269 | static struct of_device_id of_palmas_match_tbl[] = { |
225 | { .compatible = "ti,palmas-usb", }, | 270 | { .compatible = "ti,palmas-usb", }, |
226 | { .compatible = "ti,twl6035-usb", }, | 271 | { .compatible = "ti,twl6035-usb", }, |
@@ -234,6 +279,7 @@ static struct platform_driver palmas_usb_driver = { | |||
234 | .name = "palmas-usb", | 279 | .name = "palmas-usb", |
235 | .of_match_table = of_palmas_match_tbl, | 280 | .of_match_table = of_palmas_match_tbl, |
236 | .owner = THIS_MODULE, | 281 | .owner = THIS_MODULE, |
282 | .pm = &palmas_pm_ops, | ||
237 | }, | 283 | }, |
238 | }; | 284 | }; |
239 | 285 | ||
diff --git a/drivers/extcon/of_extcon.c b/drivers/extcon/of_extcon.c new file mode 100644 index 000000000000..72173ecbb311 --- /dev/null +++ b/drivers/extcon/of_extcon.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * OF helpers for External connector (extcon) framework | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments, Inc. | ||
5 | * Kishon Vijay Abraham I <kishon@ti.com> | ||
6 | * | ||
7 | * Copyright (C) 2013 Samsung Electronics | ||
8 | * Chanwoo Choi <cw00.choi@samsung.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/extcon.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | #include <linux/extcon/of_extcon.h> | ||
23 | |||
24 | /* | ||
25 | * of_extcon_get_extcon_dev - Get the name of extcon device from devicetree | ||
26 | * @dev - instance to the given device | ||
27 | * @index - index into list of extcon_dev | ||
28 | * | ||
29 | * return the instance of extcon device | ||
30 | */ | ||
31 | struct extcon_dev *of_extcon_get_extcon_dev(struct device *dev, int index) | ||
32 | { | ||
33 | struct device_node *node; | ||
34 | struct extcon_dev *edev; | ||
35 | struct platform_device *extcon_parent_dev; | ||
36 | |||
37 | if (!dev->of_node) { | ||
38 | dev_dbg(dev, "device does not have a device node entry\n"); | ||
39 | return ERR_PTR(-EINVAL); | ||
40 | } | ||
41 | |||
42 | node = of_parse_phandle(dev->of_node, "extcon", index); | ||
43 | if (!node) { | ||
44 | dev_dbg(dev, "failed to get phandle in %s node\n", | ||
45 | dev->of_node->full_name); | ||
46 | return ERR_PTR(-ENODEV); | ||
47 | } | ||
48 | |||
49 | extcon_parent_dev = of_find_device_by_node(node); | ||
50 | if (!extcon_parent_dev) { | ||
51 | dev_dbg(dev, "unable to find device by node\n"); | ||
52 | return ERR_PTR(-EPROBE_DEFER); | ||
53 | } | ||
54 | |||
55 | edev = extcon_get_extcon_dev(dev_name(&extcon_parent_dev->dev)); | ||
56 | if (!edev) { | ||
57 | dev_dbg(dev, "unable to get extcon device : %s\n", | ||
58 | dev_name(&extcon_parent_dev->dev)); | ||
59 | return ERR_PTR(-ENODEV); | ||
60 | } | ||
61 | |||
62 | return edev; | ||
63 | } | ||
64 | EXPORT_SYMBOL_GPL(of_extcon_get_extcon_dev); | ||
diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c index cc031db2d2a3..ace6ef24d15e 100644 --- a/drivers/fmc/fmc-chardev.c +++ b/drivers/fmc/fmc-chardev.c | |||
@@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc) | |||
143 | fc->misc.fops = &fc_fops; | 143 | fc->misc.fops = &fc_fops; |
144 | fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); | 144 | fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); |
145 | 145 | ||
146 | spin_lock(&fc_lock); | ||
147 | ret = misc_register(&fc->misc); | 146 | ret = misc_register(&fc->misc); |
148 | if (ret < 0) | 147 | if (ret < 0) |
149 | goto err_unlock; | 148 | goto out; |
149 | spin_lock(&fc_lock); | ||
150 | list_add(&fc->list, &fc_devices); | 150 | list_add(&fc->list, &fc_devices); |
151 | spin_unlock(&fc_lock); | 151 | spin_unlock(&fc_lock); |
152 | dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", | 152 | dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", |
153 | fc->misc.name); | 153 | fc->misc.name); |
154 | return 0; | 154 | return 0; |
155 | 155 | ||
156 | err_unlock: | 156 | out: |
157 | spin_unlock(&fc_lock); | ||
158 | kfree(fc->misc.name); | 157 | kfree(fc->misc.name); |
159 | kfree(fc); | 158 | kfree(fc); |
160 | return ret; | 159 | return ret; |
@@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc) | |||
174 | 173 | ||
175 | spin_lock(&fc_lock); | 174 | spin_lock(&fc_lock); |
176 | list_del(&fc->list); | 175 | list_del(&fc->list); |
176 | spin_unlock(&fc_lock); | ||
177 | misc_deregister(&fc->misc); | 177 | misc_deregister(&fc->misc); |
178 | kfree(fc->misc.name); | 178 | kfree(fc->misc.name); |
179 | kfree(fc); | 179 | kfree(fc); |
180 | spin_unlock(&fc_lock); | ||
181 | 180 | ||
182 | return 0; | 181 | return 0; |
183 | } | 182 | } |
diff --git a/drivers/fmc/fmc-write-eeprom.c b/drivers/fmc/fmc-write-eeprom.c index 2cc680dd604d..ee5b47904130 100644 --- a/drivers/fmc/fmc-write-eeprom.c +++ b/drivers/fmc/fmc-write-eeprom.c | |||
@@ -103,7 +103,7 @@ static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s) | |||
103 | * difficult to know in advance when probing the first card if others | 103 | * difficult to know in advance when probing the first card if others |
104 | * are there. | 104 | * are there. |
105 | */ | 105 | */ |
106 | int fwe_probe(struct fmc_device *fmc) | 106 | static int fwe_probe(struct fmc_device *fmc) |
107 | { | 107 | { |
108 | int err, index = 0; | 108 | int err, index = 0; |
109 | const struct firmware *fw; | 109 | const struct firmware *fw; |
@@ -144,7 +144,7 @@ int fwe_probe(struct fmc_device *fmc) | |||
144 | return 0; | 144 | return 0; |
145 | } | 145 | } |
146 | 146 | ||
147 | int fwe_remove(struct fmc_device *fmc) | 147 | static int fwe_remove(struct fmc_device *fmc) |
148 | { | 148 | { |
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 713217380b44..8fae6d1414cc 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c | |||
@@ -590,6 +590,5 @@ static void __exit mousevsc_exit(void) | |||
590 | } | 590 | } |
591 | 591 | ||
592 | MODULE_LICENSE("GPL"); | 592 | MODULE_LICENSE("GPL"); |
593 | MODULE_VERSION(HV_DRV_VERSION); | ||
594 | module_init(mousevsc_init); | 593 | module_init(mousevsc_init); |
595 | module_exit(mousevsc_exit); | 594 | module_exit(mousevsc_exit); |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 0df75908200e..bbff5f200bef 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry { | |||
48 | * @negop is of type &struct icmsg_negotiate. | 48 | * @negop is of type &struct icmsg_negotiate. |
49 | * Set up and fill in default negotiate response message. | 49 | * Set up and fill in default negotiate response message. |
50 | * | 50 | * |
51 | * The max_fw_version specifies the maximum framework version that | 51 | * The fw_version specifies the framework version that |
52 | * we can support and max _srv_version specifies the maximum service | 52 | * we can support and srv_version specifies the service |
53 | * version we can support. A special value MAX_SRV_VER can be | 53 | * version we can support. |
54 | * specified to indicate that we can handle the maximum version | ||
55 | * exposed by the host. | ||
56 | * | 54 | * |
57 | * Mainly used by Hyper-V drivers. | 55 | * Mainly used by Hyper-V drivers. |
58 | */ | 56 | */ |
59 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | 57 | bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, |
60 | struct icmsg_negotiate *negop, u8 *buf, | 58 | struct icmsg_negotiate *negop, u8 *buf, |
61 | int max_fw_version, int max_srv_version) | 59 | int fw_version, int srv_version) |
62 | { | 60 | { |
63 | int icframe_vercnt; | 61 | int icframe_major, icframe_minor; |
64 | int icmsg_vercnt; | 62 | int icmsg_major, icmsg_minor; |
63 | int fw_major, fw_minor; | ||
64 | int srv_major, srv_minor; | ||
65 | int i; | 65 | int i; |
66 | bool found_match = false; | ||
66 | 67 | ||
67 | icmsghdrp->icmsgsize = 0x10; | 68 | icmsghdrp->icmsgsize = 0x10; |
69 | fw_major = (fw_version >> 16); | ||
70 | fw_minor = (fw_version & 0xFFFF); | ||
71 | |||
72 | srv_major = (srv_version >> 16); | ||
73 | srv_minor = (srv_version & 0xFFFF); | ||
68 | 74 | ||
69 | negop = (struct icmsg_negotiate *)&buf[ | 75 | negop = (struct icmsg_negotiate *)&buf[ |
70 | sizeof(struct vmbuspipe_hdr) + | 76 | sizeof(struct vmbuspipe_hdr) + |
71 | sizeof(struct icmsg_hdr)]; | 77 | sizeof(struct icmsg_hdr)]; |
72 | 78 | ||
73 | icframe_vercnt = negop->icframe_vercnt; | 79 | icframe_major = negop->icframe_vercnt; |
74 | icmsg_vercnt = negop->icmsg_vercnt; | 80 | icframe_minor = 0; |
81 | |||
82 | icmsg_major = negop->icmsg_vercnt; | ||
83 | icmsg_minor = 0; | ||
75 | 84 | ||
76 | /* | 85 | /* |
77 | * Select the framework version number we will | 86 | * Select the framework version number we will |
@@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | |||
79 | */ | 88 | */ |
80 | 89 | ||
81 | for (i = 0; i < negop->icframe_vercnt; i++) { | 90 | for (i = 0; i < negop->icframe_vercnt; i++) { |
82 | if (negop->icversion_data[i].major <= max_fw_version) | 91 | if ((negop->icversion_data[i].major == fw_major) && |
83 | icframe_vercnt = negop->icversion_data[i].major; | 92 | (negop->icversion_data[i].minor == fw_minor)) { |
93 | icframe_major = negop->icversion_data[i].major; | ||
94 | icframe_minor = negop->icversion_data[i].minor; | ||
95 | found_match = true; | ||
96 | } | ||
84 | } | 97 | } |
85 | 98 | ||
99 | if (!found_match) | ||
100 | goto fw_error; | ||
101 | |||
102 | found_match = false; | ||
103 | |||
86 | for (i = negop->icframe_vercnt; | 104 | for (i = negop->icframe_vercnt; |
87 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { | 105 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { |
88 | if (negop->icversion_data[i].major <= max_srv_version) | 106 | if ((negop->icversion_data[i].major == srv_major) && |
89 | icmsg_vercnt = negop->icversion_data[i].major; | 107 | (negop->icversion_data[i].minor == srv_minor)) { |
108 | icmsg_major = negop->icversion_data[i].major; | ||
109 | icmsg_minor = negop->icversion_data[i].minor; | ||
110 | found_match = true; | ||
111 | } | ||
90 | } | 112 | } |
91 | 113 | ||
92 | /* | 114 | /* |
93 | * Respond with the maximum framework and service | 115 | * Respond with the framework and service |
94 | * version numbers we can support. | 116 | * version numbers we can support. |
95 | */ | 117 | */ |
96 | negop->icframe_vercnt = 1; | 118 | |
97 | negop->icmsg_vercnt = 1; | 119 | fw_error: |
98 | negop->icversion_data[0].major = icframe_vercnt; | 120 | if (!found_match) { |
99 | negop->icversion_data[0].minor = 0; | 121 | negop->icframe_vercnt = 0; |
100 | negop->icversion_data[1].major = icmsg_vercnt; | 122 | negop->icmsg_vercnt = 0; |
101 | negop->icversion_data[1].minor = 0; | 123 | } else { |
124 | negop->icframe_vercnt = 1; | ||
125 | negop->icmsg_vercnt = 1; | ||
126 | } | ||
127 | |||
128 | negop->icversion_data[0].major = icframe_major; | ||
129 | negop->icversion_data[0].minor = icframe_minor; | ||
130 | negop->icversion_data[1].major = icmsg_major; | ||
131 | negop->icversion_data[1].minor = icmsg_minor; | ||
132 | return found_match; | ||
102 | } | 133 | } |
103 | 134 | ||
104 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); | 135 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
@@ -262,6 +293,13 @@ static void vmbus_process_offer(struct work_struct *work) | |||
262 | } | 293 | } |
263 | 294 | ||
264 | /* | 295 | /* |
296 | * This state is used to indicate a successful open | ||
297 | * so that when we do close the channel normally, we | ||
298 | * can cleanup properly | ||
299 | */ | ||
300 | newchannel->state = CHANNEL_OPEN_STATE; | ||
301 | |||
302 | /* | ||
265 | * Start the process of binding this offer to the driver | 303 | * Start the process of binding this offer to the driver |
266 | * We need to set the DeviceObject field before calling | 304 | * We need to set the DeviceObject field before calling |
267 | * vmbus_child_dev_add() | 305 | * vmbus_child_dev_add() |
@@ -287,13 +325,6 @@ static void vmbus_process_offer(struct work_struct *work) | |||
287 | kfree(newchannel->device_obj); | 325 | kfree(newchannel->device_obj); |
288 | 326 | ||
289 | free_channel(newchannel); | 327 | free_channel(newchannel); |
290 | } else { | ||
291 | /* | ||
292 | * This state is used to indicate a successful open | ||
293 | * so that when we do close the channel normally, we | ||
294 | * can cleanup properly | ||
295 | */ | ||
296 | newchannel->state = CHANNEL_OPEN_STATE; | ||
297 | } | 328 | } |
298 | } | 329 | } |
299 | 330 | ||
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index ec3b8cdf1e04..8f4743ab5fb2 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c | |||
@@ -195,7 +195,10 @@ int vmbus_connect(void) | |||
195 | 195 | ||
196 | do { | 196 | do { |
197 | ret = vmbus_negotiate_version(msginfo, version); | 197 | ret = vmbus_negotiate_version(msginfo, version); |
198 | if (ret == 0) | 198 | if (ret) |
199 | goto cleanup; | ||
200 | |||
201 | if (vmbus_connection.conn_state == CONNECTED) | ||
199 | break; | 202 | break; |
200 | 203 | ||
201 | version = vmbus_get_next_version(version); | 204 | version = vmbus_get_next_version(version); |
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index deb5c25305af..7e17a5495e02 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c | |||
@@ -825,7 +825,6 @@ static void hot_add_req(struct work_struct *dummy) | |||
825 | memset(&resp, 0, sizeof(struct dm_hot_add_response)); | 825 | memset(&resp, 0, sizeof(struct dm_hot_add_response)); |
826 | resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE; | 826 | resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE; |
827 | resp.hdr.size = sizeof(struct dm_hot_add_response); | 827 | resp.hdr.size = sizeof(struct dm_hot_add_response); |
828 | resp.hdr.trans_id = atomic_inc_return(&trans_id); | ||
829 | 828 | ||
830 | #ifdef CONFIG_MEMORY_HOTPLUG | 829 | #ifdef CONFIG_MEMORY_HOTPLUG |
831 | pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; | 830 | 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 | pr_info("Memory hot add failed\n"); | 886 | pr_info("Memory hot add failed\n"); |
888 | 887 | ||
889 | dm->state = DM_INITIALIZED; | 888 | dm->state = DM_INITIALIZED; |
889 | resp.hdr.trans_id = atomic_inc_return(&trans_id); | ||
890 | vmbus_sendpacket(dm->dev->channel, &resp, | 890 | vmbus_sendpacket(dm->dev->channel, &resp, |
891 | sizeof(struct dm_hot_add_response), | 891 | sizeof(struct dm_hot_add_response), |
892 | (unsigned long)NULL, | 892 | (unsigned long)NULL, |
@@ -1081,7 +1081,6 @@ static void balloon_up(struct work_struct *dummy) | |||
1081 | bl_resp = (struct dm_balloon_response *)send_buffer; | 1081 | bl_resp = (struct dm_balloon_response *)send_buffer; |
1082 | memset(send_buffer, 0, PAGE_SIZE); | 1082 | memset(send_buffer, 0, PAGE_SIZE); |
1083 | bl_resp->hdr.type = DM_BALLOON_RESPONSE; | 1083 | bl_resp->hdr.type = DM_BALLOON_RESPONSE; |
1084 | bl_resp->hdr.trans_id = atomic_inc_return(&trans_id); | ||
1085 | bl_resp->hdr.size = sizeof(struct dm_balloon_response); | 1084 | bl_resp->hdr.size = sizeof(struct dm_balloon_response); |
1086 | bl_resp->more_pages = 1; | 1085 | bl_resp->more_pages = 1; |
1087 | 1086 | ||
@@ -1109,6 +1108,7 @@ static void balloon_up(struct work_struct *dummy) | |||
1109 | */ | 1108 | */ |
1110 | 1109 | ||
1111 | do { | 1110 | do { |
1111 | bl_resp->hdr.trans_id = atomic_inc_return(&trans_id); | ||
1112 | ret = vmbus_sendpacket(dm_device.dev->channel, | 1112 | ret = vmbus_sendpacket(dm_device.dev->channel, |
1113 | bl_resp, | 1113 | bl_resp, |
1114 | bl_resp->hdr.size, | 1114 | bl_resp->hdr.size, |
@@ -1526,5 +1526,4 @@ static int __init init_balloon_drv(void) | |||
1526 | module_init(init_balloon_drv); | 1526 | module_init(init_balloon_drv); |
1527 | 1527 | ||
1528 | MODULE_DESCRIPTION("Hyper-V Balloon"); | 1528 | MODULE_DESCRIPTION("Hyper-V Balloon"); |
1529 | MODULE_VERSION(HV_DRV_VERSION); | ||
1530 | MODULE_LICENSE("GPL"); | 1529 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index ed50e9e83c61..28b03325b872 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -29,6 +29,16 @@ | |||
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | 31 | ||
32 | /* | ||
33 | * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7) | ||
34 | */ | ||
35 | #define WIN7_SRV_MAJOR 3 | ||
36 | #define WIN7_SRV_MINOR 0 | ||
37 | #define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR) | ||
38 | |||
39 | #define WIN8_SRV_MAJOR 4 | ||
40 | #define WIN8_SRV_MINOR 0 | ||
41 | #define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) | ||
32 | 42 | ||
33 | /* | 43 | /* |
34 | * Global state maintained for transaction that is being processed. | 44 | * Global state maintained for transaction that is being processed. |
@@ -76,7 +86,9 @@ static u8 *recv_buffer; | |||
76 | /* | 86 | /* |
77 | * Register the kernel component with the user-level daemon. | 87 | * Register the kernel component with the user-level daemon. |
78 | * As part of this registration, pass the LIC version number. | 88 | * As part of this registration, pass the LIC version number. |
89 | * This number has no meaning, it satisfies the registration protocol. | ||
79 | */ | 90 | */ |
91 | #define HV_DRV_VERSION "3.1" | ||
80 | 92 | ||
81 | static void | 93 | static void |
82 | kvp_register(int reg_value) | 94 | kvp_register(int reg_value) |
@@ -593,8 +605,19 @@ void hv_kvp_onchannelcallback(void *context) | |||
593 | sizeof(struct vmbuspipe_hdr)]; | 605 | sizeof(struct vmbuspipe_hdr)]; |
594 | 606 | ||
595 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 607 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
608 | /* | ||
609 | * We start with win8 version and if the host cannot | ||
610 | * support that we use the previous version. | ||
611 | */ | ||
612 | if (vmbus_prep_negotiate_resp(icmsghdrp, negop, | ||
613 | recv_buffer, UTIL_FW_MAJOR_MINOR, | ||
614 | WIN8_SRV_MAJOR_MINOR)) | ||
615 | goto done; | ||
616 | |||
596 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 617 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
597 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | 618 | recv_buffer, UTIL_FW_MAJOR_MINOR, |
619 | WIN7_SRV_MAJOR_MINOR); | ||
620 | |||
598 | } else { | 621 | } else { |
599 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ | 622 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ |
600 | sizeof(struct vmbuspipe_hdr) + | 623 | sizeof(struct vmbuspipe_hdr) + |
@@ -626,6 +649,7 @@ void hv_kvp_onchannelcallback(void *context) | |||
626 | return; | 649 | return; |
627 | 650 | ||
628 | } | 651 | } |
652 | done: | ||
629 | 653 | ||
630 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | 654 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION |
631 | | ICMSGHDRFLAG_RESPONSE; | 655 | | ICMSGHDRFLAG_RESPONSE; |
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 8ad5653ce447..e4572f3f2834 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c | |||
@@ -24,6 +24,10 @@ | |||
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/hyperv.h> | 25 | #include <linux/hyperv.h> |
26 | 26 | ||
27 | #define VSS_MAJOR 5 | ||
28 | #define VSS_MINOR 0 | ||
29 | #define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR) | ||
30 | |||
27 | 31 | ||
28 | 32 | ||
29 | /* | 33 | /* |
@@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context) | |||
186 | 190 | ||
187 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 191 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
188 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 192 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
189 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | 193 | recv_buffer, UTIL_FW_MAJOR_MINOR, |
190 | /* | 194 | VSS_MAJOR_MINOR); |
191 | * We currently negotiate the highest number the | ||
192 | * host has presented. If this version is not | ||
193 | * atleast 5.0, reject. | ||
194 | */ | ||
195 | negop = (struct icmsg_negotiate *)&recv_buffer[ | ||
196 | sizeof(struct vmbuspipe_hdr) + | ||
197 | sizeof(struct icmsg_hdr)]; | ||
198 | |||
199 | if (negop->icversion_data[1].major < 5) | ||
200 | negop->icframe_vercnt = 0; | ||
201 | } else { | 195 | } else { |
202 | vss_msg = (struct hv_vss_msg *)&recv_buffer[ | 196 | vss_msg = (struct hv_vss_msg *)&recv_buffer[ |
203 | sizeof(struct vmbuspipe_hdr) + | 197 | sizeof(struct vmbuspipe_hdr) + |
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 2f561c5dfe24..cb82233541b1 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -28,6 +28,18 @@ | |||
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #define SHUTDOWN_MAJOR 3 | ||
32 | #define SHUTDOWN_MINOR 0 | ||
33 | #define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR) | ||
34 | |||
35 | #define TIMESYNCH_MAJOR 3 | ||
36 | #define TIMESYNCH_MINOR 0 | ||
37 | #define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR) | ||
38 | |||
39 | #define HEARTBEAT_MAJOR 3 | ||
40 | #define HEARTBEAT_MINOR 0 | ||
41 | #define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR) | ||
42 | |||
31 | static void shutdown_onchannelcallback(void *context); | 43 | static void shutdown_onchannelcallback(void *context); |
32 | static struct hv_util_service util_shutdown = { | 44 | static struct hv_util_service util_shutdown = { |
33 | .util_cb = shutdown_onchannelcallback, | 45 | .util_cb = shutdown_onchannelcallback, |
@@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context) | |||
87 | 99 | ||
88 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 100 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
89 | vmbus_prep_negotiate_resp(icmsghdrp, negop, | 101 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
90 | shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | 102 | shut_txf_buf, UTIL_FW_MAJOR_MINOR, |
103 | SHUTDOWN_MAJOR_MINOR); | ||
91 | } else { | 104 | } else { |
92 | shutdown_msg = | 105 | shutdown_msg = |
93 | (struct shutdown_msg_data *)&shut_txf_buf[ | 106 | (struct shutdown_msg_data *)&shut_txf_buf[ |
@@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context) | |||
213 | 226 | ||
214 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 227 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
215 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, | 228 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, |
216 | MAX_SRV_VER, MAX_SRV_VER); | 229 | UTIL_FW_MAJOR_MINOR, |
230 | TIMESYNCH_MAJOR_MINOR); | ||
217 | } else { | 231 | } else { |
218 | timedatap = (struct ictimesync_data *)&time_txf_buf[ | 232 | timedatap = (struct ictimesync_data *)&time_txf_buf[ |
219 | sizeof(struct vmbuspipe_hdr) + | 233 | sizeof(struct vmbuspipe_hdr) + |
@@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context) | |||
253 | 267 | ||
254 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 268 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
255 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, | 269 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, |
256 | hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | 270 | hbeat_txf_buf, UTIL_FW_MAJOR_MINOR, |
271 | HEARTBEAT_MAJOR_MINOR); | ||
257 | } else { | 272 | } else { |
258 | heartbeat_msg = | 273 | heartbeat_msg = |
259 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ | 274 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ |
@@ -380,5 +395,4 @@ module_init(init_hyperv_utils); | |||
380 | module_exit(exit_hyperv_utils); | 395 | module_exit(exit_hyperv_utils); |
381 | 396 | ||
382 | MODULE_DESCRIPTION("Hyper-V Utilities"); | 397 | MODULE_DESCRIPTION("Hyper-V Utilities"); |
383 | MODULE_VERSION(HV_DRV_VERSION); | ||
384 | MODULE_LICENSE("GPL"); | 398 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e8e071fc1d6d..f9fe46f52cfa 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -816,7 +816,6 @@ static void __exit vmbus_exit(void) | |||
816 | 816 | ||
817 | 817 | ||
818 | MODULE_LICENSE("GPL"); | 818 | MODULE_LICENSE("GPL"); |
819 | MODULE_VERSION(HV_DRV_VERSION); | ||
820 | 819 | ||
821 | subsys_initcall(hv_acpi_init); | 820 | subsys_initcall(hv_acpi_init); |
822 | module_exit(vmbus_exit); | 821 | module_exit(vmbus_exit); |
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index e068a76a5f6f..5be808406edc 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | 20 | ||
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/pinctrl/consumer.h> | ||
23 | 22 | ||
24 | /* Serialize access to ssc_list and user count */ | 23 | /* Serialize access to ssc_list and user count */ |
25 | static DEFINE_SPINLOCK(user_lock); | 24 | static DEFINE_SPINLOCK(user_lock); |
@@ -137,13 +136,6 @@ static int ssc_probe(struct platform_device *pdev) | |||
137 | struct resource *regs; | 136 | struct resource *regs; |
138 | struct ssc_device *ssc; | 137 | struct ssc_device *ssc; |
139 | const struct atmel_ssc_platform_data *plat_dat; | 138 | const struct atmel_ssc_platform_data *plat_dat; |
140 | struct pinctrl *pinctrl; | ||
141 | |||
142 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
143 | if (IS_ERR(pinctrl)) { | ||
144 | dev_err(&pdev->dev, "Failed to request pinctrl\n"); | ||
145 | return PTR_ERR(pinctrl); | ||
146 | } | ||
147 | 139 | ||
148 | ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); | 140 | ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); |
149 | if (!ssc) { | 141 | if (!ssc) { |
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 621c7a373390..b83e3ca12a41 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -759,7 +759,7 @@ static int ilo_probe(struct pci_dev *pdev, | |||
759 | 759 | ||
760 | /* Ignore subsystem_device = 0x1979 (set by BIOS) */ | 760 | /* Ignore subsystem_device = 0x1979 (set by BIOS) */ |
761 | if (pdev->subsystem_device == 0x1979) | 761 | if (pdev->subsystem_device == 0x1979) |
762 | goto out; | 762 | return 0; |
763 | 763 | ||
764 | if (max_ccb > MAX_CCB) | 764 | if (max_ccb > MAX_CCB) |
765 | max_ccb = MAX_CCB; | 765 | max_ccb = MAX_CCB; |
@@ -899,7 +899,7 @@ static void __exit ilo_exit(void) | |||
899 | class_destroy(ilo_class); | 899 | class_destroy(ilo_class); |
900 | } | 900 | } |
901 | 901 | ||
902 | MODULE_VERSION("1.4"); | 902 | MODULE_VERSION("1.4.1"); |
903 | MODULE_ALIAS(ILO_NAME); | 903 | MODULE_ALIAS(ILO_NAME); |
904 | MODULE_DESCRIPTION(ILO_NAME); | 904 | MODULE_DESCRIPTION(ILO_NAME); |
905 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); | 905 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 08aad69c8da4..2fc0586ce3bb 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <scsi/scsi_cmnd.h> | 44 | #include <scsi/scsi_cmnd.h> |
45 | #include <linux/debugfs.h> | 45 | #include <linux/debugfs.h> |
46 | #include <linux/vmalloc.h> | ||
46 | 47 | ||
47 | #ifdef CONFIG_IDE | 48 | #ifdef CONFIG_IDE |
48 | #include <linux/ide.h> | 49 | #include <linux/ide.h> |
@@ -50,6 +51,7 @@ | |||
50 | 51 | ||
51 | #define DEFAULT_COUNT 10 | 52 | #define DEFAULT_COUNT 10 |
52 | #define REC_NUM_DEFAULT 10 | 53 | #define REC_NUM_DEFAULT 10 |
54 | #define EXEC_SIZE 64 | ||
53 | 55 | ||
54 | enum cname { | 56 | enum cname { |
55 | CN_INVALID, | 57 | CN_INVALID, |
@@ -68,6 +70,7 @@ enum ctype { | |||
68 | CT_NONE, | 70 | CT_NONE, |
69 | CT_PANIC, | 71 | CT_PANIC, |
70 | CT_BUG, | 72 | CT_BUG, |
73 | CT_WARNING, | ||
71 | CT_EXCEPTION, | 74 | CT_EXCEPTION, |
72 | CT_LOOP, | 75 | CT_LOOP, |
73 | CT_OVERFLOW, | 76 | CT_OVERFLOW, |
@@ -77,7 +80,12 @@ enum ctype { | |||
77 | CT_WRITE_AFTER_FREE, | 80 | CT_WRITE_AFTER_FREE, |
78 | CT_SOFTLOCKUP, | 81 | CT_SOFTLOCKUP, |
79 | CT_HARDLOCKUP, | 82 | CT_HARDLOCKUP, |
83 | CT_SPINLOCKUP, | ||
80 | CT_HUNG_TASK, | 84 | CT_HUNG_TASK, |
85 | CT_EXEC_DATA, | ||
86 | CT_EXEC_STACK, | ||
87 | CT_EXEC_KMALLOC, | ||
88 | CT_EXEC_VMALLOC, | ||
81 | }; | 89 | }; |
82 | 90 | ||
83 | static char* cp_name[] = { | 91 | static char* cp_name[] = { |
@@ -95,6 +103,7 @@ static char* cp_name[] = { | |||
95 | static char* cp_type[] = { | 103 | static char* cp_type[] = { |
96 | "PANIC", | 104 | "PANIC", |
97 | "BUG", | 105 | "BUG", |
106 | "WARNING", | ||
98 | "EXCEPTION", | 107 | "EXCEPTION", |
99 | "LOOP", | 108 | "LOOP", |
100 | "OVERFLOW", | 109 | "OVERFLOW", |
@@ -104,7 +113,12 @@ static char* cp_type[] = { | |||
104 | "WRITE_AFTER_FREE", | 113 | "WRITE_AFTER_FREE", |
105 | "SOFTLOCKUP", | 114 | "SOFTLOCKUP", |
106 | "HARDLOCKUP", | 115 | "HARDLOCKUP", |
116 | "SPINLOCKUP", | ||
107 | "HUNG_TASK", | 117 | "HUNG_TASK", |
118 | "EXEC_DATA", | ||
119 | "EXEC_STACK", | ||
120 | "EXEC_KMALLOC", | ||
121 | "EXEC_VMALLOC", | ||
108 | }; | 122 | }; |
109 | 123 | ||
110 | static struct jprobe lkdtm; | 124 | static struct jprobe lkdtm; |
@@ -121,6 +135,9 @@ static enum cname cpoint = CN_INVALID; | |||
121 | static enum ctype cptype = CT_NONE; | 135 | static enum ctype cptype = CT_NONE; |
122 | static int count = DEFAULT_COUNT; | 136 | static int count = DEFAULT_COUNT; |
123 | static DEFINE_SPINLOCK(count_lock); | 137 | static DEFINE_SPINLOCK(count_lock); |
138 | static DEFINE_SPINLOCK(lock_me_up); | ||
139 | |||
140 | static u8 data_area[EXEC_SIZE]; | ||
124 | 141 | ||
125 | module_param(recur_count, int, 0644); | 142 | module_param(recur_count, int, 0644); |
126 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ | 143 | MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ |
@@ -275,6 +292,19 @@ static int recursive_loop(int a) | |||
275 | return recursive_loop(a); | 292 | return recursive_loop(a); |
276 | } | 293 | } |
277 | 294 | ||
295 | static void do_nothing(void) | ||
296 | { | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | static void execute_location(void *dst) | ||
301 | { | ||
302 | void (*func)(void) = dst; | ||
303 | |||
304 | memcpy(dst, do_nothing, EXEC_SIZE); | ||
305 | func(); | ||
306 | } | ||
307 | |||
278 | static void lkdtm_do_action(enum ctype which) | 308 | static void lkdtm_do_action(enum ctype which) |
279 | { | 309 | { |
280 | switch (which) { | 310 | switch (which) { |
@@ -284,6 +314,9 @@ static void lkdtm_do_action(enum ctype which) | |||
284 | case CT_BUG: | 314 | case CT_BUG: |
285 | BUG(); | 315 | BUG(); |
286 | break; | 316 | break; |
317 | case CT_WARNING: | ||
318 | WARN_ON(1); | ||
319 | break; | ||
287 | case CT_EXCEPTION: | 320 | case CT_EXCEPTION: |
288 | *((int *) 0) = 0; | 321 | *((int *) 0) = 0; |
289 | break; | 322 | break; |
@@ -295,10 +328,10 @@ static void lkdtm_do_action(enum ctype which) | |||
295 | (void) recursive_loop(0); | 328 | (void) recursive_loop(0); |
296 | break; | 329 | break; |
297 | case CT_CORRUPT_STACK: { | 330 | case CT_CORRUPT_STACK: { |
298 | volatile u32 data[8]; | 331 | /* Make sure the compiler creates and uses an 8 char array. */ |
299 | volatile u32 *p = data; | 332 | volatile char data[8]; |
300 | 333 | ||
301 | p[12] = 0x12345678; | 334 | memset((void *)data, 0, 64); |
302 | break; | 335 | break; |
303 | } | 336 | } |
304 | case CT_UNALIGNED_LOAD_STORE_WRITE: { | 337 | case CT_UNALIGNED_LOAD_STORE_WRITE: { |
@@ -340,10 +373,34 @@ static void lkdtm_do_action(enum ctype which) | |||
340 | for (;;) | 373 | for (;;) |
341 | cpu_relax(); | 374 | cpu_relax(); |
342 | break; | 375 | break; |
376 | case CT_SPINLOCKUP: | ||
377 | /* Must be called twice to trigger. */ | ||
378 | spin_lock(&lock_me_up); | ||
379 | break; | ||
343 | case CT_HUNG_TASK: | 380 | case CT_HUNG_TASK: |
344 | set_current_state(TASK_UNINTERRUPTIBLE); | 381 | set_current_state(TASK_UNINTERRUPTIBLE); |
345 | schedule(); | 382 | schedule(); |
346 | break; | 383 | break; |
384 | case CT_EXEC_DATA: | ||
385 | execute_location(data_area); | ||
386 | break; | ||
387 | case CT_EXEC_STACK: { | ||
388 | u8 stack_area[EXEC_SIZE]; | ||
389 | execute_location(stack_area); | ||
390 | break; | ||
391 | } | ||
392 | case CT_EXEC_KMALLOC: { | ||
393 | u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL); | ||
394 | execute_location(kmalloc_area); | ||
395 | kfree(kmalloc_area); | ||
396 | break; | ||
397 | } | ||
398 | case CT_EXEC_VMALLOC: { | ||
399 | u32 *vmalloc_area = vmalloc(EXEC_SIZE); | ||
400 | execute_location(vmalloc_area); | ||
401 | vfree(vmalloc_area); | ||
402 | break; | ||
403 | } | ||
347 | case CT_NONE: | 404 | case CT_NONE: |
348 | default: | 405 | default: |
349 | break; | 406 | break; |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 749452f8e2f6..d0fdc134068a 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev, | |||
418 | struct file *file, poll_table *wait) | 418 | struct file *file, poll_table *wait) |
419 | { | 419 | { |
420 | unsigned int mask = 0; | 420 | unsigned int mask = 0; |
421 | mutex_unlock(&dev->device_lock); | 421 | |
422 | poll_wait(file, &dev->iamthif_cl.wait, wait); | 422 | poll_wait(file, &dev->iamthif_cl.wait, wait); |
423 | |||
423 | mutex_lock(&dev->device_lock); | 424 | mutex_lock(&dev->device_lock); |
424 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && | 425 | if (!mei_cl_is_connected(&dev->iamthif_cl)) { |
425 | dev->iamthif_file_object == file) { | 426 | |
427 | mask = POLLERR; | ||
428 | |||
429 | } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && | ||
430 | dev->iamthif_file_object == file) { | ||
431 | |||
426 | mask |= (POLLIN | POLLRDNORM); | 432 | mask |= (POLLIN | POLLRDNORM); |
427 | dev_dbg(&dev->pdev->dev, "run next amthif cb\n"); | 433 | dev_dbg(&dev->pdev->dev, "run next amthif cb\n"); |
428 | mei_amthif_run_next_cmd(dev); | 434 | mei_amthif_run_next_cmd(dev); |
429 | } | 435 | } |
436 | mutex_unlock(&dev->device_lock); | ||
437 | |||
430 | return mask; | 438 | return mask; |
431 | } | 439 | } |
432 | 440 | ||
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 9ecd49a7be1b..a150a42ed4af 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c | |||
@@ -47,7 +47,7 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv) | |||
47 | id = driver->id_table; | 47 | id = driver->id_table; |
48 | 48 | ||
49 | while (id->name[0]) { | 49 | while (id->name[0]) { |
50 | if (!strcmp(dev_name(dev), id->name)) | 50 | if (!strncmp(dev_name(dev), id->name, sizeof(id->name))) |
51 | return 1; | 51 | return 1; |
52 | 52 | ||
53 | id++; | 53 | id++; |
@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev) | |||
71 | 71 | ||
72 | dev_dbg(dev, "Device probe\n"); | 72 | dev_dbg(dev, "Device probe\n"); |
73 | 73 | ||
74 | strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE); | 74 | strncpy(id.name, dev_name(dev), sizeof(id.name)); |
75 | 75 | ||
76 | return driver->probe(device, &id); | 76 | return driver->probe(device, &id); |
77 | } | 77 | } |
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 21d3f5aa8353..e0684b4d9a08 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c | |||
@@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) | |||
635 | 635 | ||
636 | dev = cl->dev; | 636 | dev = cl->dev; |
637 | 637 | ||
638 | if (cl->state != MEI_FILE_CONNECTED) | 638 | if (!mei_cl_is_connected(cl)) |
639 | return -ENODEV; | ||
640 | |||
641 | if (dev->dev_state != MEI_DEV_ENABLED) | ||
642 | return -ENODEV; | 639 | return -ENODEV; |
643 | 640 | ||
644 | if (cl->read_cb) { | 641 | if (cl->read_cb) { |
@@ -892,18 +889,22 @@ void mei_cl_all_disconnect(struct mei_device *dev) | |||
892 | 889 | ||
893 | 890 | ||
894 | /** | 891 | /** |
895 | * mei_cl_all_read_wakeup - wake up all readings so they can be interrupted | 892 | * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted |
896 | * | 893 | * |
897 | * @dev - mei device | 894 | * @dev - mei device |
898 | */ | 895 | */ |
899 | void mei_cl_all_read_wakeup(struct mei_device *dev) | 896 | void mei_cl_all_wakeup(struct mei_device *dev) |
900 | { | 897 | { |
901 | struct mei_cl *cl, *next; | 898 | struct mei_cl *cl, *next; |
902 | list_for_each_entry_safe(cl, next, &dev->file_list, link) { | 899 | list_for_each_entry_safe(cl, next, &dev->file_list, link) { |
903 | if (waitqueue_active(&cl->rx_wait)) { | 900 | if (waitqueue_active(&cl->rx_wait)) { |
904 | dev_dbg(&dev->pdev->dev, "Waking up client!\n"); | 901 | dev_dbg(&dev->pdev->dev, "Waking up reading client!\n"); |
905 | wake_up_interruptible(&cl->rx_wait); | 902 | wake_up_interruptible(&cl->rx_wait); |
906 | } | 903 | } |
904 | if (waitqueue_active(&cl->tx_wait)) { | ||
905 | dev_dbg(&dev->pdev->dev, "Waking up writing client!\n"); | ||
906 | wake_up_interruptible(&cl->tx_wait); | ||
907 | } | ||
907 | } | 908 | } |
908 | } | 909 | } |
909 | 910 | ||
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 26b157d8bad5..9eb031e92070 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h | |||
@@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); | |||
84 | /* | 84 | /* |
85 | * MEI input output function prototype | 85 | * MEI input output function prototype |
86 | */ | 86 | */ |
87 | static inline bool mei_cl_is_connected(struct mei_cl *cl) | ||
88 | { | ||
89 | return (cl->dev && | ||
90 | cl->dev->dev_state == MEI_DEV_ENABLED && | ||
91 | cl->state == MEI_FILE_CONNECTED); | ||
92 | } | ||
93 | |||
87 | bool mei_cl_is_other_connecting(struct mei_cl *cl); | 94 | bool mei_cl_is_other_connecting(struct mei_cl *cl); |
88 | int mei_cl_disconnect(struct mei_cl *cl); | 95 | int mei_cl_disconnect(struct mei_cl *cl); |
89 | int mei_cl_connect(struct mei_cl *cl, struct file *file); | 96 | 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 | 106 | ||
100 | 107 | ||
101 | void mei_cl_all_disconnect(struct mei_device *dev); | 108 | void mei_cl_all_disconnect(struct mei_device *dev); |
102 | void mei_cl_all_read_wakeup(struct mei_device *dev); | 109 | void mei_cl_all_wakeup(struct mei_device *dev); |
103 | void mei_cl_all_write_clear(struct mei_device *dev); | 110 | void mei_cl_all_write_clear(struct mei_device *dev); |
104 | 111 | ||
105 | #endif /* _MEI_CLIENT_H_ */ | 112 | #endif /* _MEI_CLIENT_H_ */ |
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index b22c7e247225..3412adcdaeb0 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -176,21 +176,18 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) | |||
176 | struct mei_me_hw *hw = to_me_hw(dev); | 176 | struct mei_me_hw *hw = to_me_hw(dev); |
177 | u32 hcsr = mei_hcsr_read(hw); | 177 | u32 hcsr = mei_hcsr_read(hw); |
178 | 178 | ||
179 | dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); | 179 | hcsr |= H_RST | H_IG | H_IS; |
180 | |||
181 | hcsr |= (H_RST | H_IG); | ||
182 | 180 | ||
183 | if (intr_enable) | 181 | if (intr_enable) |
184 | hcsr |= H_IE; | 182 | hcsr |= H_IE; |
185 | else | 183 | else |
186 | hcsr |= ~H_IE; | 184 | hcsr &= ~H_IE; |
187 | 185 | ||
188 | mei_hcsr_set(hw, hcsr); | 186 | mei_me_reg_write(hw, H_CSR, hcsr); |
189 | 187 | ||
190 | if (dev->dev_state == MEI_DEV_POWER_DOWN) | 188 | if (dev->dev_state == MEI_DEV_POWER_DOWN) |
191 | mei_me_hw_reset_release(dev); | 189 | mei_me_hw_reset_release(dev); |
192 | 190 | ||
193 | dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw)); | ||
194 | return 0; | 191 | return 0; |
195 | } | 192 | } |
196 | 193 | ||
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index e6f16f83ecde..92c73118b13c 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -154,8 +154,14 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
154 | dev->dev_state != MEI_DEV_POWER_DOWN) | 154 | dev->dev_state != MEI_DEV_POWER_DOWN) |
155 | dev->dev_state = MEI_DEV_RESETTING; | 155 | dev->dev_state = MEI_DEV_RESETTING; |
156 | 156 | ||
157 | /* remove all waiting requests */ | ||
158 | mei_cl_all_write_clear(dev); | ||
159 | |||
157 | mei_cl_all_disconnect(dev); | 160 | mei_cl_all_disconnect(dev); |
158 | 161 | ||
162 | /* wake up all readings so they can be interrupted */ | ||
163 | mei_cl_all_wakeup(dev); | ||
164 | |||
159 | /* remove entry if already in list */ | 165 | /* remove entry if already in list */ |
160 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); | 166 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); |
161 | mei_cl_unlink(&dev->wd_cl); | 167 | mei_cl_unlink(&dev->wd_cl); |
@@ -196,11 +202,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
196 | 202 | ||
197 | mei_hbm_start_req(dev); | 203 | mei_hbm_start_req(dev); |
198 | 204 | ||
199 | /* wake up all readings so they can be interrupted */ | ||
200 | mei_cl_all_read_wakeup(dev); | ||
201 | |||
202 | /* remove all waiting requests */ | ||
203 | mei_cl_all_write_clear(dev); | ||
204 | } | 205 | } |
205 | EXPORT_SYMBOL_GPL(mei_reset); | 206 | EXPORT_SYMBOL_GPL(mei_reset); |
206 | 207 | ||
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 5e11b5b9b65d..173ff095be0d 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) | |||
625 | unsigned int mask = 0; | 625 | unsigned int mask = 0; |
626 | 626 | ||
627 | if (WARN_ON(!cl || !cl->dev)) | 627 | if (WARN_ON(!cl || !cl->dev)) |
628 | return mask; | 628 | return POLLERR; |
629 | 629 | ||
630 | dev = cl->dev; | 630 | dev = cl->dev; |
631 | 631 | ||
632 | mutex_lock(&dev->device_lock); | 632 | mutex_lock(&dev->device_lock); |
633 | 633 | ||
634 | if (dev->dev_state != MEI_DEV_ENABLED) | 634 | if (!mei_cl_is_connected(cl)) { |
635 | goto out; | 635 | mask = POLLERR; |
636 | |||
637 | |||
638 | if (cl == &dev->iamthif_cl) { | ||
639 | mask = mei_amthif_poll(dev, file, wait); | ||
640 | goto out; | 636 | goto out; |
641 | } | 637 | } |
642 | 638 | ||
643 | mutex_unlock(&dev->device_lock); | 639 | mutex_unlock(&dev->device_lock); |
640 | |||
641 | |||
642 | if (cl == &dev->iamthif_cl) | ||
643 | return mei_amthif_poll(dev, file, wait); | ||
644 | |||
644 | poll_wait(file, &cl->tx_wait, wait); | 645 | poll_wait(file, &cl->tx_wait, wait); |
646 | |||
645 | mutex_lock(&dev->device_lock); | 647 | mutex_lock(&dev->device_lock); |
648 | |||
649 | if (!mei_cl_is_connected(cl)) { | ||
650 | mask = POLLERR; | ||
651 | goto out; | ||
652 | } | ||
653 | |||
646 | if (MEI_WRITE_COMPLETE == cl->writing_state) | 654 | if (MEI_WRITE_COMPLETE == cl->writing_state) |
647 | mask |= (POLLIN | POLLRDNORM); | 655 | mask |= (POLLIN | POLLRDNORM); |
648 | 656 | ||
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index d87cc91bc016..afe66571ce0b 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c | |||
@@ -68,7 +68,8 @@ static int sram_probe(struct platform_device *pdev) | |||
68 | ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base, | 68 | ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base, |
69 | res->start, size, -1); | 69 | res->start, size, -1); |
70 | if (ret < 0) { | 70 | if (ret < 0) { |
71 | gen_pool_destroy(sram->pool); | 71 | if (sram->clk) |
72 | clk_disable_unprepare(sram->clk); | ||
72 | return ret; | 73 | return ret; |
73 | } | 74 | } |
74 | 75 | ||
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 0a1428016350..8d64b681dd93 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c | |||
@@ -562,7 +562,9 @@ long st_register(struct st_proto_s *new_proto) | |||
562 | if ((st_gdata->protos_registered != ST_EMPTY) && | 562 | if ((st_gdata->protos_registered != ST_EMPTY) && |
563 | (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { | 563 | (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { |
564 | pr_err(" KIM failure complete callback "); | 564 | pr_err(" KIM failure complete callback "); |
565 | spin_lock_irqsave(&st_gdata->lock, flags); | ||
565 | st_reg_complete(st_gdata, err); | 566 | st_reg_complete(st_gdata, err); |
567 | spin_unlock_irqrestore(&st_gdata->lock, flags); | ||
566 | clear_bit(ST_REG_PENDING, &st_gdata->st_state); | 568 | clear_bit(ST_REG_PENDING, &st_gdata->st_state); |
567 | } | 569 | } |
568 | return -EINVAL; | 570 | return -EINVAL; |
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index cb56e270da11..2421835d5daf 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c | |||
@@ -133,7 +133,7 @@ MODULE_LICENSE("GPL"); | |||
133 | #define VMWARE_BALLOON_CMD(cmd, data, result) \ | 133 | #define VMWARE_BALLOON_CMD(cmd, data, result) \ |
134 | ({ \ | 134 | ({ \ |
135 | unsigned long __stat, __dummy1, __dummy2; \ | 135 | unsigned long __stat, __dummy1, __dummy2; \ |
136 | __asm__ __volatile__ ("inl (%%dx)" : \ | 136 | __asm__ __volatile__ ("inl %%dx" : \ |
137 | "=a"(__stat), \ | 137 | "=a"(__stat), \ |
138 | "=c"(__dummy1), \ | 138 | "=c"(__dummy1), \ |
139 | "=d"(__dummy2), \ | 139 | "=d"(__dummy2), \ |
diff --git a/drivers/misc/vmw_vmci/vmci_driver.c b/drivers/misc/vmw_vmci/vmci_driver.c index 7b3fce2da6c3..3dee7ae123e7 100644 --- a/drivers/misc/vmw_vmci/vmci_driver.c +++ b/drivers/misc/vmw_vmci/vmci_driver.c | |||
@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit); | |||
113 | 113 | ||
114 | MODULE_AUTHOR("VMware, Inc."); | 114 | MODULE_AUTHOR("VMware, Inc."); |
115 | MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface."); | 115 | MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface."); |
116 | MODULE_VERSION("1.0.0.0-k"); | 116 | MODULE_VERSION("1.1.0.0-k"); |
117 | MODULE_LICENSE("GPL v2"); | 117 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/misc/vmw_vmci/vmci_driver.h b/drivers/misc/vmw_vmci/vmci_driver.h index f69156a1f30c..cee9e977d318 100644 --- a/drivers/misc/vmw_vmci/vmci_driver.h +++ b/drivers/misc/vmw_vmci/vmci_driver.h | |||
@@ -35,6 +35,13 @@ struct vmci_obj { | |||
35 | enum vmci_obj_type type; | 35 | enum vmci_obj_type type; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* | ||
39 | * Needed by other components of this module. It's okay to have one global | ||
40 | * instance of this because there can only ever be one VMCI device. Our | ||
41 | * virtual hardware enforces this. | ||
42 | */ | ||
43 | extern struct pci_dev *vmci_pdev; | ||
44 | |||
38 | u32 vmci_get_context_id(void); | 45 | u32 vmci_get_context_id(void); |
39 | int vmci_send_datagram(struct vmci_datagram *dg); | 46 | int vmci_send_datagram(struct vmci_datagram *dg); |
40 | 47 | ||
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c index 60c01999f489..b3a2b763ecf2 100644 --- a/drivers/misc/vmw_vmci/vmci_guest.c +++ b/drivers/misc/vmw_vmci/vmci_guest.c | |||
@@ -65,9 +65,11 @@ struct vmci_guest_device { | |||
65 | 65 | ||
66 | void *data_buffer; | 66 | void *data_buffer; |
67 | void *notification_bitmap; | 67 | void *notification_bitmap; |
68 | dma_addr_t notification_base; | ||
68 | }; | 69 | }; |
69 | 70 | ||
70 | /* vmci_dev singleton device and supporting data*/ | 71 | /* vmci_dev singleton device and supporting data*/ |
72 | struct pci_dev *vmci_pdev; | ||
71 | static struct vmci_guest_device *vmci_dev_g; | 73 | static struct vmci_guest_device *vmci_dev_g; |
72 | static DEFINE_SPINLOCK(vmci_dev_spinlock); | 74 | static DEFINE_SPINLOCK(vmci_dev_spinlock); |
73 | 75 | ||
@@ -528,7 +530,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, | |||
528 | * well. | 530 | * well. |
529 | */ | 531 | */ |
530 | if (capabilities & VMCI_CAPS_NOTIFICATIONS) { | 532 | if (capabilities & VMCI_CAPS_NOTIFICATIONS) { |
531 | vmci_dev->notification_bitmap = vmalloc(PAGE_SIZE); | 533 | vmci_dev->notification_bitmap = dma_alloc_coherent( |
534 | &pdev->dev, PAGE_SIZE, &vmci_dev->notification_base, | ||
535 | GFP_KERNEL); | ||
532 | if (!vmci_dev->notification_bitmap) { | 536 | if (!vmci_dev->notification_bitmap) { |
533 | dev_warn(&pdev->dev, | 537 | dev_warn(&pdev->dev, |
534 | "Unable to allocate notification bitmap\n"); | 538 | "Unable to allocate notification bitmap\n"); |
@@ -546,6 +550,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, | |||
546 | /* Set up global device so that we can start sending datagrams */ | 550 | /* Set up global device so that we can start sending datagrams */ |
547 | spin_lock_irq(&vmci_dev_spinlock); | 551 | spin_lock_irq(&vmci_dev_spinlock); |
548 | vmci_dev_g = vmci_dev; | 552 | vmci_dev_g = vmci_dev; |
553 | vmci_pdev = pdev; | ||
549 | spin_unlock_irq(&vmci_dev_spinlock); | 554 | spin_unlock_irq(&vmci_dev_spinlock); |
550 | 555 | ||
551 | /* | 556 | /* |
@@ -553,9 +558,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, | |||
553 | * used. | 558 | * used. |
554 | */ | 559 | */ |
555 | if (capabilities & VMCI_CAPS_NOTIFICATIONS) { | 560 | if (capabilities & VMCI_CAPS_NOTIFICATIONS) { |
556 | struct page *page = | 561 | unsigned long bitmap_ppn = |
557 | vmalloc_to_page(vmci_dev->notification_bitmap); | 562 | vmci_dev->notification_base >> PAGE_SHIFT; |
558 | unsigned long bitmap_ppn = page_to_pfn(page); | ||
559 | if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) { | 563 | if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) { |
560 | dev_warn(&pdev->dev, | 564 | dev_warn(&pdev->dev, |
561 | "VMCI device unable to register notification bitmap with PPN 0x%x\n", | 565 | "VMCI device unable to register notification bitmap with PPN 0x%x\n", |
@@ -665,11 +669,14 @@ err_remove_bitmap: | |||
665 | if (vmci_dev->notification_bitmap) { | 669 | if (vmci_dev->notification_bitmap) { |
666 | iowrite32(VMCI_CONTROL_RESET, | 670 | iowrite32(VMCI_CONTROL_RESET, |
667 | vmci_dev->iobase + VMCI_CONTROL_ADDR); | 671 | vmci_dev->iobase + VMCI_CONTROL_ADDR); |
668 | vfree(vmci_dev->notification_bitmap); | 672 | dma_free_coherent(&pdev->dev, PAGE_SIZE, |
673 | vmci_dev->notification_bitmap, | ||
674 | vmci_dev->notification_base); | ||
669 | } | 675 | } |
670 | 676 | ||
671 | err_remove_vmci_dev_g: | 677 | err_remove_vmci_dev_g: |
672 | spin_lock_irq(&vmci_dev_spinlock); | 678 | spin_lock_irq(&vmci_dev_spinlock); |
679 | vmci_pdev = NULL; | ||
673 | vmci_dev_g = NULL; | 680 | vmci_dev_g = NULL; |
674 | spin_unlock_irq(&vmci_dev_spinlock); | 681 | spin_unlock_irq(&vmci_dev_spinlock); |
675 | 682 | ||
@@ -699,6 +706,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) | |||
699 | 706 | ||
700 | spin_lock_irq(&vmci_dev_spinlock); | 707 | spin_lock_irq(&vmci_dev_spinlock); |
701 | vmci_dev_g = NULL; | 708 | vmci_dev_g = NULL; |
709 | vmci_pdev = NULL; | ||
702 | spin_unlock_irq(&vmci_dev_spinlock); | 710 | spin_unlock_irq(&vmci_dev_spinlock); |
703 | 711 | ||
704 | dev_dbg(&pdev->dev, "Resetting vmci device\n"); | 712 | dev_dbg(&pdev->dev, "Resetting vmci device\n"); |
@@ -727,7 +735,9 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) | |||
727 | * device, so we can safely free it here. | 735 | * device, so we can safely free it here. |
728 | */ | 736 | */ |
729 | 737 | ||
730 | vfree(vmci_dev->notification_bitmap); | 738 | dma_free_coherent(&pdev->dev, PAGE_SIZE, |
739 | vmci_dev->notification_bitmap, | ||
740 | vmci_dev->notification_base); | ||
731 | } | 741 | } |
732 | 742 | ||
733 | vfree(vmci_dev->data_buffer); | 743 | vfree(vmci_dev->data_buffer); |
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index 8ff2e5ee8fb8..a0515a6d6ebd 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
24 | #include <linux/pci.h> | ||
24 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/uio.h> | 27 | #include <linux/uio.h> |
@@ -146,14 +147,20 @@ typedef int vmci_memcpy_from_queue_func(void *dest, size_t dest_offset, | |||
146 | 147 | ||
147 | /* The Kernel specific component of the struct vmci_queue structure. */ | 148 | /* The Kernel specific component of the struct vmci_queue structure. */ |
148 | struct vmci_queue_kern_if { | 149 | struct vmci_queue_kern_if { |
149 | struct page **page; | ||
150 | struct page **header_page; | ||
151 | void *va; | ||
152 | struct mutex __mutex; /* Protects the queue. */ | 150 | struct mutex __mutex; /* Protects the queue. */ |
153 | struct mutex *mutex; /* Shared by producer and consumer queues. */ | 151 | struct mutex *mutex; /* Shared by producer and consumer queues. */ |
154 | bool host; | 152 | size_t num_pages; /* Number of pages incl. header. */ |
155 | size_t num_pages; | 153 | bool host; /* Host or guest? */ |
156 | bool mapped; | 154 | union { |
155 | struct { | ||
156 | dma_addr_t *pas; | ||
157 | void **vas; | ||
158 | } g; /* Used by the guest. */ | ||
159 | struct { | ||
160 | struct page **page; | ||
161 | struct page **header_page; | ||
162 | } h; /* Used by the host. */ | ||
163 | } u; | ||
157 | }; | 164 | }; |
158 | 165 | ||
159 | /* | 166 | /* |
@@ -265,76 +272,65 @@ static void qp_free_queue(void *q, u64 size) | |||
265 | struct vmci_queue *queue = q; | 272 | struct vmci_queue *queue = q; |
266 | 273 | ||
267 | if (queue) { | 274 | if (queue) { |
268 | u64 i = DIV_ROUND_UP(size, PAGE_SIZE); | 275 | u64 i; |
269 | 276 | ||
270 | if (queue->kernel_if->mapped) { | 277 | /* Given size does not include header, so add in a page here. */ |
271 | vunmap(queue->kernel_if->va); | 278 | for (i = 0; i < DIV_ROUND_UP(size, PAGE_SIZE) + 1; i++) { |
272 | queue->kernel_if->va = NULL; | 279 | dma_free_coherent(&vmci_pdev->dev, PAGE_SIZE, |
280 | queue->kernel_if->u.g.vas[i], | ||
281 | queue->kernel_if->u.g.pas[i]); | ||
273 | } | 282 | } |
274 | 283 | ||
275 | while (i) | 284 | vfree(queue); |
276 | __free_page(queue->kernel_if->page[--i]); | ||
277 | |||
278 | vfree(queue->q_header); | ||
279 | } | 285 | } |
280 | } | 286 | } |
281 | 287 | ||
282 | /* | 288 | /* |
283 | * Allocates kernel VA space of specified size, plus space for the | 289 | * Allocates kernel queue pages of specified size with IOMMU mappings, |
284 | * queue structure/kernel interface and the queue header. Allocates | 290 | * plus space for the queue structure/kernel interface and the queue |
285 | * physical pages for the queue data pages. | 291 | * header. |
286 | * | ||
287 | * PAGE m: struct vmci_queue_header (struct vmci_queue->q_header) | ||
288 | * PAGE m+1: struct vmci_queue | ||
289 | * PAGE m+1+q: struct vmci_queue_kern_if (struct vmci_queue->kernel_if) | ||
290 | * PAGE n-size: Data pages (struct vmci_queue->kernel_if->page[]) | ||
291 | */ | 292 | */ |
292 | static void *qp_alloc_queue(u64 size, u32 flags) | 293 | static void *qp_alloc_queue(u64 size, u32 flags) |
293 | { | 294 | { |
294 | u64 i; | 295 | u64 i; |
295 | struct vmci_queue *queue; | 296 | struct vmci_queue *queue; |
296 | struct vmci_queue_header *q_header; | 297 | const size_t num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1; |
297 | const u64 num_data_pages = DIV_ROUND_UP(size, PAGE_SIZE); | 298 | const size_t pas_size = num_pages * sizeof(*queue->kernel_if->u.g.pas); |
298 | const uint queue_size = | 299 | const size_t vas_size = num_pages * sizeof(*queue->kernel_if->u.g.vas); |
299 | PAGE_SIZE + | 300 | const size_t queue_size = |
300 | sizeof(*queue) + sizeof(*(queue->kernel_if)) + | 301 | sizeof(*queue) + sizeof(*queue->kernel_if) + |
301 | num_data_pages * sizeof(*(queue->kernel_if->page)); | 302 | pas_size + vas_size; |
302 | 303 | ||
303 | q_header = vmalloc(queue_size); | 304 | queue = vmalloc(queue_size); |
304 | if (!q_header) | 305 | if (!queue) |
305 | return NULL; | 306 | return NULL; |
306 | 307 | ||
307 | queue = (void *)q_header + PAGE_SIZE; | 308 | queue->q_header = NULL; |
308 | queue->q_header = q_header; | ||
309 | queue->saved_header = NULL; | 309 | queue->saved_header = NULL; |
310 | queue->kernel_if = (struct vmci_queue_kern_if *)(queue + 1); | 310 | queue->kernel_if = (struct vmci_queue_kern_if *)(queue + 1); |
311 | queue->kernel_if->header_page = NULL; /* Unused in guest. */ | 311 | queue->kernel_if->mutex = NULL; |
312 | queue->kernel_if->page = (struct page **)(queue->kernel_if + 1); | 312 | queue->kernel_if->num_pages = num_pages; |
313 | queue->kernel_if->u.g.pas = (dma_addr_t *)(queue->kernel_if + 1); | ||
314 | queue->kernel_if->u.g.vas = | ||
315 | (void **)((u8 *)queue->kernel_if->u.g.pas + pas_size); | ||
313 | queue->kernel_if->host = false; | 316 | queue->kernel_if->host = false; |
314 | queue->kernel_if->va = NULL; | ||
315 | queue->kernel_if->mapped = false; | ||
316 | |||
317 | for (i = 0; i < num_data_pages; i++) { | ||
318 | queue->kernel_if->page[i] = alloc_pages(GFP_KERNEL, 0); | ||
319 | if (!queue->kernel_if->page[i]) | ||
320 | goto fail; | ||
321 | } | ||
322 | 317 | ||
323 | if (vmci_qp_pinned(flags)) { | 318 | for (i = 0; i < num_pages; i++) { |
324 | queue->kernel_if->va = | 319 | queue->kernel_if->u.g.vas[i] = |
325 | vmap(queue->kernel_if->page, num_data_pages, VM_MAP, | 320 | dma_alloc_coherent(&vmci_pdev->dev, PAGE_SIZE, |
326 | PAGE_KERNEL); | 321 | &queue->kernel_if->u.g.pas[i], |
327 | if (!queue->kernel_if->va) | 322 | GFP_KERNEL); |
328 | goto fail; | 323 | if (!queue->kernel_if->u.g.vas[i]) { |
329 | 324 | /* Size excl. the header. */ | |
330 | queue->kernel_if->mapped = true; | 325 | qp_free_queue(queue, i * PAGE_SIZE); |
326 | return NULL; | ||
327 | } | ||
331 | } | 328 | } |
332 | 329 | ||
333 | return (void *)queue; | 330 | /* Queue header is the first page. */ |
331 | queue->q_header = queue->kernel_if->u.g.vas[0]; | ||
334 | 332 | ||
335 | fail: | 333 | return queue; |
336 | qp_free_queue(queue, i * PAGE_SIZE); | ||
337 | return NULL; | ||
338 | } | 334 | } |
339 | 335 | ||
340 | /* | 336 | /* |
@@ -353,17 +349,18 @@ static int __qp_memcpy_to_queue(struct vmci_queue *queue, | |||
353 | size_t bytes_copied = 0; | 349 | size_t bytes_copied = 0; |
354 | 350 | ||
355 | while (bytes_copied < size) { | 351 | while (bytes_copied < size) { |
356 | u64 page_index = (queue_offset + bytes_copied) / PAGE_SIZE; | 352 | const u64 page_index = |
357 | size_t page_offset = | 353 | (queue_offset + bytes_copied) / PAGE_SIZE; |
354 | const size_t page_offset = | ||
358 | (queue_offset + bytes_copied) & (PAGE_SIZE - 1); | 355 | (queue_offset + bytes_copied) & (PAGE_SIZE - 1); |
359 | void *va; | 356 | void *va; |
360 | size_t to_copy; | 357 | size_t to_copy; |
361 | 358 | ||
362 | if (!kernel_if->mapped) | 359 | if (kernel_if->host) |
363 | va = kmap(kernel_if->page[page_index]); | 360 | va = kmap(kernel_if->u.h.page[page_index]); |
364 | else | 361 | else |
365 | va = (void *)((u8 *)kernel_if->va + | 362 | va = kernel_if->u.g.vas[page_index + 1]; |
366 | (page_index * PAGE_SIZE)); | 363 | /* Skip header. */ |
367 | 364 | ||
368 | if (size - bytes_copied > PAGE_SIZE - page_offset) | 365 | if (size - bytes_copied > PAGE_SIZE - page_offset) |
369 | /* Enough payload to fill up from this page. */ | 366 | /* Enough payload to fill up from this page. */ |
@@ -379,7 +376,8 @@ static int __qp_memcpy_to_queue(struct vmci_queue *queue, | |||
379 | err = memcpy_fromiovec((u8 *)va + page_offset, | 376 | err = memcpy_fromiovec((u8 *)va + page_offset, |
380 | iov, to_copy); | 377 | iov, to_copy); |
381 | if (err != 0) { | 378 | if (err != 0) { |
382 | kunmap(kernel_if->page[page_index]); | 379 | if (kernel_if->host) |
380 | kunmap(kernel_if->u.h.page[page_index]); | ||
383 | return VMCI_ERROR_INVALID_ARGS; | 381 | return VMCI_ERROR_INVALID_ARGS; |
384 | } | 382 | } |
385 | } else { | 383 | } else { |
@@ -388,8 +386,8 @@ static int __qp_memcpy_to_queue(struct vmci_queue *queue, | |||
388 | } | 386 | } |
389 | 387 | ||
390 | bytes_copied += to_copy; | 388 | bytes_copied += to_copy; |
391 | if (!kernel_if->mapped) | 389 | if (kernel_if->host) |
392 | kunmap(kernel_if->page[page_index]); | 390 | kunmap(kernel_if->u.h.page[page_index]); |
393 | } | 391 | } |
394 | 392 | ||
395 | return VMCI_SUCCESS; | 393 | return VMCI_SUCCESS; |
@@ -411,17 +409,18 @@ static int __qp_memcpy_from_queue(void *dest, | |||
411 | size_t bytes_copied = 0; | 409 | size_t bytes_copied = 0; |
412 | 410 | ||
413 | while (bytes_copied < size) { | 411 | while (bytes_copied < size) { |
414 | u64 page_index = (queue_offset + bytes_copied) / PAGE_SIZE; | 412 | const u64 page_index = |
415 | size_t page_offset = | 413 | (queue_offset + bytes_copied) / PAGE_SIZE; |
414 | const size_t page_offset = | ||
416 | (queue_offset + bytes_copied) & (PAGE_SIZE - 1); | 415 | (queue_offset + bytes_copied) & (PAGE_SIZE - 1); |
417 | void *va; | 416 | void *va; |
418 | size_t to_copy; | 417 | size_t to_copy; |
419 | 418 | ||
420 | if (!kernel_if->mapped) | 419 | if (kernel_if->host) |
421 | va = kmap(kernel_if->page[page_index]); | 420 | va = kmap(kernel_if->u.h.page[page_index]); |
422 | else | 421 | else |
423 | va = (void *)((u8 *)kernel_if->va + | 422 | va = kernel_if->u.g.vas[page_index + 1]; |
424 | (page_index * PAGE_SIZE)); | 423 | /* Skip header. */ |
425 | 424 | ||
426 | if (size - bytes_copied > PAGE_SIZE - page_offset) | 425 | if (size - bytes_copied > PAGE_SIZE - page_offset) |
427 | /* Enough payload to fill up this page. */ | 426 | /* Enough payload to fill up this page. */ |
@@ -437,7 +436,8 @@ static int __qp_memcpy_from_queue(void *dest, | |||
437 | err = memcpy_toiovec(iov, (u8 *)va + page_offset, | 436 | err = memcpy_toiovec(iov, (u8 *)va + page_offset, |
438 | to_copy); | 437 | to_copy); |
439 | if (err != 0) { | 438 | if (err != 0) { |
440 | kunmap(kernel_if->page[page_index]); | 439 | if (kernel_if->host) |
440 | kunmap(kernel_if->u.h.page[page_index]); | ||
441 | return VMCI_ERROR_INVALID_ARGS; | 441 | return VMCI_ERROR_INVALID_ARGS; |
442 | } | 442 | } |
443 | } else { | 443 | } else { |
@@ -446,8 +446,8 @@ static int __qp_memcpy_from_queue(void *dest, | |||
446 | } | 446 | } |
447 | 447 | ||
448 | bytes_copied += to_copy; | 448 | bytes_copied += to_copy; |
449 | if (!kernel_if->mapped) | 449 | if (kernel_if->host) |
450 | kunmap(kernel_if->page[page_index]); | 450 | kunmap(kernel_if->u.h.page[page_index]); |
451 | } | 451 | } |
452 | 452 | ||
453 | return VMCI_SUCCESS; | 453 | return VMCI_SUCCESS; |
@@ -489,12 +489,11 @@ static int qp_alloc_ppn_set(void *prod_q, | |||
489 | return VMCI_ERROR_NO_MEM; | 489 | return VMCI_ERROR_NO_MEM; |
490 | } | 490 | } |
491 | 491 | ||
492 | produce_ppns[0] = page_to_pfn(vmalloc_to_page(produce_q->q_header)); | 492 | for (i = 0; i < num_produce_pages; i++) { |
493 | for (i = 1; i < num_produce_pages; i++) { | ||
494 | unsigned long pfn; | 493 | unsigned long pfn; |
495 | 494 | ||
496 | produce_ppns[i] = | 495 | produce_ppns[i] = |
497 | page_to_pfn(produce_q->kernel_if->page[i - 1]); | 496 | produce_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT; |
498 | pfn = produce_ppns[i]; | 497 | pfn = produce_ppns[i]; |
499 | 498 | ||
500 | /* Fail allocation if PFN isn't supported by hypervisor. */ | 499 | /* Fail allocation if PFN isn't supported by hypervisor. */ |
@@ -503,12 +502,11 @@ static int qp_alloc_ppn_set(void *prod_q, | |||
503 | goto ppn_error; | 502 | goto ppn_error; |
504 | } | 503 | } |
505 | 504 | ||
506 | consume_ppns[0] = page_to_pfn(vmalloc_to_page(consume_q->q_header)); | 505 | for (i = 0; i < num_consume_pages; i++) { |
507 | for (i = 1; i < num_consume_pages; i++) { | ||
508 | unsigned long pfn; | 506 | unsigned long pfn; |
509 | 507 | ||
510 | consume_ppns[i] = | 508 | consume_ppns[i] = |
511 | page_to_pfn(consume_q->kernel_if->page[i - 1]); | 509 | consume_q->kernel_if->u.g.pas[i] >> PAGE_SHIFT; |
512 | pfn = consume_ppns[i]; | 510 | pfn = consume_ppns[i]; |
513 | 511 | ||
514 | /* Fail allocation if PFN isn't supported by hypervisor. */ | 512 | /* Fail allocation if PFN isn't supported by hypervisor. */ |
@@ -619,23 +617,20 @@ static struct vmci_queue *qp_host_alloc_queue(u64 size) | |||
619 | const size_t num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1; | 617 | const size_t num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1; |
620 | const size_t queue_size = sizeof(*queue) + sizeof(*(queue->kernel_if)); | 618 | const size_t queue_size = sizeof(*queue) + sizeof(*(queue->kernel_if)); |
621 | const size_t queue_page_size = | 619 | const size_t queue_page_size = |
622 | num_pages * sizeof(*queue->kernel_if->page); | 620 | num_pages * sizeof(*queue->kernel_if->u.h.page); |
623 | 621 | ||
624 | queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL); | 622 | queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL); |
625 | if (queue) { | 623 | if (queue) { |
626 | queue->q_header = NULL; | 624 | queue->q_header = NULL; |
627 | queue->saved_header = NULL; | 625 | queue->saved_header = NULL; |
628 | queue->kernel_if = | 626 | queue->kernel_if = (struct vmci_queue_kern_if *)(queue + 1); |
629 | (struct vmci_queue_kern_if *)((u8 *)queue + | ||
630 | sizeof(*queue)); | ||
631 | queue->kernel_if->host = true; | 627 | queue->kernel_if->host = true; |
632 | queue->kernel_if->mutex = NULL; | 628 | queue->kernel_if->mutex = NULL; |
633 | queue->kernel_if->num_pages = num_pages; | 629 | queue->kernel_if->num_pages = num_pages; |
634 | queue->kernel_if->header_page = | 630 | queue->kernel_if->u.h.header_page = |
635 | (struct page **)((u8 *)queue + queue_size); | 631 | (struct page **)((u8 *)queue + queue_size); |
636 | queue->kernel_if->page = &queue->kernel_if->header_page[1]; | 632 | queue->kernel_if->u.h.page = |
637 | queue->kernel_if->va = NULL; | 633 | &queue->kernel_if->u.h.header_page[1]; |
638 | queue->kernel_if->mapped = false; | ||
639 | } | 634 | } |
640 | 635 | ||
641 | return queue; | 636 | return queue; |
@@ -742,11 +737,12 @@ static int qp_host_get_user_memory(u64 produce_uva, | |||
742 | current->mm, | 737 | current->mm, |
743 | (uintptr_t) produce_uva, | 738 | (uintptr_t) produce_uva, |
744 | produce_q->kernel_if->num_pages, | 739 | produce_q->kernel_if->num_pages, |
745 | 1, 0, produce_q->kernel_if->header_page, NULL); | 740 | 1, 0, |
741 | produce_q->kernel_if->u.h.header_page, NULL); | ||
746 | if (retval < produce_q->kernel_if->num_pages) { | 742 | if (retval < produce_q->kernel_if->num_pages) { |
747 | pr_warn("get_user_pages(produce) failed (retval=%d)", retval); | 743 | pr_warn("get_user_pages(produce) failed (retval=%d)", retval); |
748 | qp_release_pages(produce_q->kernel_if->header_page, retval, | 744 | qp_release_pages(produce_q->kernel_if->u.h.header_page, |
749 | false); | 745 | retval, false); |
750 | err = VMCI_ERROR_NO_MEM; | 746 | err = VMCI_ERROR_NO_MEM; |
751 | goto out; | 747 | goto out; |
752 | } | 748 | } |
@@ -755,12 +751,13 @@ static int qp_host_get_user_memory(u64 produce_uva, | |||
755 | current->mm, | 751 | current->mm, |
756 | (uintptr_t) consume_uva, | 752 | (uintptr_t) consume_uva, |
757 | consume_q->kernel_if->num_pages, | 753 | consume_q->kernel_if->num_pages, |
758 | 1, 0, consume_q->kernel_if->header_page, NULL); | 754 | 1, 0, |
755 | consume_q->kernel_if->u.h.header_page, NULL); | ||
759 | if (retval < consume_q->kernel_if->num_pages) { | 756 | if (retval < consume_q->kernel_if->num_pages) { |
760 | pr_warn("get_user_pages(consume) failed (retval=%d)", retval); | 757 | pr_warn("get_user_pages(consume) failed (retval=%d)", retval); |
761 | qp_release_pages(consume_q->kernel_if->header_page, retval, | 758 | qp_release_pages(consume_q->kernel_if->u.h.header_page, |
762 | false); | 759 | retval, false); |
763 | qp_release_pages(produce_q->kernel_if->header_page, | 760 | qp_release_pages(produce_q->kernel_if->u.h.header_page, |
764 | produce_q->kernel_if->num_pages, false); | 761 | produce_q->kernel_if->num_pages, false); |
765 | err = VMCI_ERROR_NO_MEM; | 762 | err = VMCI_ERROR_NO_MEM; |
766 | } | 763 | } |
@@ -803,15 +800,15 @@ static int qp_host_register_user_memory(struct vmci_qp_page_store *page_store, | |||
803 | static void qp_host_unregister_user_memory(struct vmci_queue *produce_q, | 800 | static void qp_host_unregister_user_memory(struct vmci_queue *produce_q, |
804 | struct vmci_queue *consume_q) | 801 | struct vmci_queue *consume_q) |
805 | { | 802 | { |
806 | qp_release_pages(produce_q->kernel_if->header_page, | 803 | qp_release_pages(produce_q->kernel_if->u.h.header_page, |
807 | produce_q->kernel_if->num_pages, true); | 804 | produce_q->kernel_if->num_pages, true); |
808 | memset(produce_q->kernel_if->header_page, 0, | 805 | memset(produce_q->kernel_if->u.h.header_page, 0, |
809 | sizeof(*produce_q->kernel_if->header_page) * | 806 | sizeof(*produce_q->kernel_if->u.h.header_page) * |
810 | produce_q->kernel_if->num_pages); | 807 | produce_q->kernel_if->num_pages); |
811 | qp_release_pages(consume_q->kernel_if->header_page, | 808 | qp_release_pages(consume_q->kernel_if->u.h.header_page, |
812 | consume_q->kernel_if->num_pages, true); | 809 | consume_q->kernel_if->num_pages, true); |
813 | memset(consume_q->kernel_if->header_page, 0, | 810 | memset(consume_q->kernel_if->u.h.header_page, 0, |
814 | sizeof(*consume_q->kernel_if->header_page) * | 811 | sizeof(*consume_q->kernel_if->u.h.header_page) * |
815 | consume_q->kernel_if->num_pages); | 812 | consume_q->kernel_if->num_pages); |
816 | } | 813 | } |
817 | 814 | ||
@@ -834,12 +831,12 @@ static int qp_host_map_queues(struct vmci_queue *produce_q, | |||
834 | if (produce_q->q_header != consume_q->q_header) | 831 | if (produce_q->q_header != consume_q->q_header) |
835 | return VMCI_ERROR_QUEUEPAIR_MISMATCH; | 832 | return VMCI_ERROR_QUEUEPAIR_MISMATCH; |
836 | 833 | ||
837 | if (produce_q->kernel_if->header_page == NULL || | 834 | if (produce_q->kernel_if->u.h.header_page == NULL || |
838 | *produce_q->kernel_if->header_page == NULL) | 835 | *produce_q->kernel_if->u.h.header_page == NULL) |
839 | return VMCI_ERROR_UNAVAILABLE; | 836 | return VMCI_ERROR_UNAVAILABLE; |
840 | 837 | ||
841 | headers[0] = *produce_q->kernel_if->header_page; | 838 | headers[0] = *produce_q->kernel_if->u.h.header_page; |
842 | headers[1] = *consume_q->kernel_if->header_page; | 839 | headers[1] = *consume_q->kernel_if->u.h.header_page; |
843 | 840 | ||
844 | produce_q->q_header = vmap(headers, 2, VM_MAP, PAGE_KERNEL); | 841 | produce_q->q_header = vmap(headers, 2, VM_MAP, PAGE_KERNEL); |
845 | if (produce_q->q_header != NULL) { | 842 | if (produce_q->q_header != NULL) { |
@@ -1720,21 +1717,6 @@ static int qp_broker_attach(struct qp_broker_entry *entry, | |||
1720 | if (result < VMCI_SUCCESS) | 1717 | if (result < VMCI_SUCCESS) |
1721 | return result; | 1718 | return result; |
1722 | 1719 | ||
1723 | /* | ||
1724 | * Preemptively load in the headers if non-blocking to | ||
1725 | * prevent blocking later. | ||
1726 | */ | ||
1727 | if (entry->qp.flags & VMCI_QPFLAG_NONBLOCK) { | ||
1728 | result = qp_host_map_queues(entry->produce_q, | ||
1729 | entry->consume_q); | ||
1730 | if (result < VMCI_SUCCESS) { | ||
1731 | qp_host_unregister_user_memory( | ||
1732 | entry->produce_q, | ||
1733 | entry->consume_q); | ||
1734 | return result; | ||
1735 | } | ||
1736 | } | ||
1737 | |||
1738 | entry->state = VMCIQPB_ATTACHED_MEM; | 1720 | entry->state = VMCIQPB_ATTACHED_MEM; |
1739 | } else { | 1721 | } else { |
1740 | entry->state = VMCIQPB_ATTACHED_NO_MEM; | 1722 | entry->state = VMCIQPB_ATTACHED_NO_MEM; |
@@ -1749,24 +1731,6 @@ static int qp_broker_attach(struct qp_broker_entry *entry, | |||
1749 | 1731 | ||
1750 | return VMCI_ERROR_UNAVAILABLE; | 1732 | return VMCI_ERROR_UNAVAILABLE; |
1751 | } else { | 1733 | } else { |
1752 | /* | ||
1753 | * For non-blocking queue pairs, we cannot rely on | ||
1754 | * enqueue/dequeue to map in the pages on the | ||
1755 | * host-side, since it may block, so we make an | ||
1756 | * attempt here. | ||
1757 | */ | ||
1758 | |||
1759 | if (flags & VMCI_QPFLAG_NONBLOCK) { | ||
1760 | result = | ||
1761 | qp_host_map_queues(entry->produce_q, | ||
1762 | entry->consume_q); | ||
1763 | if (result < VMCI_SUCCESS) | ||
1764 | return result; | ||
1765 | |||
1766 | entry->qp.flags |= flags & | ||
1767 | (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED); | ||
1768 | } | ||
1769 | |||
1770 | /* The host side has successfully attached to a queue pair. */ | 1734 | /* The host side has successfully attached to a queue pair. */ |
1771 | entry->state = VMCIQPB_ATTACHED_MEM; | 1735 | entry->state = VMCIQPB_ATTACHED_MEM; |
1772 | } | 1736 | } |
@@ -2543,24 +2507,19 @@ void vmci_qp_guest_endpoints_exit(void) | |||
2543 | * Since non-blocking isn't yet implemented on the host personality we | 2507 | * Since non-blocking isn't yet implemented on the host personality we |
2544 | * have no reason to acquire a spin lock. So to avoid the use of an | 2508 | * have no reason to acquire a spin lock. So to avoid the use of an |
2545 | * unnecessary lock only acquire the mutex if we can block. | 2509 | * unnecessary lock only acquire the mutex if we can block. |
2546 | * Note: It is assumed that QPFLAG_PINNED implies QPFLAG_NONBLOCK. Therefore | ||
2547 | * we can use the same locking function for access to both the queue | ||
2548 | * and the queue headers as it is the same logic. Assert this behvior. | ||
2549 | */ | 2510 | */ |
2550 | static void qp_lock(const struct vmci_qp *qpair) | 2511 | static void qp_lock(const struct vmci_qp *qpair) |
2551 | { | 2512 | { |
2552 | if (vmci_can_block(qpair->flags)) | 2513 | qp_acquire_queue_mutex(qpair->produce_q); |
2553 | qp_acquire_queue_mutex(qpair->produce_q); | ||
2554 | } | 2514 | } |
2555 | 2515 | ||
2556 | /* | 2516 | /* |
2557 | * Helper routine that unlocks the queue pair after calling | 2517 | * Helper routine that unlocks the queue pair after calling |
2558 | * qp_lock. Respects non-blocking and pinning flags. | 2518 | * qp_lock. |
2559 | */ | 2519 | */ |
2560 | static void qp_unlock(const struct vmci_qp *qpair) | 2520 | static void qp_unlock(const struct vmci_qp *qpair) |
2561 | { | 2521 | { |
2562 | if (vmci_can_block(qpair->flags)) | 2522 | qp_release_queue_mutex(qpair->produce_q); |
2563 | qp_release_queue_mutex(qpair->produce_q); | ||
2564 | } | 2523 | } |
2565 | 2524 | ||
2566 | /* | 2525 | /* |
@@ -2568,17 +2527,12 @@ static void qp_unlock(const struct vmci_qp *qpair) | |||
2568 | * currently not mapped, it will be attempted to do so. | 2527 | * currently not mapped, it will be attempted to do so. |
2569 | */ | 2528 | */ |
2570 | static int qp_map_queue_headers(struct vmci_queue *produce_q, | 2529 | static int qp_map_queue_headers(struct vmci_queue *produce_q, |
2571 | struct vmci_queue *consume_q, | 2530 | struct vmci_queue *consume_q) |
2572 | bool can_block) | ||
2573 | { | 2531 | { |
2574 | int result; | 2532 | int result; |
2575 | 2533 | ||
2576 | if (NULL == produce_q->q_header || NULL == consume_q->q_header) { | 2534 | if (NULL == produce_q->q_header || NULL == consume_q->q_header) { |
2577 | if (can_block) | 2535 | result = qp_host_map_queues(produce_q, consume_q); |
2578 | result = qp_host_map_queues(produce_q, consume_q); | ||
2579 | else | ||
2580 | result = VMCI_ERROR_QUEUEPAIR_NOT_READY; | ||
2581 | |||
2582 | if (result < VMCI_SUCCESS) | 2536 | if (result < VMCI_SUCCESS) |
2583 | return (produce_q->saved_header && | 2537 | return (produce_q->saved_header && |
2584 | consume_q->saved_header) ? | 2538 | consume_q->saved_header) ? |
@@ -2601,8 +2555,7 @@ static int qp_get_queue_headers(const struct vmci_qp *qpair, | |||
2601 | { | 2555 | { |
2602 | int result; | 2556 | int result; |
2603 | 2557 | ||
2604 | result = qp_map_queue_headers(qpair->produce_q, qpair->consume_q, | 2558 | result = qp_map_queue_headers(qpair->produce_q, qpair->consume_q); |
2605 | vmci_can_block(qpair->flags)); | ||
2606 | if (result == VMCI_SUCCESS) { | 2559 | if (result == VMCI_SUCCESS) { |
2607 | *produce_q_header = qpair->produce_q->q_header; | 2560 | *produce_q_header = qpair->produce_q->q_header; |
2608 | *consume_q_header = qpair->consume_q->q_header; | 2561 | *consume_q_header = qpair->consume_q->q_header; |
@@ -2645,9 +2598,6 @@ static bool qp_wait_for_ready_queue(struct vmci_qp *qpair) | |||
2645 | { | 2598 | { |
2646 | unsigned int generation; | 2599 | unsigned int generation; |
2647 | 2600 | ||
2648 | if (qpair->flags & VMCI_QPFLAG_NONBLOCK) | ||
2649 | return false; | ||
2650 | |||
2651 | qpair->blocked++; | 2601 | qpair->blocked++; |
2652 | generation = qpair->generation; | 2602 | generation = qpair->generation; |
2653 | qp_unlock(qpair); | 2603 | qp_unlock(qpair); |
@@ -2674,15 +2624,14 @@ static ssize_t qp_enqueue_locked(struct vmci_queue *produce_q, | |||
2674 | const u64 produce_q_size, | 2624 | const u64 produce_q_size, |
2675 | const void *buf, | 2625 | const void *buf, |
2676 | size_t buf_size, | 2626 | size_t buf_size, |
2677 | vmci_memcpy_to_queue_func memcpy_to_queue, | 2627 | vmci_memcpy_to_queue_func memcpy_to_queue) |
2678 | bool can_block) | ||
2679 | { | 2628 | { |
2680 | s64 free_space; | 2629 | s64 free_space; |
2681 | u64 tail; | 2630 | u64 tail; |
2682 | size_t written; | 2631 | size_t written; |
2683 | ssize_t result; | 2632 | ssize_t result; |
2684 | 2633 | ||
2685 | result = qp_map_queue_headers(produce_q, consume_q, can_block); | 2634 | result = qp_map_queue_headers(produce_q, consume_q); |
2686 | if (unlikely(result != VMCI_SUCCESS)) | 2635 | if (unlikely(result != VMCI_SUCCESS)) |
2687 | return result; | 2636 | return result; |
2688 | 2637 | ||
@@ -2737,15 +2686,14 @@ static ssize_t qp_dequeue_locked(struct vmci_queue *produce_q, | |||
2737 | void *buf, | 2686 | void *buf, |
2738 | size_t buf_size, | 2687 | size_t buf_size, |
2739 | vmci_memcpy_from_queue_func memcpy_from_queue, | 2688 | vmci_memcpy_from_queue_func memcpy_from_queue, |
2740 | bool update_consumer, | 2689 | bool update_consumer) |
2741 | bool can_block) | ||
2742 | { | 2690 | { |
2743 | s64 buf_ready; | 2691 | s64 buf_ready; |
2744 | u64 head; | 2692 | u64 head; |
2745 | size_t read; | 2693 | size_t read; |
2746 | ssize_t result; | 2694 | ssize_t result; |
2747 | 2695 | ||
2748 | result = qp_map_queue_headers(produce_q, consume_q, can_block); | 2696 | result = qp_map_queue_headers(produce_q, consume_q); |
2749 | if (unlikely(result != VMCI_SUCCESS)) | 2697 | if (unlikely(result != VMCI_SUCCESS)) |
2750 | return result; | 2698 | return result; |
2751 | 2699 | ||
@@ -2842,32 +2790,11 @@ int vmci_qpair_alloc(struct vmci_qp **qpair, | |||
2842 | route = vmci_guest_code_active() ? | 2790 | route = vmci_guest_code_active() ? |
2843 | VMCI_ROUTE_AS_GUEST : VMCI_ROUTE_AS_HOST; | 2791 | VMCI_ROUTE_AS_GUEST : VMCI_ROUTE_AS_HOST; |
2844 | 2792 | ||
2845 | /* If NONBLOCK or PINNED is set, we better be the guest personality. */ | 2793 | if (flags & (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED)) { |
2846 | if ((!vmci_can_block(flags) || vmci_qp_pinned(flags)) && | 2794 | pr_devel("NONBLOCK OR PINNED set"); |
2847 | VMCI_ROUTE_AS_GUEST != route) { | ||
2848 | pr_devel("Not guest personality w/ NONBLOCK OR PINNED set"); | ||
2849 | return VMCI_ERROR_INVALID_ARGS; | 2795 | return VMCI_ERROR_INVALID_ARGS; |
2850 | } | 2796 | } |
2851 | 2797 | ||
2852 | /* | ||
2853 | * Limit the size of pinned QPs and check sanity. | ||
2854 | * | ||
2855 | * Pinned pages implies non-blocking mode. Mutexes aren't acquired | ||
2856 | * when the NONBLOCK flag is set in qpair code; and also should not be | ||
2857 | * acquired when the PINNED flagged is set. Since pinning pages | ||
2858 | * implies we want speed, it makes no sense not to have NONBLOCK | ||
2859 | * set if PINNED is set. Hence enforce this implication. | ||
2860 | */ | ||
2861 | if (vmci_qp_pinned(flags)) { | ||
2862 | if (vmci_can_block(flags)) { | ||
2863 | pr_err("Attempted to enable pinning w/o non-blocking"); | ||
2864 | return VMCI_ERROR_INVALID_ARGS; | ||
2865 | } | ||
2866 | |||
2867 | if (produce_qsize + consume_qsize > VMCI_MAX_PINNED_QP_MEMORY) | ||
2868 | return VMCI_ERROR_NO_RESOURCES; | ||
2869 | } | ||
2870 | |||
2871 | my_qpair = kzalloc(sizeof(*my_qpair), GFP_KERNEL); | 2798 | my_qpair = kzalloc(sizeof(*my_qpair), GFP_KERNEL); |
2872 | if (!my_qpair) | 2799 | if (!my_qpair) |
2873 | return VMCI_ERROR_NO_MEM; | 2800 | return VMCI_ERROR_NO_MEM; |
@@ -3195,8 +3122,7 @@ ssize_t vmci_qpair_enqueue(struct vmci_qp *qpair, | |||
3195 | qpair->consume_q, | 3122 | qpair->consume_q, |
3196 | qpair->produce_q_size, | 3123 | qpair->produce_q_size, |
3197 | buf, buf_size, | 3124 | buf, buf_size, |
3198 | qp_memcpy_to_queue, | 3125 | qp_memcpy_to_queue); |
3199 | vmci_can_block(qpair->flags)); | ||
3200 | 3126 | ||
3201 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3127 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3202 | !qp_wait_for_ready_queue(qpair)) | 3128 | !qp_wait_for_ready_queue(qpair)) |
@@ -3237,8 +3163,7 @@ ssize_t vmci_qpair_dequeue(struct vmci_qp *qpair, | |||
3237 | qpair->consume_q, | 3163 | qpair->consume_q, |
3238 | qpair->consume_q_size, | 3164 | qpair->consume_q_size, |
3239 | buf, buf_size, | 3165 | buf, buf_size, |
3240 | qp_memcpy_from_queue, true, | 3166 | qp_memcpy_from_queue, true); |
3241 | vmci_can_block(qpair->flags)); | ||
3242 | 3167 | ||
3243 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3168 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3244 | !qp_wait_for_ready_queue(qpair)) | 3169 | !qp_wait_for_ready_queue(qpair)) |
@@ -3280,8 +3205,7 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair, | |||
3280 | qpair->consume_q, | 3205 | qpair->consume_q, |
3281 | qpair->consume_q_size, | 3206 | qpair->consume_q_size, |
3282 | buf, buf_size, | 3207 | buf, buf_size, |
3283 | qp_memcpy_from_queue, false, | 3208 | qp_memcpy_from_queue, false); |
3284 | vmci_can_block(qpair->flags)); | ||
3285 | 3209 | ||
3286 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3210 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3287 | !qp_wait_for_ready_queue(qpair)) | 3211 | !qp_wait_for_ready_queue(qpair)) |
@@ -3323,8 +3247,7 @@ ssize_t vmci_qpair_enquev(struct vmci_qp *qpair, | |||
3323 | qpair->consume_q, | 3247 | qpair->consume_q, |
3324 | qpair->produce_q_size, | 3248 | qpair->produce_q_size, |
3325 | iov, iov_size, | 3249 | iov, iov_size, |
3326 | qp_memcpy_to_queue_iov, | 3250 | qp_memcpy_to_queue_iov); |
3327 | vmci_can_block(qpair->flags)); | ||
3328 | 3251 | ||
3329 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3252 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3330 | !qp_wait_for_ready_queue(qpair)) | 3253 | !qp_wait_for_ready_queue(qpair)) |
@@ -3367,7 +3290,7 @@ ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, | |||
3367 | qpair->consume_q_size, | 3290 | qpair->consume_q_size, |
3368 | iov, iov_size, | 3291 | iov, iov_size, |
3369 | qp_memcpy_from_queue_iov, | 3292 | qp_memcpy_from_queue_iov, |
3370 | true, vmci_can_block(qpair->flags)); | 3293 | true); |
3371 | 3294 | ||
3372 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3295 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3373 | !qp_wait_for_ready_queue(qpair)) | 3296 | !qp_wait_for_ready_queue(qpair)) |
@@ -3411,7 +3334,7 @@ ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, | |||
3411 | qpair->consume_q_size, | 3334 | qpair->consume_q_size, |
3412 | iov, iov_size, | 3335 | iov, iov_size, |
3413 | qp_memcpy_from_queue_iov, | 3336 | qp_memcpy_from_queue_iov, |
3414 | false, vmci_can_block(qpair->flags)); | 3337 | false); |
3415 | 3338 | ||
3416 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && | 3339 | if (result == VMCI_ERROR_QUEUEPAIR_NOT_READY && |
3417 | !qp_wait_for_ready_queue(qpair)) | 3340 | !qp_wait_for_ready_queue(qpair)) |
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.h b/drivers/misc/vmw_vmci/vmci_queue_pair.h index 58c6959f6b6d..ed177f04ef24 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.h +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.h | |||
@@ -146,24 +146,6 @@ VMCI_QP_PAGESTORE_IS_WELLFORMED(struct vmci_qp_page_store *page_store) | |||
146 | return page_store->len >= 2; | 146 | return page_store->len >= 2; |
147 | } | 147 | } |
148 | 148 | ||
149 | /* | ||
150 | * Helper function to check if the non-blocking flag | ||
151 | * is set for a given queue pair. | ||
152 | */ | ||
153 | static inline bool vmci_can_block(u32 flags) | ||
154 | { | ||
155 | return !(flags & VMCI_QPFLAG_NONBLOCK); | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Helper function to check if the queue pair is pinned | ||
160 | * into memory. | ||
161 | */ | ||
162 | static inline bool vmci_qp_pinned(u32 flags) | ||
163 | { | ||
164 | return flags & VMCI_QPFLAG_PINNED; | ||
165 | } | ||
166 | |||
167 | void vmci_qp_broker_exit(void); | 149 | void vmci_qp_broker_exit(void); |
168 | int vmci_qp_broker_alloc(struct vmci_handle handle, u32 peer, | 150 | int vmci_qp_broker_alloc(struct vmci_handle handle, u32 peer, |
169 | u32 flags, u32 priv_flags, | 151 | u32 flags, u32 priv_flags, |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 23a0fff0df52..524f713f6017 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -306,7 +306,6 @@ static void netvsc_get_drvinfo(struct net_device *net, | |||
306 | struct ethtool_drvinfo *info) | 306 | struct ethtool_drvinfo *info) |
307 | { | 307 | { |
308 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); | 308 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); |
309 | strlcpy(info->version, HV_DRV_VERSION, sizeof(info->version)); | ||
310 | strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); | 309 | strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); |
311 | } | 310 | } |
312 | 311 | ||
@@ -529,7 +528,6 @@ static int __init netvsc_drv_init(void) | |||
529 | } | 528 | } |
530 | 529 | ||
531 | MODULE_LICENSE("GPL"); | 530 | MODULE_LICENSE("GPL"); |
532 | MODULE_VERSION(HV_DRV_VERSION); | ||
533 | MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); | 531 | MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); |
534 | 532 | ||
535 | module_init(netvsc_drv_init); | 533 | module_init(netvsc_drv_init); |
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index dc82ef096f3b..70694ce38be2 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -37,7 +37,7 @@ config PARPORT_PC | |||
37 | tristate "PC-style hardware" | 37 | tristate "PC-style hardware" |
38 | depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \ | 38 | depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \ |
39 | (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \ | 39 | (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \ |
40 | !XTENSA && !CRIS | 40 | !XTENSA && !CRIS && !H8300 |
41 | 41 | ||
42 | ---help--- | 42 | ---help--- |
43 | You should say Y here if you have a PC-style parallel port. All | 43 | You should say Y here if you have a PC-style parallel port. All |
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c index 09503b8d12e6..26ecdea84fb5 100644 --- a/drivers/parport/parport_amiga.c +++ b/drivers/parport/parport_amiga.c | |||
@@ -232,7 +232,6 @@ static int __exit amiga_parallel_remove(struct platform_device *pdev) | |||
232 | if (port->irq != PARPORT_IRQ_NONE) | 232 | if (port->irq != PARPORT_IRQ_NONE) |
233 | free_irq(IRQ_AMIGA_CIAA_FLG, port); | 233 | free_irq(IRQ_AMIGA_CIAA_FLG, port); |
234 | parport_put_port(port); | 234 | parport_put_port(port); |
235 | platform_set_drvdata(pdev, NULL); | ||
236 | return 0; | 235 | return 0; |
237 | } | 236 | } |
238 | 237 | ||
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 83ec1aa85964..1a28f5632797 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
@@ -1879,7 +1879,6 @@ static void __exit storvsc_drv_exit(void) | |||
1879 | } | 1879 | } |
1880 | 1880 | ||
1881 | MODULE_LICENSE("GPL"); | 1881 | MODULE_LICENSE("GPL"); |
1882 | MODULE_VERSION(HV_DRV_VERSION); | ||
1883 | MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); | 1882 | MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); |
1884 | module_init(storvsc_drv_init); | 1883 | module_init(storvsc_drv_init); |
1885 | module_exit(storvsc_drv_exit); | 1884 | module_exit(storvsc_drv_exit); |
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 5295be0342c1..5a90914d856d 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | menuconfig UIO | 1 | menuconfig UIO |
2 | tristate "Userspace I/O drivers" | 2 | tristate "Userspace I/O drivers" |
3 | depends on MMU | ||
3 | help | 4 | help |
4 | Enable this to allow the userspace driver core code to be | 5 | Enable this to allow the userspace driver core code to be |
5 | built. This code allows userspace programs easy access to | 6 | built. This code allows userspace programs easy access to |
@@ -23,13 +24,6 @@ config UIO_CIF | |||
23 | To compile this driver as a module, choose M here: the module | 24 | To compile this driver as a module, choose M here: the module |
24 | will be called uio_cif. | 25 | will be called uio_cif. |
25 | 26 | ||
26 | config UIO_PDRV | ||
27 | tristate "Userspace I/O platform driver" | ||
28 | help | ||
29 | Generic platform driver for Userspace I/O devices. | ||
30 | |||
31 | If you don't know what to do here, say N. | ||
32 | |||
33 | config UIO_PDRV_GENIRQ | 27 | config UIO_PDRV_GENIRQ |
34 | tristate "Userspace I/O platform driver with generic IRQ handling" | 28 | tristate "Userspace I/O platform driver with generic IRQ handling" |
35 | help | 29 | help |
@@ -128,4 +122,17 @@ config UIO_PRUSS | |||
128 | To compile this driver as a module, choose M here: the module | 122 | To compile this driver as a module, choose M here: the module |
129 | will be called uio_pruss. | 123 | will be called uio_pruss. |
130 | 124 | ||
125 | config UIO_MF624 | ||
126 | tristate "Humusoft MF624 DAQ PCI card driver" | ||
127 | depends on PCI | ||
128 | help | ||
129 | Userspace I/O interface for the Humusoft MF624 PCI card. | ||
130 | A sample userspace application using this driver is available | ||
131 | (among other MF624 related information and software components) | ||
132 | for download in a git repository: | ||
133 | |||
134 | git clone git://rtime.felk.cvut.cz/mf6xx.git | ||
135 | |||
136 | If you compile this as a module, it will be called uio_mf624. | ||
137 | |||
131 | endif | 138 | endif |
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index b354c539507a..d3218bde3aeb 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | obj-$(CONFIG_UIO) += uio.o | 1 | obj-$(CONFIG_UIO) += uio.o |
2 | obj-$(CONFIG_UIO_CIF) += uio_cif.o | 2 | obj-$(CONFIG_UIO_CIF) += uio_cif.o |
3 | obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o | ||
4 | obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o | 3 | obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o |
5 | obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o | 4 | obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o |
6 | obj-$(CONFIG_UIO_AEC) += uio_aec.o | 5 | obj-$(CONFIG_UIO_AEC) += uio_aec.o |
@@ -8,3 +7,4 @@ obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o | |||
8 | obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o | 7 | obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o |
9 | obj-$(CONFIG_UIO_NETX) += uio_netx.o | 8 | obj-$(CONFIG_UIO_NETX) += uio_netx.o |
10 | obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o | 9 | obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o |
10 | obj-$(CONFIG_UIO_MF624) += uio_mf624.o | ||
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 3b96f18593b3..8abe78c0b16f 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -35,7 +35,6 @@ struct uio_device { | |||
35 | atomic_t event; | 35 | atomic_t event; |
36 | struct fasync_struct *async_queue; | 36 | struct fasync_struct *async_queue; |
37 | wait_queue_head_t wait; | 37 | wait_queue_head_t wait; |
38 | int vma_count; | ||
39 | struct uio_info *info; | 38 | struct uio_info *info; |
40 | struct kobject *map_dir; | 39 | struct kobject *map_dir; |
41 | struct kobject *portio_dir; | 40 | struct kobject *portio_dir; |
@@ -593,18 +592,6 @@ static int uio_find_mem_index(struct vm_area_struct *vma) | |||
593 | return -1; | 592 | return -1; |
594 | } | 593 | } |
595 | 594 | ||
596 | static void uio_vma_open(struct vm_area_struct *vma) | ||
597 | { | ||
598 | struct uio_device *idev = vma->vm_private_data; | ||
599 | idev->vma_count++; | ||
600 | } | ||
601 | |||
602 | static void uio_vma_close(struct vm_area_struct *vma) | ||
603 | { | ||
604 | struct uio_device *idev = vma->vm_private_data; | ||
605 | idev->vma_count--; | ||
606 | } | ||
607 | |||
608 | static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 595 | static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
609 | { | 596 | { |
610 | struct uio_device *idev = vma->vm_private_data; | 597 | 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 | return 0; | 617 | return 0; |
631 | } | 618 | } |
632 | 619 | ||
633 | static const struct vm_operations_struct uio_vm_ops = { | 620 | static const struct vm_operations_struct uio_logical_vm_ops = { |
634 | .open = uio_vma_open, | ||
635 | .close = uio_vma_close, | ||
636 | .fault = uio_vma_fault, | 621 | .fault = uio_vma_fault, |
637 | }; | 622 | }; |
638 | 623 | ||
624 | static int uio_mmap_logical(struct vm_area_struct *vma) | ||
625 | { | ||
626 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; | ||
627 | vma->vm_ops = &uio_logical_vm_ops; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static const struct vm_operations_struct uio_physical_vm_ops = { | ||
632 | #ifdef CONFIG_HAVE_IOREMAP_PROT | ||
633 | .access = generic_access_phys, | ||
634 | #endif | ||
635 | }; | ||
636 | |||
639 | static int uio_mmap_physical(struct vm_area_struct *vma) | 637 | static int uio_mmap_physical(struct vm_area_struct *vma) |
640 | { | 638 | { |
641 | struct uio_device *idev = vma->vm_private_data; | 639 | struct uio_device *idev = vma->vm_private_data; |
@@ -643,6 +641,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma) | |||
643 | if (mi < 0) | 641 | if (mi < 0) |
644 | return -EINVAL; | 642 | return -EINVAL; |
645 | 643 | ||
644 | vma->vm_ops = &uio_physical_vm_ops; | ||
645 | |||
646 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 646 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
647 | 647 | ||
648 | return remap_pfn_range(vma, | 648 | return remap_pfn_range(vma, |
@@ -652,14 +652,6 @@ static int uio_mmap_physical(struct vm_area_struct *vma) | |||
652 | vma->vm_page_prot); | 652 | vma->vm_page_prot); |
653 | } | 653 | } |
654 | 654 | ||
655 | static int uio_mmap_logical(struct vm_area_struct *vma) | ||
656 | { | ||
657 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; | ||
658 | vma->vm_ops = &uio_vm_ops; | ||
659 | uio_vma_open(vma); | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static int uio_mmap(struct file *filep, struct vm_area_struct *vma) | 655 | static int uio_mmap(struct file *filep, struct vm_area_struct *vma) |
664 | { | 656 | { |
665 | struct uio_listener *listener = filep->private_data; | 657 | struct uio_listener *listener = filep->private_data; |
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index 125d0e5a6887..1270f3b26139 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c | |||
@@ -146,7 +146,7 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) | |||
146 | 146 | ||
147 | static int uio_dmem_genirq_probe(struct platform_device *pdev) | 147 | static int uio_dmem_genirq_probe(struct platform_device *pdev) |
148 | { | 148 | { |
149 | struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data; | 149 | struct uio_dmem_genirq_pdata *pdata = dev_get_platdata(&pdev->dev); |
150 | struct uio_info *uioinfo = &pdata->uioinfo; | 150 | struct uio_info *uioinfo = &pdata->uioinfo; |
151 | struct uio_dmem_genirq_platdata *priv; | 151 | struct uio_dmem_genirq_platdata *priv; |
152 | struct uio_mem *uiomem; | 152 | struct uio_mem *uiomem; |
diff --git a/drivers/uio/uio_mf624.c b/drivers/uio/uio_mf624.c new file mode 100644 index 000000000000..a1768b2f4493 --- /dev/null +++ b/drivers/uio/uio_mf624.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * UIO driver fo Humusoft MF624 DAQ card. | ||
3 | * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>, | ||
4 | * Czech Technical University in Prague | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/uio_driver.h> | ||
29 | |||
30 | #define PCI_VENDOR_ID_HUMUSOFT 0x186c | ||
31 | #define PCI_DEVICE_ID_MF624 0x0624 | ||
32 | #define PCI_SUBVENDOR_ID_HUMUSOFT 0x186c | ||
33 | #define PCI_SUBDEVICE_DEVICE 0x0624 | ||
34 | |||
35 | /* BAR0 Interrupt control/status register */ | ||
36 | #define INTCSR 0x4C | ||
37 | #define INTCSR_ADINT_ENABLE (1 << 0) | ||
38 | #define INTCSR_CTR4INT_ENABLE (1 << 3) | ||
39 | #define INTCSR_PCIINT_ENABLE (1 << 6) | ||
40 | #define INTCSR_ADINT_STATUS (1 << 2) | ||
41 | #define INTCSR_CTR4INT_STATUS (1 << 5) | ||
42 | |||
43 | enum mf624_interrupt_source {ADC, CTR4, ALL}; | ||
44 | |||
45 | void mf624_disable_interrupt(enum mf624_interrupt_source source, | ||
46 | struct uio_info *info) | ||
47 | { | ||
48 | void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR; | ||
49 | |||
50 | switch (source) { | ||
51 | case ADC: | ||
52 | iowrite32(ioread32(INTCSR_reg) | ||
53 | & ~(INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE), | ||
54 | INTCSR_reg); | ||
55 | break; | ||
56 | |||
57 | case CTR4: | ||
58 | iowrite32(ioread32(INTCSR_reg) | ||
59 | & ~(INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE), | ||
60 | INTCSR_reg); | ||
61 | break; | ||
62 | |||
63 | case ALL: | ||
64 | default: | ||
65 | iowrite32(ioread32(INTCSR_reg) | ||
66 | & ~(INTCSR_ADINT_ENABLE | INTCSR_CTR4INT_ENABLE | ||
67 | | INTCSR_PCIINT_ENABLE), | ||
68 | INTCSR_reg); | ||
69 | break; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | void mf624_enable_interrupt(enum mf624_interrupt_source source, | ||
74 | struct uio_info *info) | ||
75 | { | ||
76 | void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR; | ||
77 | |||
78 | switch (source) { | ||
79 | case ADC: | ||
80 | iowrite32(ioread32(INTCSR_reg) | ||
81 | | INTCSR_ADINT_ENABLE | INTCSR_PCIINT_ENABLE, | ||
82 | INTCSR_reg); | ||
83 | break; | ||
84 | |||
85 | case CTR4: | ||
86 | iowrite32(ioread32(INTCSR_reg) | ||
87 | | INTCSR_CTR4INT_ENABLE | INTCSR_PCIINT_ENABLE, | ||
88 | INTCSR_reg); | ||
89 | break; | ||
90 | |||
91 | case ALL: | ||
92 | default: | ||
93 | iowrite32(ioread32(INTCSR_reg) | ||
94 | | INTCSR_ADINT_ENABLE | INTCSR_CTR4INT_ENABLE | ||
95 | | INTCSR_PCIINT_ENABLE, | ||
96 | INTCSR_reg); | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static irqreturn_t mf624_irq_handler(int irq, struct uio_info *info) | ||
102 | { | ||
103 | void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR; | ||
104 | |||
105 | if ((ioread32(INTCSR_reg) & INTCSR_ADINT_ENABLE) | ||
106 | && (ioread32(INTCSR_reg) & INTCSR_ADINT_STATUS)) { | ||
107 | mf624_disable_interrupt(ADC, info); | ||
108 | return IRQ_HANDLED; | ||
109 | } | ||
110 | |||
111 | if ((ioread32(INTCSR_reg) & INTCSR_CTR4INT_ENABLE) | ||
112 | && (ioread32(INTCSR_reg) & INTCSR_CTR4INT_STATUS)) { | ||
113 | mf624_disable_interrupt(CTR4, info); | ||
114 | return IRQ_HANDLED; | ||
115 | } | ||
116 | |||
117 | return IRQ_NONE; | ||
118 | } | ||
119 | |||
120 | static int mf624_irqcontrol(struct uio_info *info, s32 irq_on) | ||
121 | { | ||
122 | if (irq_on == 0) | ||
123 | mf624_disable_interrupt(ALL, info); | ||
124 | else if (irq_on == 1) | ||
125 | mf624_enable_interrupt(ALL, info); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int mf624_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
131 | { | ||
132 | struct uio_info *info; | ||
133 | |||
134 | info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); | ||
135 | if (!info) | ||
136 | return -ENOMEM; | ||
137 | |||
138 | if (pci_enable_device(dev)) | ||
139 | goto out_free; | ||
140 | |||
141 | if (pci_request_regions(dev, "mf624")) | ||
142 | goto out_disable; | ||
143 | |||
144 | info->name = "mf624"; | ||
145 | info->version = "0.0.1"; | ||
146 | |||
147 | /* Note: Datasheet says device uses BAR0, BAR1, BAR2 -- do not trust it */ | ||
148 | |||
149 | /* BAR0 */ | ||
150 | info->mem[0].name = "PCI chipset, interrupts, status " | ||
151 | "bits, special functions"; | ||
152 | info->mem[0].addr = pci_resource_start(dev, 0); | ||
153 | if (!info->mem[0].addr) | ||
154 | goto out_release; | ||
155 | info->mem[0].size = pci_resource_len(dev, 0); | ||
156 | info->mem[0].memtype = UIO_MEM_PHYS; | ||
157 | info->mem[0].internal_addr = pci_ioremap_bar(dev, 0); | ||
158 | if (!info->mem[0].internal_addr) | ||
159 | goto out_release; | ||
160 | |||
161 | /* BAR2 */ | ||
162 | info->mem[1].name = "ADC, DAC, DIO"; | ||
163 | info->mem[1].addr = pci_resource_start(dev, 2); | ||
164 | if (!info->mem[1].addr) | ||
165 | goto out_unmap0; | ||
166 | info->mem[1].size = pci_resource_len(dev, 2); | ||
167 | info->mem[1].memtype = UIO_MEM_PHYS; | ||
168 | info->mem[1].internal_addr = pci_ioremap_bar(dev, 2); | ||
169 | if (!info->mem[1].internal_addr) | ||
170 | goto out_unmap0; | ||
171 | |||
172 | /* BAR4 */ | ||
173 | info->mem[2].name = "Counter/timer chip"; | ||
174 | info->mem[2].addr = pci_resource_start(dev, 4); | ||
175 | if (!info->mem[2].addr) | ||
176 | goto out_unmap1; | ||
177 | info->mem[2].size = pci_resource_len(dev, 4); | ||
178 | info->mem[2].memtype = UIO_MEM_PHYS; | ||
179 | info->mem[2].internal_addr = pci_ioremap_bar(dev, 4); | ||
180 | if (!info->mem[2].internal_addr) | ||
181 | goto out_unmap1; | ||
182 | |||
183 | info->irq = dev->irq; | ||
184 | info->irq_flags = IRQF_SHARED; | ||
185 | info->handler = mf624_irq_handler; | ||
186 | |||
187 | info->irqcontrol = mf624_irqcontrol; | ||
188 | |||
189 | if (uio_register_device(&dev->dev, info)) | ||
190 | goto out_unmap2; | ||
191 | |||
192 | pci_set_drvdata(dev, info); | ||
193 | |||
194 | return 0; | ||
195 | |||
196 | out_unmap2: | ||
197 | iounmap(info->mem[2].internal_addr); | ||
198 | out_unmap1: | ||
199 | iounmap(info->mem[1].internal_addr); | ||
200 | out_unmap0: | ||
201 | iounmap(info->mem[0].internal_addr); | ||
202 | |||
203 | out_release: | ||
204 | pci_release_regions(dev); | ||
205 | |||
206 | out_disable: | ||
207 | pci_disable_device(dev); | ||
208 | |||
209 | out_free: | ||
210 | kfree(info); | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | |||
214 | static void mf624_pci_remove(struct pci_dev *dev) | ||
215 | { | ||
216 | struct uio_info *info = pci_get_drvdata(dev); | ||
217 | |||
218 | mf624_disable_interrupt(ALL, info); | ||
219 | |||
220 | uio_unregister_device(info); | ||
221 | pci_release_regions(dev); | ||
222 | pci_disable_device(dev); | ||
223 | pci_set_drvdata(dev, NULL); | ||
224 | |||
225 | iounmap(info->mem[0].internal_addr); | ||
226 | iounmap(info->mem[1].internal_addr); | ||
227 | iounmap(info->mem[2].internal_addr); | ||
228 | |||
229 | kfree(info); | ||
230 | } | ||
231 | |||
232 | static DEFINE_PCI_DEVICE_TABLE(mf624_pci_id) = { | ||
233 | { PCI_DEVICE(PCI_VENDOR_ID_HUMUSOFT, PCI_DEVICE_ID_MF624) }, | ||
234 | { 0, } | ||
235 | }; | ||
236 | |||
237 | static struct pci_driver mf624_pci_driver = { | ||
238 | .name = "mf624", | ||
239 | .id_table = mf624_pci_id, | ||
240 | .probe = mf624_pci_probe, | ||
241 | .remove = mf624_pci_remove, | ||
242 | }; | ||
243 | MODULE_DEVICE_TABLE(pci, mf624_pci_id); | ||
244 | |||
245 | module_pci_driver(mf624_pci_driver); | ||
246 | MODULE_LICENSE("GPL v2"); | ||
247 | MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>"); | ||
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c deleted file mode 100644 index 39be9e061700..000000000000 --- a/drivers/uio/uio_pdrv.c +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/uio/uio_pdrv.c | ||
3 | * | ||
4 | * Copyright (C) 2008 by Digi International Inc. | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/uio_driver.h> | ||
13 | #include <linux/stringify.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #define DRIVER_NAME "uio_pdrv" | ||
18 | |||
19 | struct uio_platdata { | ||
20 | struct uio_info *uioinfo; | ||
21 | }; | ||
22 | |||
23 | static int uio_pdrv_probe(struct platform_device *pdev) | ||
24 | { | ||
25 | struct uio_info *uioinfo = pdev->dev.platform_data; | ||
26 | struct uio_platdata *pdata; | ||
27 | struct uio_mem *uiomem; | ||
28 | int ret = -ENODEV; | ||
29 | int i; | ||
30 | |||
31 | if (!uioinfo || !uioinfo->name || !uioinfo->version) { | ||
32 | dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__); | ||
33 | goto err_uioinfo; | ||
34 | } | ||
35 | |||
36 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
37 | if (!pdata) { | ||
38 | ret = -ENOMEM; | ||
39 | dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__); | ||
40 | goto err_alloc_pdata; | ||
41 | } | ||
42 | |||
43 | pdata->uioinfo = uioinfo; | ||
44 | |||
45 | uiomem = &uioinfo->mem[0]; | ||
46 | |||
47 | for (i = 0; i < pdev->num_resources; ++i) { | ||
48 | struct resource *r = &pdev->resource[i]; | ||
49 | |||
50 | if (r->flags != IORESOURCE_MEM) | ||
51 | continue; | ||
52 | |||
53 | if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { | ||
54 | dev_warn(&pdev->dev, "device has more than " | ||
55 | __stringify(MAX_UIO_MAPS) | ||
56 | " I/O memory resources.\n"); | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | uiomem->memtype = UIO_MEM_PHYS; | ||
61 | uiomem->addr = r->start; | ||
62 | uiomem->size = resource_size(r); | ||
63 | uiomem->name = r->name; | ||
64 | ++uiomem; | ||
65 | } | ||
66 | |||
67 | while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { | ||
68 | uiomem->size = 0; | ||
69 | ++uiomem; | ||
70 | } | ||
71 | |||
72 | pdata->uioinfo->priv = pdata; | ||
73 | |||
74 | ret = uio_register_device(&pdev->dev, pdata->uioinfo); | ||
75 | |||
76 | if (ret) { | ||
77 | kfree(pdata); | ||
78 | err_alloc_pdata: | ||
79 | err_uioinfo: | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | platform_set_drvdata(pdev, pdata); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int uio_pdrv_remove(struct platform_device *pdev) | ||
89 | { | ||
90 | struct uio_platdata *pdata = platform_get_drvdata(pdev); | ||
91 | |||
92 | uio_unregister_device(pdata->uioinfo); | ||
93 | |||
94 | kfree(pdata); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static struct platform_driver uio_pdrv = { | ||
100 | .probe = uio_pdrv_probe, | ||
101 | .remove = uio_pdrv_remove, | ||
102 | .driver = { | ||
103 | .name = DRIVER_NAME, | ||
104 | .owner = THIS_MODULE, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | module_platform_driver(uio_pdrv); | ||
109 | |||
110 | MODULE_AUTHOR("Uwe Kleine-Koenig"); | ||
111 | MODULE_DESCRIPTION("Userspace I/O platform driver"); | ||
112 | MODULE_LICENSE("GPL v2"); | ||
113 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index 4eb8eaf71be8..90ff17a0202f 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c | |||
@@ -104,7 +104,7 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) | |||
104 | 104 | ||
105 | static int uio_pdrv_genirq_probe(struct platform_device *pdev) | 105 | static int uio_pdrv_genirq_probe(struct platform_device *pdev) |
106 | { | 106 | { |
107 | struct uio_info *uioinfo = pdev->dev.platform_data; | 107 | struct uio_info *uioinfo = dev_get_platdata(&pdev->dev); |
108 | struct uio_pdrv_genirq_platdata *priv; | 108 | struct uio_pdrv_genirq_platdata *priv; |
109 | struct uio_mem *uiomem; | 109 | struct uio_mem *uiomem; |
110 | int ret = -EINVAL; | 110 | int ret = -EINVAL; |
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c index 21f7a72301e4..f519da9034b7 100644 --- a/drivers/uio/uio_pruss.c +++ b/drivers/uio/uio_pruss.c | |||
@@ -121,7 +121,7 @@ static int pruss_probe(struct platform_device *dev) | |||
121 | struct uio_pruss_dev *gdev; | 121 | struct uio_pruss_dev *gdev; |
122 | struct resource *regs_prussio; | 122 | struct resource *regs_prussio; |
123 | int ret = -ENODEV, cnt = 0, len; | 123 | int ret = -ENODEV, cnt = 0, len; |
124 | struct uio_pruss_pdata *pdata = dev->dev.platform_data; | 124 | struct uio_pruss_pdata *pdata = dev_get_platdata(&dev->dev); |
125 | 125 | ||
126 | gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); | 126 | gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); |
127 | if (!gdev) | 127 | if (!gdev) |
@@ -224,7 +224,6 @@ static int pruss_remove(struct platform_device *dev) | |||
224 | struct uio_pruss_dev *gdev = platform_get_drvdata(dev); | 224 | struct uio_pruss_dev *gdev = platform_get_drvdata(dev); |
225 | 225 | ||
226 | pruss_cleanup(dev, gdev); | 226 | pruss_cleanup(dev, gdev); |
227 | platform_set_drvdata(dev, NULL); | ||
228 | return 0; | 227 | return 0; |
229 | } | 228 | } |
230 | 229 | ||
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 3e225d5846f6..f969ea266acb 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config USB_DWC3 | 1 | config USB_DWC3 |
2 | tristate "DesignWare USB3 DRD Core Support" | 2 | tristate "DesignWare USB3 DRD Core Support" |
3 | depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA | 3 | depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA |
4 | depends on EXTCON | ||
4 | select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD | 5 | select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD |
5 | help | 6 | help |
6 | Say Y or M here if your system has a Dual Role SuperSpeed | 7 | Say Y or M here if your system has a Dual Role SuperSpeed |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ecd99451ee90..7f7ea62e961b 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -23,13 +23,15 @@ | |||
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/platform_data/dwc3-omap.h> | 25 | #include <linux/platform_data/dwc3-omap.h> |
26 | #include <linux/usb/dwc3-omap.h> | ||
27 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
28 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
29 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
30 | #include <linux/io.h> | 29 | #include <linux/io.h> |
31 | #include <linux/of.h> | 30 | #include <linux/of.h> |
32 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
32 | #include <linux/extcon.h> | ||
33 | #include <linux/extcon/of_extcon.h> | ||
34 | #include <linux/regulator/consumer.h> | ||
33 | 35 | ||
34 | #include <linux/usb/otg.h> | 36 | #include <linux/usb/otg.h> |
35 | 37 | ||
@@ -135,9 +137,21 @@ struct dwc3_omap { | |||
135 | u32 revision; | 137 | u32 revision; |
136 | 138 | ||
137 | u32 dma_status:1; | 139 | u32 dma_status:1; |
140 | |||
141 | struct extcon_specific_cable_nb extcon_vbus_dev; | ||
142 | struct extcon_specific_cable_nb extcon_id_dev; | ||
143 | struct notifier_block vbus_nb; | ||
144 | struct notifier_block id_nb; | ||
145 | |||
146 | struct regulator *vbus_reg; | ||
138 | }; | 147 | }; |
139 | 148 | ||
140 | static struct dwc3_omap *_omap; | 149 | enum omap_dwc3_vbus_id_status { |
150 | OMAP_DWC3_ID_FLOAT, | ||
151 | OMAP_DWC3_ID_GROUND, | ||
152 | OMAP_DWC3_VBUS_OFF, | ||
153 | OMAP_DWC3_VBUS_VALID, | ||
154 | }; | ||
141 | 155 | ||
142 | static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) | 156 | static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) |
143 | { | 157 | { |
@@ -201,18 +215,24 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) | |||
201 | omap->irq0_offset, value); | 215 | omap->irq0_offset, value); |
202 | } | 216 | } |
203 | 217 | ||
204 | int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | 218 | static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, |
219 | enum omap_dwc3_vbus_id_status status) | ||
205 | { | 220 | { |
206 | u32 val; | 221 | int ret; |
207 | struct dwc3_omap *omap = _omap; | 222 | u32 val; |
208 | |||
209 | if (!omap) | ||
210 | return -EPROBE_DEFER; | ||
211 | 223 | ||
212 | switch (status) { | 224 | switch (status) { |
213 | case OMAP_DWC3_ID_GROUND: | 225 | case OMAP_DWC3_ID_GROUND: |
214 | dev_dbg(omap->dev, "ID GND\n"); | 226 | dev_dbg(omap->dev, "ID GND\n"); |
215 | 227 | ||
228 | if (omap->vbus_reg) { | ||
229 | ret = regulator_enable(omap->vbus_reg); | ||
230 | if (ret) { | ||
231 | dev_dbg(omap->dev, "regulator enable failed\n"); | ||
232 | return; | ||
233 | } | ||
234 | } | ||
235 | |||
216 | val = dwc3_omap_read_utmi_status(omap); | 236 | val = dwc3_omap_read_utmi_status(omap); |
217 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG | 237 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG |
218 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 238 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
@@ -235,6 +255,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | |||
235 | break; | 255 | break; |
236 | 256 | ||
237 | case OMAP_DWC3_ID_FLOAT: | 257 | case OMAP_DWC3_ID_FLOAT: |
258 | if (omap->vbus_reg) | ||
259 | regulator_disable(omap->vbus_reg); | ||
260 | |||
238 | case OMAP_DWC3_VBUS_OFF: | 261 | case OMAP_DWC3_VBUS_OFF: |
239 | dev_dbg(omap->dev, "VBUS Disconnect\n"); | 262 | dev_dbg(omap->dev, "VBUS Disconnect\n"); |
240 | 263 | ||
@@ -248,12 +271,9 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | |||
248 | break; | 271 | break; |
249 | 272 | ||
250 | default: | 273 | default: |
251 | dev_dbg(omap->dev, "ID float\n"); | 274 | dev_dbg(omap->dev, "invalid state\n"); |
252 | } | 275 | } |
253 | |||
254 | return 0; | ||
255 | } | 276 | } |
256 | EXPORT_SYMBOL_GPL(dwc3_omap_mailbox); | ||
257 | 277 | ||
258 | static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) | 278 | static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) |
259 | { | 279 | { |
@@ -346,6 +366,32 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) | |||
346 | 366 | ||
347 | static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); | 367 | static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); |
348 | 368 | ||
369 | static int dwc3_omap_id_notifier(struct notifier_block *nb, | ||
370 | unsigned long event, void *ptr) | ||
371 | { | ||
372 | struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb); | ||
373 | |||
374 | if (event) | ||
375 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); | ||
376 | else | ||
377 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); | ||
378 | |||
379 | return NOTIFY_DONE; | ||
380 | } | ||
381 | |||
382 | static int dwc3_omap_vbus_notifier(struct notifier_block *nb, | ||
383 | unsigned long event, void *ptr) | ||
384 | { | ||
385 | struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb); | ||
386 | |||
387 | if (event) | ||
388 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); | ||
389 | else | ||
390 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); | ||
391 | |||
392 | return NOTIFY_DONE; | ||
393 | } | ||
394 | |||
349 | static int dwc3_omap_probe(struct platform_device *pdev) | 395 | static int dwc3_omap_probe(struct platform_device *pdev) |
350 | { | 396 | { |
351 | struct device_node *node = pdev->dev.of_node; | 397 | struct device_node *node = pdev->dev.of_node; |
@@ -353,6 +399,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
353 | struct dwc3_omap *omap; | 399 | struct dwc3_omap *omap; |
354 | struct resource *res; | 400 | struct resource *res; |
355 | struct device *dev = &pdev->dev; | 401 | struct device *dev = &pdev->dev; |
402 | struct extcon_dev *edev; | ||
403 | struct regulator *vbus_reg = NULL; | ||
356 | 404 | ||
357 | int ret = -ENOMEM; | 405 | int ret = -ENOMEM; |
358 | int irq; | 406 | int irq; |
@@ -393,19 +441,22 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
393 | if (IS_ERR(base)) | 441 | if (IS_ERR(base)) |
394 | return PTR_ERR(base); | 442 | return PTR_ERR(base); |
395 | 443 | ||
444 | if (of_property_read_bool(node, "vbus-supply")) { | ||
445 | vbus_reg = devm_regulator_get(dev, "vbus"); | ||
446 | if (IS_ERR(vbus_reg)) { | ||
447 | dev_err(dev, "vbus init failed\n"); | ||
448 | return PTR_ERR(vbus_reg); | ||
449 | } | ||
450 | } | ||
451 | |||
396 | spin_lock_init(&omap->lock); | 452 | spin_lock_init(&omap->lock); |
397 | 453 | ||
398 | omap->dev = dev; | 454 | omap->dev = dev; |
399 | omap->irq = irq; | 455 | omap->irq = irq; |
400 | omap->base = base; | 456 | omap->base = base; |
457 | omap->vbus_reg = vbus_reg; | ||
401 | dev->dma_mask = &dwc3_omap_dma_mask; | 458 | dev->dma_mask = &dwc3_omap_dma_mask; |
402 | 459 | ||
403 | /* | ||
404 | * REVISIT if we ever have two instances of the wrapper, we will be | ||
405 | * in big trouble | ||
406 | */ | ||
407 | _omap = omap; | ||
408 | |||
409 | pm_runtime_enable(dev); | 460 | pm_runtime_enable(dev); |
410 | ret = pm_runtime_get_sync(dev); | 461 | ret = pm_runtime_get_sync(dev); |
411 | if (ret < 0) { | 462 | if (ret < 0) { |
@@ -480,14 +531,46 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
480 | 531 | ||
481 | dwc3_omap_enable_irqs(omap); | 532 | dwc3_omap_enable_irqs(omap); |
482 | 533 | ||
534 | if (of_property_read_bool(node, "extcon")) { | ||
535 | edev = of_extcon_get_extcon_dev(dev, 0); | ||
536 | if (IS_ERR(edev)) { | ||
537 | dev_vdbg(dev, "couldn't get extcon device\n"); | ||
538 | ret = PTR_ERR(edev); | ||
539 | goto err2; | ||
540 | } | ||
541 | |||
542 | omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; | ||
543 | ret = extcon_register_interest(&omap->extcon_vbus_dev, | ||
544 | edev->name, "USB", &omap->vbus_nb); | ||
545 | if (ret < 0) | ||
546 | dev_vdbg(dev, "failed to register notifier for USB\n"); | ||
547 | omap->id_nb.notifier_call = dwc3_omap_id_notifier; | ||
548 | ret = extcon_register_interest(&omap->extcon_id_dev, edev->name, | ||
549 | "USB-HOST", &omap->id_nb); | ||
550 | if (ret < 0) | ||
551 | dev_vdbg(dev, | ||
552 | "failed to register notifier for USB-HOST\n"); | ||
553 | |||
554 | if (extcon_get_cable_state(edev, "USB") == true) | ||
555 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); | ||
556 | if (extcon_get_cable_state(edev, "USB-HOST") == true) | ||
557 | dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); | ||
558 | } | ||
559 | |||
483 | ret = of_platform_populate(node, NULL, NULL, dev); | 560 | ret = of_platform_populate(node, NULL, NULL, dev); |
484 | if (ret) { | 561 | if (ret) { |
485 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); | 562 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); |
486 | goto err2; | 563 | goto err3; |
487 | } | 564 | } |
488 | 565 | ||
489 | return 0; | 566 | return 0; |
490 | 567 | ||
568 | err3: | ||
569 | if (omap->extcon_vbus_dev.edev) | ||
570 | extcon_unregister_interest(&omap->extcon_vbus_dev); | ||
571 | if (omap->extcon_id_dev.edev) | ||
572 | extcon_unregister_interest(&omap->extcon_id_dev); | ||
573 | |||
491 | err2: | 574 | err2: |
492 | dwc3_omap_disable_irqs(omap); | 575 | dwc3_omap_disable_irqs(omap); |
493 | 576 | ||
@@ -504,6 +587,10 @@ static int dwc3_omap_remove(struct platform_device *pdev) | |||
504 | { | 587 | { |
505 | struct dwc3_omap *omap = platform_get_drvdata(pdev); | 588 | struct dwc3_omap *omap = platform_get_drvdata(pdev); |
506 | 589 | ||
590 | if (omap->extcon_vbus_dev.edev) | ||
591 | extcon_unregister_interest(&omap->extcon_vbus_dev); | ||
592 | if (omap->extcon_id_dev.edev) | ||
593 | extcon_unregister_interest(&omap->extcon_id_dev); | ||
507 | dwc3_omap_disable_irqs(omap); | 594 | dwc3_omap_disable_irqs(omap); |
508 | pm_runtime_put_sync(&pdev->dev); | 595 | pm_runtime_put_sync(&pdev->dev); |
509 | pm_runtime_disable(&pdev->dev); | 596 | pm_runtime_disable(&pdev->dev); |
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c index d4d2c5fe2488..8ac99b87c07e 100644 --- a/drivers/video/hyperv_fb.c +++ b/drivers/video/hyperv_fb.c | |||
@@ -825,5 +825,4 @@ module_init(hvfb_drv_init); | |||
825 | module_exit(hvfb_drv_exit); | 825 | module_exit(hvfb_drv_exit); |
826 | 826 | ||
827 | MODULE_LICENSE("GPL"); | 827 | MODULE_LICENSE("GPL"); |
828 | MODULE_VERSION(HV_DRV_VERSION); | ||
829 | MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver"); | 828 | MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver"); |
diff --git a/drivers/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c index dd22b5072e21..cf74aee2cef0 100644 --- a/drivers/vme/boards/vme_vmivme7805.c +++ b/drivers/vme/boards/vme_vmivme7805.c | |||
@@ -23,7 +23,7 @@ static int vmic_probe(struct pci_dev *, const struct pci_device_id *); | |||
23 | static void vmic_remove(struct pci_dev *); | 23 | static void vmic_remove(struct pci_dev *); |
24 | 24 | ||
25 | /** Base address to access FPGA register */ | 25 | /** Base address to access FPGA register */ |
26 | static void *vmic_base; | 26 | static void __iomem *vmic_base; |
27 | 27 | ||
28 | static const char driver_name[] = "vmivme_7805"; | 28 | static const char driver_name[] = "vmivme_7805"; |
29 | 29 | ||
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index 64bfea314429..f8448573d030 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c | |||
@@ -243,6 +243,8 @@ static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge) | |||
243 | static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, | 243 | static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, |
244 | struct pci_dev *pdev) | 244 | struct pci_dev *pdev) |
245 | { | 245 | { |
246 | struct vme_bridge *ca91cx42_bridge; | ||
247 | |||
246 | /* Disable interrupts from PCI to VME */ | 248 | /* Disable interrupts from PCI to VME */ |
247 | iowrite32(0, bridge->base + VINT_EN); | 249 | iowrite32(0, bridge->base + VINT_EN); |
248 | 250 | ||
@@ -251,7 +253,9 @@ static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge, | |||
251 | /* Clear Any Pending PCI Interrupts */ | 253 | /* Clear Any Pending PCI Interrupts */ |
252 | iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); | 254 | iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); |
253 | 255 | ||
254 | free_irq(pdev->irq, pdev); | 256 | ca91cx42_bridge = container_of((void *)bridge, struct vme_bridge, |
257 | driver_priv); | ||
258 | free_irq(pdev->irq, ca91cx42_bridge); | ||
255 | } | 259 | } |
256 | 260 | ||
257 | static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level) | 261 | 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 | void *buf, size_t count, loff_t offset) | 860 | void *buf, size_t count, loff_t offset) |
857 | { | 861 | { |
858 | ssize_t retval; | 862 | ssize_t retval; |
859 | void *addr = image->kern_base + offset; | 863 | void __iomem *addr = image->kern_base + offset; |
860 | unsigned int done = 0; | 864 | unsigned int done = 0; |
861 | unsigned int count32; | 865 | unsigned int count32; |
862 | 866 | ||
@@ -916,7 +920,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, | |||
916 | void *buf, size_t count, loff_t offset) | 920 | void *buf, size_t count, loff_t offset) |
917 | { | 921 | { |
918 | ssize_t retval; | 922 | ssize_t retval; |
919 | void *addr = image->kern_base + offset; | 923 | void __iomem *addr = image->kern_base + offset; |
920 | unsigned int done = 0; | 924 | unsigned int done = 0; |
921 | unsigned int count32; | 925 | unsigned int count32; |
922 | 926 | ||
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 94c892f27be4..9cf88337e4e9 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c | |||
@@ -1267,7 +1267,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf, | |||
1267 | u32 aspace, cycle, dwidth; | 1267 | u32 aspace, cycle, dwidth; |
1268 | struct vme_bus_error *vme_err = NULL; | 1268 | struct vme_bus_error *vme_err = NULL; |
1269 | struct vme_bridge *tsi148_bridge; | 1269 | struct vme_bridge *tsi148_bridge; |
1270 | void *addr = image->kern_base + offset; | 1270 | void __iomem *addr = image->kern_base + offset; |
1271 | unsigned int done = 0; | 1271 | unsigned int done = 0; |
1272 | unsigned int count32; | 1272 | unsigned int count32; |
1273 | 1273 | ||
@@ -1348,7 +1348,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf, | |||
1348 | int retval = 0, enabled; | 1348 | int retval = 0, enabled; |
1349 | unsigned long long vme_base, size; | 1349 | unsigned long long vme_base, size; |
1350 | u32 aspace, cycle, dwidth; | 1350 | u32 aspace, cycle, dwidth; |
1351 | void *addr = image->kern_base + offset; | 1351 | void __iomem *addr = image->kern_base + offset; |
1352 | unsigned int done = 0; | 1352 | unsigned int done = 0; |
1353 | unsigned int count32; | 1353 | unsigned int count32; |
1354 | 1354 | ||
diff --git a/include/linux/extcon/of_extcon.h b/include/linux/extcon/of_extcon.h new file mode 100644 index 000000000000..0ebfeff1b55d --- /dev/null +++ b/include/linux/extcon/of_extcon.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * OF helpers for External connector (extcon) framework | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments, Inc. | ||
5 | * Kishon Vijay Abraham I <kishon@ti.com> | ||
6 | * | ||
7 | * Copyright (C) 2013 Samsung Electronics | ||
8 | * Chanwoo Choi <cw00.choi@samsung.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef __LINUX_OF_EXTCON_H | ||
17 | #define __LINUX_OF_EXTCON_H | ||
18 | |||
19 | #include <linux/err.h> | ||
20 | |||
21 | #if IS_ENABLED(CONFIG_OF_EXTCON) | ||
22 | extern struct extcon_dev | ||
23 | *of_extcon_get_extcon_dev(struct device *dev, int index); | ||
24 | #else | ||
25 | static inline struct extcon_dev | ||
26 | *of_extcon_get_extcon_dev(struct device *dev, int index) | ||
27 | { | ||
28 | return ERR_PTR(-ENOSYS); | ||
29 | } | ||
30 | #endif /* CONFIG_OF_EXTCON */ | ||
31 | #endif /* __LINUX_OF_EXTCON_H */ | ||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index fae8bac907ef..a3b8b2e2d244 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -27,6 +27,14 @@ | |||
27 | 27 | ||
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | 29 | ||
30 | /* | ||
31 | * Framework version for util services. | ||
32 | */ | ||
33 | |||
34 | #define UTIL_FW_MAJOR 3 | ||
35 | #define UTIL_FW_MINOR 0 | ||
36 | #define UTIL_FW_MAJOR_MINOR (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR) | ||
37 | |||
30 | 38 | ||
31 | /* | 39 | /* |
32 | * Implementation of host controlled snapshot of the guest. | 40 | * Implementation of host controlled snapshot of the guest. |
@@ -455,27 +463,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, | |||
455 | *read = dsize - *write; | 463 | *read = dsize - *write; |
456 | } | 464 | } |
457 | 465 | ||
458 | |||
459 | /* | ||
460 | * We use the same version numbering for all Hyper-V modules. | ||
461 | * | ||
462 | * Definition of versioning is as follows; | ||
463 | * | ||
464 | * Major Number Changes for these scenarios; | ||
465 | * 1. When a new version of Windows Hyper-V | ||
466 | * is released. | ||
467 | * 2. A Major change has occurred in the | ||
468 | * Linux IC's. | ||
469 | * (For example the merge for the first time | ||
470 | * into the kernel) Every time the Major Number | ||
471 | * changes, the Revision number is reset to 0. | ||
472 | * Minor Number Changes when new functionality is added | ||
473 | * to the Linux IC's that is not a bug fix. | ||
474 | * | ||
475 | * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync | ||
476 | */ | ||
477 | #define HV_DRV_VERSION "3.1" | ||
478 | |||
479 | /* | 466 | /* |
480 | * VMBUS version is 32 bit entity broken up into | 467 | * VMBUS version is 32 bit entity broken up into |
481 | * two 16 bit quantities: major_number. minor_number. | 468 | * two 16 bit quantities: major_number. minor_number. |
@@ -1494,7 +1481,7 @@ struct hyperv_service_callback { | |||
1494 | }; | 1481 | }; |
1495 | 1482 | ||
1496 | #define MAX_SRV_VER 0x7ffffff | 1483 | #define MAX_SRV_VER 0x7ffffff |
1497 | extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, | 1484 | extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, |
1498 | struct icmsg_negotiate *, u8 *, int, | 1485 | struct icmsg_negotiate *, u8 *, int, |
1499 | int); | 1486 | int); |
1500 | 1487 | ||
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index c06d78af3342..e6090d88e91d 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h | |||
@@ -372,17 +372,15 @@ struct palmas_usb { | |||
372 | 372 | ||
373 | struct extcon_dev edev; | 373 | struct extcon_dev edev; |
374 | 374 | ||
375 | /* used to set vbus, in atomic path */ | ||
376 | struct work_struct set_vbus_work; | ||
377 | |||
378 | int id_otg_irq; | 375 | int id_otg_irq; |
379 | int id_irq; | 376 | int id_irq; |
380 | int vbus_otg_irq; | 377 | int vbus_otg_irq; |
381 | int vbus_irq; | 378 | int vbus_irq; |
382 | 379 | ||
383 | int vbus_enable; | ||
384 | |||
385 | enum palmas_usb_state linkstat; | 380 | enum palmas_usb_state linkstat; |
381 | int wakeup; | ||
382 | bool enable_vbus_detection; | ||
383 | bool enable_id_detection; | ||
386 | }; | 384 | }; |
387 | 385 | ||
388 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) | 386 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) |
diff --git a/include/linux/usb/dwc3-omap.h b/include/linux/usb/dwc3-omap.h deleted file mode 100644 index 5615f4d82724..000000000000 --- a/include/linux/usb/dwc3-omap.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 by Texas Instruments | ||
3 | * | ||
4 | * The Inventra Controller Driver for Linux is free software; you | ||
5 | * can redistribute it and/or modify it under the terms of the GNU | ||
6 | * General Public License version 2 as published by the Free Software | ||
7 | * Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef __DWC3_OMAP_H__ | ||
11 | #define __DWC3_OMAP_H__ | ||
12 | |||
13 | enum omap_dwc3_vbus_id_status { | ||
14 | OMAP_DWC3_UNKNOWN = 0, | ||
15 | OMAP_DWC3_ID_GROUND, | ||
16 | OMAP_DWC3_ID_FLOAT, | ||
17 | OMAP_DWC3_VBUS_VALID, | ||
18 | OMAP_DWC3_VBUS_OFF, | ||
19 | }; | ||
20 | |||
21 | #if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE)) | ||
22 | extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status); | ||
23 | #else | ||
24 | static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | ||
25 | { | ||
26 | return -ENODEV; | ||
27 | } | ||
28 | #endif | ||
29 | |||
30 | #endif /* __DWC3_OMAP_H__ */ | ||
diff --git a/mm/memory.c b/mm/memory.c index af84bc0ec17c..b3c6bf9a398e 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -4079,6 +4079,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, | |||
4079 | 4079 | ||
4080 | return len; | 4080 | return len; |
4081 | } | 4081 | } |
4082 | EXPORT_SYMBOL_GPL(generic_access_phys); | ||
4082 | #endif | 4083 | #endif |
4083 | 4084 | ||
4084 | /* | 4085 | /* |
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 07819bfa7dba..8fd9ec66121c 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -79,8 +79,6 @@ enum { | |||
79 | DNS | 79 | DNS |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static char kvp_send_buffer[4096]; | ||
83 | static char kvp_recv_buffer[4096 * 2]; | ||
84 | static struct sockaddr_nl addr; | 82 | static struct sockaddr_nl addr; |
85 | static int in_hand_shake = 1; | 83 | static int in_hand_shake = 1; |
86 | 84 | ||
@@ -1301,6 +1299,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | |||
1301 | } | 1299 | } |
1302 | 1300 | ||
1303 | error = kvp_write_file(file, "HWADDR", "", mac_addr); | 1301 | error = kvp_write_file(file, "HWADDR", "", mac_addr); |
1302 | free(mac_addr); | ||
1304 | if (error) | 1303 | if (error) |
1305 | goto setval_error; | 1304 | goto setval_error; |
1306 | 1305 | ||
@@ -1346,7 +1345,6 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | |||
1346 | goto setval_error; | 1345 | goto setval_error; |
1347 | 1346 | ||
1348 | setval_done: | 1347 | setval_done: |
1349 | free(mac_addr); | ||
1350 | fclose(file); | 1348 | fclose(file); |
1351 | 1349 | ||
1352 | /* | 1350 | /* |
@@ -1355,12 +1353,15 @@ setval_done: | |||
1355 | */ | 1353 | */ |
1356 | 1354 | ||
1357 | snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); | 1355 | snprintf(cmd, sizeof(cmd), "%s %s", "hv_set_ifconfig", if_file); |
1358 | system(cmd); | 1356 | if (system(cmd)) { |
1357 | syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", | ||
1358 | cmd, errno, strerror(errno)); | ||
1359 | return HV_E_FAIL; | ||
1360 | } | ||
1359 | return 0; | 1361 | return 0; |
1360 | 1362 | ||
1361 | setval_error: | 1363 | setval_error: |
1362 | syslog(LOG_ERR, "Failed to write config file"); | 1364 | syslog(LOG_ERR, "Failed to write config file"); |
1363 | free(mac_addr); | ||
1364 | fclose(file); | 1365 | fclose(file); |
1365 | return error; | 1366 | return error; |
1366 | } | 1367 | } |
@@ -1391,23 +1392,18 @@ kvp_get_domain_name(char *buffer, int length) | |||
1391 | static int | 1392 | static int |
1392 | netlink_send(int fd, struct cn_msg *msg) | 1393 | netlink_send(int fd, struct cn_msg *msg) |
1393 | { | 1394 | { |
1394 | struct nlmsghdr *nlh; | 1395 | struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; |
1395 | unsigned int size; | 1396 | unsigned int size; |
1396 | struct msghdr message; | 1397 | struct msghdr message; |
1397 | char buffer[64]; | ||
1398 | struct iovec iov[2]; | 1398 | struct iovec iov[2]; |
1399 | 1399 | ||
1400 | size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); | 1400 | size = sizeof(struct cn_msg) + msg->len; |
1401 | 1401 | ||
1402 | nlh = (struct nlmsghdr *)buffer; | 1402 | nlh.nlmsg_pid = getpid(); |
1403 | nlh->nlmsg_seq = 0; | 1403 | nlh.nlmsg_len = NLMSG_LENGTH(size); |
1404 | nlh->nlmsg_pid = getpid(); | ||
1405 | nlh->nlmsg_type = NLMSG_DONE; | ||
1406 | nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); | ||
1407 | nlh->nlmsg_flags = 0; | ||
1408 | 1404 | ||
1409 | iov[0].iov_base = nlh; | 1405 | iov[0].iov_base = &nlh; |
1410 | iov[0].iov_len = sizeof(*nlh); | 1406 | iov[0].iov_len = sizeof(nlh); |
1411 | 1407 | ||
1412 | iov[1].iov_base = msg; | 1408 | iov[1].iov_base = msg; |
1413 | iov[1].iov_len = size; | 1409 | iov[1].iov_len = size; |
@@ -1437,10 +1433,22 @@ int main(void) | |||
1437 | int pool; | 1433 | int pool; |
1438 | char *if_name; | 1434 | char *if_name; |
1439 | struct hv_kvp_ipaddr_value *kvp_ip_val; | 1435 | struct hv_kvp_ipaddr_value *kvp_ip_val; |
1436 | char *kvp_send_buffer; | ||
1437 | char *kvp_recv_buffer; | ||
1438 | size_t kvp_recv_buffer_len; | ||
1440 | 1439 | ||
1441 | daemon(1, 0); | 1440 | if (daemon(1, 0)) |
1441 | return 1; | ||
1442 | openlog("KVP", 0, LOG_USER); | 1442 | openlog("KVP", 0, LOG_USER); |
1443 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); | 1443 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); |
1444 | |||
1445 | kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg); | ||
1446 | kvp_send_buffer = calloc(1, kvp_recv_buffer_len); | ||
1447 | kvp_recv_buffer = calloc(1, kvp_recv_buffer_len); | ||
1448 | if (!(kvp_send_buffer && kvp_recv_buffer)) { | ||
1449 | syslog(LOG_ERR, "Failed to allocate netlink buffers"); | ||
1450 | exit(EXIT_FAILURE); | ||
1451 | } | ||
1444 | /* | 1452 | /* |
1445 | * Retrieve OS release information. | 1453 | * Retrieve OS release information. |
1446 | */ | 1454 | */ |
@@ -1514,7 +1522,7 @@ int main(void) | |||
1514 | continue; | 1522 | continue; |
1515 | } | 1523 | } |
1516 | 1524 | ||
1517 | len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, | 1525 | len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0, |
1518 | addr_p, &addr_l); | 1526 | addr_p, &addr_l); |
1519 | 1527 | ||
1520 | if (len < 0) { | 1528 | if (len < 0) { |
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index fea03a3edaf4..8611962c672c 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c | |||
@@ -38,8 +38,6 @@ | |||
38 | #include <linux/netlink.h> | 38 | #include <linux/netlink.h> |
39 | #include <syslog.h> | 39 | #include <syslog.h> |
40 | 40 | ||
41 | static char vss_recv_buffer[4096]; | ||
42 | static char vss_send_buffer[4096]; | ||
43 | static struct sockaddr_nl addr; | 41 | static struct sockaddr_nl addr; |
44 | 42 | ||
45 | #ifndef SOL_NETLINK | 43 | #ifndef SOL_NETLINK |
@@ -107,23 +105,18 @@ static int vss_operate(int operation) | |||
107 | 105 | ||
108 | static int netlink_send(int fd, struct cn_msg *msg) | 106 | static int netlink_send(int fd, struct cn_msg *msg) |
109 | { | 107 | { |
110 | struct nlmsghdr *nlh; | 108 | struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; |
111 | unsigned int size; | 109 | unsigned int size; |
112 | struct msghdr message; | 110 | struct msghdr message; |
113 | char buffer[64]; | ||
114 | struct iovec iov[2]; | 111 | struct iovec iov[2]; |
115 | 112 | ||
116 | size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); | 113 | size = sizeof(struct cn_msg) + msg->len; |
117 | 114 | ||
118 | nlh = (struct nlmsghdr *)buffer; | 115 | nlh.nlmsg_pid = getpid(); |
119 | nlh->nlmsg_seq = 0; | 116 | nlh.nlmsg_len = NLMSG_LENGTH(size); |
120 | nlh->nlmsg_pid = getpid(); | ||
121 | nlh->nlmsg_type = NLMSG_DONE; | ||
122 | nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); | ||
123 | nlh->nlmsg_flags = 0; | ||
124 | 117 | ||
125 | iov[0].iov_base = nlh; | 118 | iov[0].iov_base = &nlh; |
126 | iov[0].iov_len = sizeof(*nlh); | 119 | iov[0].iov_len = sizeof(nlh); |
127 | 120 | ||
128 | iov[1].iov_base = msg; | 121 | iov[1].iov_base = msg; |
129 | iov[1].iov_len = size; | 122 | iov[1].iov_len = size; |
@@ -147,6 +140,9 @@ int main(void) | |||
147 | struct cn_msg *incoming_cn_msg; | 140 | struct cn_msg *incoming_cn_msg; |
148 | int op; | 141 | int op; |
149 | struct hv_vss_msg *vss_msg; | 142 | struct hv_vss_msg *vss_msg; |
143 | char *vss_send_buffer; | ||
144 | char *vss_recv_buffer; | ||
145 | size_t vss_recv_buffer_len; | ||
150 | 146 | ||
151 | if (daemon(1, 0)) | 147 | if (daemon(1, 0)) |
152 | return 1; | 148 | return 1; |
@@ -154,9 +150,18 @@ int main(void) | |||
154 | openlog("Hyper-V VSS", 0, LOG_USER); | 150 | openlog("Hyper-V VSS", 0, LOG_USER); |
155 | syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); | 151 | syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); |
156 | 152 | ||
153 | vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg); | ||
154 | vss_send_buffer = calloc(1, vss_recv_buffer_len); | ||
155 | vss_recv_buffer = calloc(1, vss_recv_buffer_len); | ||
156 | if (!(vss_send_buffer && vss_recv_buffer)) { | ||
157 | syslog(LOG_ERR, "Failed to allocate netlink buffers"); | ||
158 | exit(EXIT_FAILURE); | ||
159 | } | ||
160 | |||
157 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); | 161 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); |
158 | if (fd < 0) { | 162 | if (fd < 0) { |
159 | syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); | 163 | syslog(LOG_ERR, "netlink socket creation failed; error:%d %s", |
164 | errno, strerror(errno)); | ||
160 | exit(EXIT_FAILURE); | 165 | exit(EXIT_FAILURE); |
161 | } | 166 | } |
162 | addr.nl_family = AF_NETLINK; | 167 | addr.nl_family = AF_NETLINK; |
@@ -167,12 +172,16 @@ int main(void) | |||
167 | 172 | ||
168 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); | 173 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); |
169 | if (error < 0) { | 174 | if (error < 0) { |
170 | syslog(LOG_ERR, "bind failed; error:%d", error); | 175 | syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno)); |
171 | close(fd); | 176 | close(fd); |
172 | exit(EXIT_FAILURE); | 177 | exit(EXIT_FAILURE); |
173 | } | 178 | } |
174 | nl_group = CN_VSS_IDX; | 179 | nl_group = CN_VSS_IDX; |
175 | setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); | 180 | if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { |
181 | syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno)); | ||
182 | close(fd); | ||
183 | exit(EXIT_FAILURE); | ||
184 | } | ||
176 | /* | 185 | /* |
177 | * Register ourselves with the kernel. | 186 | * Register ourselves with the kernel. |
178 | */ | 187 | */ |
@@ -187,7 +196,7 @@ int main(void) | |||
187 | 196 | ||
188 | len = netlink_send(fd, message); | 197 | len = netlink_send(fd, message); |
189 | if (len < 0) { | 198 | if (len < 0) { |
190 | syslog(LOG_ERR, "netlink_send failed; error:%d", len); | 199 | syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno)); |
191 | close(fd); | 200 | close(fd); |
192 | exit(EXIT_FAILURE); | 201 | exit(EXIT_FAILURE); |
193 | } | 202 | } |
@@ -199,9 +208,18 @@ int main(void) | |||
199 | socklen_t addr_l = sizeof(addr); | 208 | socklen_t addr_l = sizeof(addr); |
200 | pfd.events = POLLIN; | 209 | pfd.events = POLLIN; |
201 | pfd.revents = 0; | 210 | pfd.revents = 0; |
202 | poll(&pfd, 1, -1); | ||
203 | 211 | ||
204 | len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0, | 212 | if (poll(&pfd, 1, -1) < 0) { |
213 | syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); | ||
214 | if (errno == EINVAL) { | ||
215 | close(fd); | ||
216 | exit(EXIT_FAILURE); | ||
217 | } | ||
218 | else | ||
219 | continue; | ||
220 | } | ||
221 | |||
222 | len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0, | ||
205 | addr_p, &addr_l); | 223 | addr_p, &addr_l); |
206 | 224 | ||
207 | if (len < 0) { | 225 | if (len < 0) { |
@@ -241,7 +259,8 @@ int main(void) | |||
241 | vss_msg->error = error; | 259 | vss_msg->error = error; |
242 | len = netlink_send(fd, incoming_cn_msg); | 260 | len = netlink_send(fd, incoming_cn_msg); |
243 | if (len < 0) { | 261 | if (len < 0) { |
244 | syslog(LOG_ERR, "net_link send failed; error:%d", len); | 262 | syslog(LOG_ERR, "net_link send failed; error:%d %s", |
263 | errno, strerror(errno)); | ||
245 | exit(EXIT_FAILURE); | 264 | exit(EXIT_FAILURE); |
246 | } | 265 | } |
247 | } | 266 | } |