diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 13:23:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 13:23:36 -0500 |
commit | 4c257ec37bc365614933c7f0a7fe9b0688dfd1e7 (patch) | |
tree | 37df4c3e0e963df9b87729c19f7c337e2f53008e | |
parent | 39272dde8ffcfd1322209e05f3f8fa4d14f796de (diff) | |
parent | ed6dc538e5a36a331b6256d54f435c80f6715460 (diff) |
Merge tag 'char-misc-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc updates from Greg KH:
"Here's the big set of char/misc patches for 4.5-rc1.
Nothing major, lots of different driver subsystem updates, full
details in the shortlog. All of these have been in linux-next for a
while"
* tag 'char-misc-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (71 commits)
mei: fix fasync return value on error
parport: avoid assignment in if
parport: remove unneeded space
parport: change style of NULL comparison
parport: remove unnecessary out of memory message
parport: remove braces
parport: quoted strings should not be split
parport: code indent should use tabs
parport: fix coding style
parport: EXPORT_SYMBOL should follow function
parport: remove trailing white space
parport: fix a trivial typo
coresight: Fix a typo in Kconfig
coresight: checking for NULL string in coresight_name_match()
Drivers: hv: vmbus: Treat Fibre Channel devices as performance critical
Drivers: hv: utils: fix hvt_op_poll() return value on transport destroy
Drivers: hv: vmbus: fix the building warning with hyperv-keyboard
extcon: add Maxim MAX3355 driver
Drivers: hv: ring_buffer: eliminate hv_ringbuffer_peek()
Drivers: hv: remove code duplication between vmbus_recvpacket()/vmbus_recvpacket_raw()
...
34 files changed, 1104 insertions, 676 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt index e1705fae63a8..e27341f8a4c7 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-arizona.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-arizona.txt | |||
@@ -13,3 +13,63 @@ Optional properties: | |||
13 | ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR | 13 | ARIZONA_ACCDET_MODE_HPR or 2 - Headphone detect mode is set to HPDETR |
14 | If this node is not mentioned or if the value is unknown, then | 14 | If this node is not mentioned or if the value is unknown, then |
15 | headphone detection mode is set to HPDETL. | 15 | headphone detection mode is set to HPDETL. |
16 | |||
17 | - wlf,use-jd2 : Use the additional JD input along with JD1 for dual pin jack | ||
18 | detection. | ||
19 | - wlf,use-jd2-nopull : Internal pull on JD2 is disabled when used for | ||
20 | jack detection. | ||
21 | - wlf,jd-invert : Invert the polarity of the jack detection switch | ||
22 | |||
23 | - wlf,micd-software-compare : Use a software comparison to determine mic | ||
24 | presence | ||
25 | - wlf,micd-detect-debounce : Additional software microphone detection | ||
26 | debounce specified in milliseconds. | ||
27 | - wlf,micd-pol-gpio : GPIO specifier for the GPIO controlling the headset | ||
28 | polarity if one exists. | ||
29 | - wlf,micd-bias-start-time : Time allowed for MICBIAS to startup prior to | ||
30 | performing microphone detection, specified as per the ARIZONA_MICD_TIME_XXX | ||
31 | defines. | ||
32 | - wlf,micd-rate : Delay between successive microphone detection measurements, | ||
33 | specified as per the ARIZONA_MICD_TIME_XXX defines. | ||
34 | - wlf,micd-dbtime : Microphone detection hardware debounces specified as the | ||
35 | number of measurements to take, valid values being 2 and 4. | ||
36 | - wlf,micd-timeout-ms : Timeout for microphone detection, specified in | ||
37 | milliseconds. | ||
38 | - wlf,micd-force-micbias : Force MICBIAS continuously on during microphone | ||
39 | detection. | ||
40 | - wlf,micd-configs : Headset polarity configurations (generally used for | ||
41 | detection of CTIA / OMTP headsets), the field can be of variable length | ||
42 | but should always be a multiple of 3 cells long, each three cell group | ||
43 | represents one polarity configuration. | ||
44 | The first cell defines the accessory detection pin, zero will use MICDET1 | ||
45 | and all other values will use MICDET2. | ||
46 | The second cell represents the MICBIAS to be used. | ||
47 | The third cell represents the value of the micd-pol-gpio pin. | ||
48 | |||
49 | - wlf,gpsw : Settings for the general purpose switch | ||
50 | |||
51 | Example: | ||
52 | |||
53 | codec: wm8280@0 { | ||
54 | compatible = "wlf,wm8280"; | ||
55 | reg = <0>; | ||
56 | ... | ||
57 | |||
58 | wlf,use-jd2; | ||
59 | wlf,use-jd2-nopull; | ||
60 | wlf,jd-invert; | ||
61 | |||
62 | wlf,micd-software-compare; | ||
63 | wlf,micd-detect-debounce = <0>; | ||
64 | wlf,micd-pol-gpio = <&codec 2 0>; | ||
65 | wlf,micd-rate = <ARIZONA_MICD_TIME_8MS>; | ||
66 | wlf,micd-dbtime = <4>; | ||
67 | wlf,micd-timeout-ms = <100>; | ||
68 | wlf,micd-force-micbias; | ||
69 | wlf,micd-configs = < | ||
70 | 0 1 0 /* MICDET1 MICBIAS1 GPIO=low */ | ||
71 | 1 2 1 /* MICDET2 MICBIAS2 GPIO=high */ | ||
72 | >; | ||
73 | |||
74 | wlf,gpsw = <0>; | ||
75 | }; | ||
diff --git a/Documentation/devicetree/bindings/extcon/extcon-max3355.txt b/Documentation/devicetree/bindings/extcon/extcon-max3355.txt new file mode 100644 index 000000000000..f2288ea9eb82 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-max3355.txt | |||
@@ -0,0 +1,21 @@ | |||
1 | Maxim Integrated MAX3355 USB OTG chip | ||
2 | ------------------------------------- | ||
3 | |||
4 | MAX3355 integrates a charge pump and comparators to enable a system with an | ||
5 | integrated USB OTG dual-role transceiver to function as a USB OTG dual-role | ||
6 | device. | ||
7 | |||
8 | Required properties: | ||
9 | - compatible: should be "maxim,max3355"; | ||
10 | - maxim,shdn-gpios: should contain a phandle and GPIO specifier for the GPIO pin | ||
11 | connected to the MAX3355's SHDN# pin; | ||
12 | - id-gpios: should contain a phandle and GPIO specifier for the GPIO pin | ||
13 | connected to the MAX3355's ID_OUT pin. | ||
14 | |||
15 | Example: | ||
16 | |||
17 | usb-otg { | ||
18 | compatible = "maxim,max3355"; | ||
19 | maxim,shdn-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; | ||
20 | id-gpios = <&gpio5 31 GPIO_ACTIVE_HIGH>; | ||
21 | }; | ||
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 0cebbf668886..3d89e60a3e71 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -52,6 +52,15 @@ config EXTCON_MAX14577 | |||
52 | Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory | 52 | Maxim MAX14577/77836. The MAX14577/77836 MUIC is a USB port accessory |
53 | detector and switch. | 53 | detector and switch. |
54 | 54 | ||
55 | config EXTCON_MAX3355 | ||
56 | tristate "Maxim MAX3355 USB OTG EXTCON Support" | ||
57 | depends on GPIOLIB || COMPILE_TEST | ||
58 | help | ||
59 | If you say yes here you get support for the USB OTG role detection by | ||
60 | MAX3355. The MAX3355 chip integrates a charge pump and comparators to | ||
61 | enable a system with an integrated USB OTG dual-role transceiver to | ||
62 | function as an USB OTG dual-role device. | ||
63 | |||
55 | config EXTCON_MAX77693 | 64 | config EXTCON_MAX77693 |
56 | tristate "Maxim MAX77693 EXTCON Support" | 65 | tristate "Maxim MAX77693 EXTCON Support" |
57 | depends on MFD_MAX77693 && INPUT | 66 | depends on MFD_MAX77693 && INPUT |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index ba787d04295b..2a0e4f45d5b2 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | |||
8 | obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o | 8 | obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o |
9 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o | 9 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o |
10 | obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o | 10 | obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o |
11 | obj-$(CONFIG_EXTCON_MAX3355) += extcon-max3355.o | ||
11 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o | 12 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o |
12 | obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o | 13 | obj-$(CONFIG_EXTCON_MAX77843) += extcon-max77843.o |
13 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | 14 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o |
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index e4890dd4fefd..c121d01a5cd6 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
@@ -1201,10 +1201,58 @@ static void arizona_micd_set_level(struct arizona *arizona, int index, | |||
1201 | regmap_update_bits(arizona->regmap, reg, mask, level); | 1201 | regmap_update_bits(arizona->regmap, reg, mask, level); |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | static int arizona_extcon_device_get_pdata(struct arizona *arizona) | 1204 | static int arizona_extcon_get_micd_configs(struct device *dev, |
1205 | struct arizona *arizona) | ||
1206 | { | ||
1207 | const char * const prop = "wlf,micd-configs"; | ||
1208 | const int entries_per_config = 3; | ||
1209 | struct arizona_micd_config *micd_configs; | ||
1210 | int nconfs, ret; | ||
1211 | int i, j; | ||
1212 | u32 *vals; | ||
1213 | |||
1214 | nconfs = device_property_read_u32_array(arizona->dev, prop, NULL, 0); | ||
1215 | if (nconfs <= 0) | ||
1216 | return 0; | ||
1217 | |||
1218 | vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL); | ||
1219 | if (!vals) | ||
1220 | return -ENOMEM; | ||
1221 | |||
1222 | ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs); | ||
1223 | if (ret < 0) | ||
1224 | goto out; | ||
1225 | |||
1226 | nconfs /= entries_per_config; | ||
1227 | |||
1228 | micd_configs = devm_kzalloc(dev, | ||
1229 | nconfs * sizeof(struct arizona_micd_range), | ||
1230 | GFP_KERNEL); | ||
1231 | if (!micd_configs) { | ||
1232 | ret = -ENOMEM; | ||
1233 | goto out; | ||
1234 | } | ||
1235 | |||
1236 | for (i = 0, j = 0; i < nconfs; ++i) { | ||
1237 | micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0; | ||
1238 | micd_configs[i].bias = vals[j++]; | ||
1239 | micd_configs[i].gpio = vals[j++]; | ||
1240 | } | ||
1241 | |||
1242 | arizona->pdata.micd_configs = micd_configs; | ||
1243 | arizona->pdata.num_micd_configs = nconfs; | ||
1244 | |||
1245 | out: | ||
1246 | kfree(vals); | ||
1247 | return ret; | ||
1248 | } | ||
1249 | |||
1250 | static int arizona_extcon_device_get_pdata(struct device *dev, | ||
1251 | struct arizona *arizona) | ||
1205 | { | 1252 | { |
1206 | struct arizona_pdata *pdata = &arizona->pdata; | 1253 | struct arizona_pdata *pdata = &arizona->pdata; |
1207 | unsigned int val = ARIZONA_ACCDET_MODE_HPL; | 1254 | unsigned int val = ARIZONA_ACCDET_MODE_HPL; |
1255 | int ret; | ||
1208 | 1256 | ||
1209 | device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); | 1257 | device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val); |
1210 | switch (val) { | 1258 | switch (val) { |
@@ -1230,12 +1278,29 @@ static int arizona_extcon_device_get_pdata(struct arizona *arizona) | |||
1230 | device_property_read_u32(arizona->dev, "wlf,micd-dbtime", | 1278 | device_property_read_u32(arizona->dev, "wlf,micd-dbtime", |
1231 | &pdata->micd_dbtime); | 1279 | &pdata->micd_dbtime); |
1232 | 1280 | ||
1233 | device_property_read_u32(arizona->dev, "wlf,micd-timeout", | 1281 | device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms", |
1234 | &pdata->micd_timeout); | 1282 | &pdata->micd_timeout); |
1235 | 1283 | ||
1236 | pdata->micd_force_micbias = device_property_read_bool(arizona->dev, | 1284 | pdata->micd_force_micbias = device_property_read_bool(arizona->dev, |
1237 | "wlf,micd-force-micbias"); | 1285 | "wlf,micd-force-micbias"); |
1238 | 1286 | ||
1287 | pdata->micd_software_compare = device_property_read_bool(arizona->dev, | ||
1288 | "wlf,micd-software-compare"); | ||
1289 | |||
1290 | pdata->jd_invert = device_property_read_bool(arizona->dev, | ||
1291 | "wlf,jd-invert"); | ||
1292 | |||
1293 | device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw); | ||
1294 | |||
1295 | pdata->jd_gpio5 = device_property_read_bool(arizona->dev, | ||
1296 | "wlf,use-jd2"); | ||
1297 | pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev, | ||
1298 | "wlf,use-jd2-nopull"); | ||
1299 | |||
1300 | ret = arizona_extcon_get_micd_configs(dev, arizona); | ||
1301 | if (ret < 0) | ||
1302 | dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret); | ||
1303 | |||
1239 | return 0; | 1304 | return 0; |
1240 | } | 1305 | } |
1241 | 1306 | ||
@@ -1257,7 +1322,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) | |||
1257 | return -ENOMEM; | 1322 | return -ENOMEM; |
1258 | 1323 | ||
1259 | if (!dev_get_platdata(arizona->dev)) | 1324 | if (!dev_get_platdata(arizona->dev)) |
1260 | arizona_extcon_device_get_pdata(arizona); | 1325 | arizona_extcon_device_get_pdata(&pdev->dev, arizona); |
1261 | 1326 | ||
1262 | info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); | 1327 | info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); |
1263 | if (IS_ERR(info->micvdd)) { | 1328 | if (IS_ERR(info->micvdd)) { |
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index 601dbd996487..b30ab97ce75f 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c | |||
@@ -692,7 +692,7 @@ static int max14577_muic_probe(struct platform_device *pdev) | |||
692 | /* Support irq domain for max14577 MUIC device */ | 692 | /* Support irq domain for max14577 MUIC device */ |
693 | for (i = 0; i < info->muic_irqs_num; i++) { | 693 | for (i = 0; i < info->muic_irqs_num; i++) { |
694 | struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; | 694 | struct max14577_muic_irq *muic_irq = &info->muic_irqs[i]; |
695 | unsigned int virq = 0; | 695 | int virq = 0; |
696 | 696 | ||
697 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); | 697 | virq = regmap_irq_get_virq(max14577->irq_data, muic_irq->irq); |
698 | if (virq <= 0) | 698 | if (virq <= 0) |
diff --git a/drivers/extcon/extcon-max3355.c b/drivers/extcon/extcon-max3355.c new file mode 100644 index 000000000000..c24abec5d06c --- /dev/null +++ b/drivers/extcon/extcon-max3355.c | |||
@@ -0,0 +1,146 @@ | |||
1 | /* | ||
2 | * Maxim Integrated MAX3355 USB OTG chip extcon driver | ||
3 | * | ||
4 | * Copyright (C) 2014-2015 Cogent Embedded, Inc. | ||
5 | * Author: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | */ | ||
11 | |||
12 | #include <linux/extcon.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/gpio/consumer.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | struct max3355_data { | ||
20 | struct extcon_dev *edev; | ||
21 | struct gpio_desc *id_gpiod; | ||
22 | struct gpio_desc *shdn_gpiod; | ||
23 | }; | ||
24 | |||
25 | static const unsigned int max3355_cable[] = { | ||
26 | EXTCON_USB, | ||
27 | EXTCON_USB_HOST, | ||
28 | EXTCON_NONE, | ||
29 | }; | ||
30 | |||
31 | static irqreturn_t max3355_id_irq(int irq, void *dev_id) | ||
32 | { | ||
33 | struct max3355_data *data = dev_id; | ||
34 | int id = gpiod_get_value_cansleep(data->id_gpiod); | ||
35 | |||
36 | if (id) { | ||
37 | /* | ||
38 | * ID = 1 means USB HOST cable detached. | ||
39 | * As we don't have event for USB peripheral cable attached, | ||
40 | * we simulate USB peripheral attach here. | ||
41 | */ | ||
42 | extcon_set_cable_state_(data->edev, EXTCON_USB_HOST, false); | ||
43 | extcon_set_cable_state_(data->edev, EXTCON_USB, true); | ||
44 | } else { | ||
45 | /* | ||
46 | * ID = 0 means USB HOST cable attached. | ||
47 | * As we don't have event for USB peripheral cable detached, | ||
48 | * we simulate USB peripheral detach here. | ||
49 | */ | ||
50 | extcon_set_cable_state_(data->edev, EXTCON_USB, false); | ||
51 | extcon_set_cable_state_(data->edev, EXTCON_USB_HOST, true); | ||
52 | } | ||
53 | |||
54 | return IRQ_HANDLED; | ||
55 | } | ||
56 | |||
57 | static int max3355_probe(struct platform_device *pdev) | ||
58 | { | ||
59 | struct max3355_data *data; | ||
60 | struct gpio_desc *gpiod; | ||
61 | int irq, err; | ||
62 | |||
63 | data = devm_kzalloc(&pdev->dev, sizeof(struct max3355_data), | ||
64 | GFP_KERNEL); | ||
65 | if (!data) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN); | ||
69 | if (IS_ERR(gpiod)) { | ||
70 | dev_err(&pdev->dev, "failed to get ID_OUT GPIO\n"); | ||
71 | return PTR_ERR(gpiod); | ||
72 | } | ||
73 | data->id_gpiod = gpiod; | ||
74 | |||
75 | gpiod = devm_gpiod_get(&pdev->dev, "maxim,shdn", GPIOD_OUT_HIGH); | ||
76 | if (IS_ERR(gpiod)) { | ||
77 | dev_err(&pdev->dev, "failed to get SHDN# GPIO\n"); | ||
78 | return PTR_ERR(gpiod); | ||
79 | } | ||
80 | data->shdn_gpiod = gpiod; | ||
81 | |||
82 | data->edev = devm_extcon_dev_allocate(&pdev->dev, max3355_cable); | ||
83 | if (IS_ERR(data->edev)) { | ||
84 | dev_err(&pdev->dev, "failed to allocate extcon device\n"); | ||
85 | return PTR_ERR(data->edev); | ||
86 | } | ||
87 | |||
88 | err = devm_extcon_dev_register(&pdev->dev, data->edev); | ||
89 | if (err < 0) { | ||
90 | dev_err(&pdev->dev, "failed to register extcon device\n"); | ||
91 | return err; | ||
92 | } | ||
93 | |||
94 | irq = gpiod_to_irq(data->id_gpiod); | ||
95 | if (irq < 0) { | ||
96 | dev_err(&pdev->dev, "failed to translate ID_OUT GPIO to IRQ\n"); | ||
97 | return irq; | ||
98 | } | ||
99 | |||
100 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, max3355_id_irq, | ||
101 | IRQF_ONESHOT | IRQF_NO_SUSPEND | | ||
102 | IRQF_TRIGGER_RISING | | ||
103 | IRQF_TRIGGER_FALLING, | ||
104 | pdev->name, data); | ||
105 | if (err < 0) { | ||
106 | dev_err(&pdev->dev, "failed to request ID_OUT IRQ\n"); | ||
107 | return err; | ||
108 | } | ||
109 | |||
110 | platform_set_drvdata(pdev, data); | ||
111 | |||
112 | /* Perform initial detection */ | ||
113 | max3355_id_irq(irq, data); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int max3355_remove(struct platform_device *pdev) | ||
119 | { | ||
120 | struct max3355_data *data = platform_get_drvdata(pdev); | ||
121 | |||
122 | gpiod_set_value_cansleep(data->shdn_gpiod, 0); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct of_device_id max3355_match_table[] = { | ||
128 | { .compatible = "maxim,max3355", }, | ||
129 | { } | ||
130 | }; | ||
131 | MODULE_DEVICE_TABLE(of, max3355_match_table); | ||
132 | |||
133 | static struct platform_driver max3355_driver = { | ||
134 | .probe = max3355_probe, | ||
135 | .remove = max3355_remove, | ||
136 | .driver = { | ||
137 | .name = "extcon-max3355", | ||
138 | .of_match_table = max3355_match_table, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | module_platform_driver(max3355_driver); | ||
143 | |||
144 | MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>"); | ||
145 | MODULE_DESCRIPTION("Maxim MAX3355 extcon driver"); | ||
146 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 44c499e1beee..fdf8f5d4d4e9 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
@@ -1127,11 +1127,11 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1127 | /* Support irq domain for MAX77693 MUIC device */ | 1127 | /* Support irq domain for MAX77693 MUIC device */ |
1128 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { | 1128 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { |
1129 | struct max77693_muic_irq *muic_irq = &muic_irqs[i]; | 1129 | struct max77693_muic_irq *muic_irq = &muic_irqs[i]; |
1130 | unsigned int virq = 0; | 1130 | int virq; |
1131 | 1131 | ||
1132 | virq = regmap_irq_get_virq(max77693->irq_data_muic, | 1132 | virq = regmap_irq_get_virq(max77693->irq_data_muic, |
1133 | muic_irq->irq); | 1133 | muic_irq->irq); |
1134 | if (!virq) | 1134 | if (virq <= 0) |
1135 | return -EINVAL; | 1135 | return -EINVAL; |
1136 | muic_irq->virq = virq; | 1136 | muic_irq->virq = virq; |
1137 | 1137 | ||
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index 9f9ea334399c..74dfb7f4f277 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c | |||
@@ -811,7 +811,7 @@ static int max77843_muic_probe(struct platform_device *pdev) | |||
811 | 811 | ||
812 | for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) { | 812 | for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) { |
813 | struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i]; | 813 | struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i]; |
814 | unsigned int virq = 0; | 814 | int virq = 0; |
815 | 815 | ||
816 | virq = regmap_irq_get_virq(max77843->irq_data_muic, | 816 | virq = regmap_irq_get_virq(max77843->irq_data_muic, |
817 | muic_irq->irq); | 817 | muic_irq->irq); |
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index 36bf1d63791c..e1bb82809bef 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c | |||
@@ -603,7 +603,7 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c, | |||
603 | 603 | ||
604 | ret = devm_request_threaded_irq(info->dev, virq, NULL, | 604 | ret = devm_request_threaded_irq(info->dev, virq, NULL, |
605 | rt8973a_muic_irq_handler, | 605 | rt8973a_muic_irq_handler, |
606 | IRQF_NO_SUSPEND, | 606 | IRQF_NO_SUSPEND | IRQF_ONESHOT, |
607 | muic_irq->name, info); | 607 | muic_irq->name, info); |
608 | if (ret) { | 608 | if (ret) { |
609 | dev_err(info->dev, | 609 | dev_err(info->dev, |
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index c4dcab048cb8..1161d68a1863 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | #include <linux/uio.h> | 30 | #include <linux/uio.h> |
31 | #include <linux/interrupt.h> | ||
31 | 32 | ||
32 | #include "hyperv_vmbus.h" | 33 | #include "hyperv_vmbus.h" |
33 | 34 | ||
@@ -496,8 +497,33 @@ static void reset_channel_cb(void *arg) | |||
496 | static int vmbus_close_internal(struct vmbus_channel *channel) | 497 | static int vmbus_close_internal(struct vmbus_channel *channel) |
497 | { | 498 | { |
498 | struct vmbus_channel_close_channel *msg; | 499 | struct vmbus_channel_close_channel *msg; |
500 | struct tasklet_struct *tasklet; | ||
499 | int ret; | 501 | int ret; |
500 | 502 | ||
503 | /* | ||
504 | * process_chn_event(), running in the tasklet, can race | ||
505 | * with vmbus_close_internal() in the case of SMP guest, e.g., when | ||
506 | * the former is accessing channel->inbound.ring_buffer, the latter | ||
507 | * could be freeing the ring_buffer pages. | ||
508 | * | ||
509 | * To resolve the race, we can serialize them by disabling the | ||
510 | * tasklet when the latter is running here. | ||
511 | */ | ||
512 | tasklet = hv_context.event_dpc[channel->target_cpu]; | ||
513 | tasklet_disable(tasklet); | ||
514 | |||
515 | /* | ||
516 | * In case a device driver's probe() fails (e.g., | ||
517 | * util_probe() -> vmbus_open() returns -ENOMEM) and the device is | ||
518 | * rescinded later (e.g., we dynamically disble an Integrated Service | ||
519 | * in Hyper-V Manager), the driver's remove() invokes vmbus_close(): | ||
520 | * here we should skip most of the below cleanup work. | ||
521 | */ | ||
522 | if (channel->state != CHANNEL_OPENED_STATE) { | ||
523 | ret = -EINVAL; | ||
524 | goto out; | ||
525 | } | ||
526 | |||
501 | channel->state = CHANNEL_OPEN_STATE; | 527 | channel->state = CHANNEL_OPEN_STATE; |
502 | channel->sc_creation_callback = NULL; | 528 | channel->sc_creation_callback = NULL; |
503 | /* Stop callback and cancel the timer asap */ | 529 | /* Stop callback and cancel the timer asap */ |
@@ -525,7 +551,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
525 | * If we failed to post the close msg, | 551 | * If we failed to post the close msg, |
526 | * it is perhaps better to leak memory. | 552 | * it is perhaps better to leak memory. |
527 | */ | 553 | */ |
528 | return ret; | 554 | goto out; |
529 | } | 555 | } |
530 | 556 | ||
531 | /* Tear down the gpadl for the channel's ring buffer */ | 557 | /* Tear down the gpadl for the channel's ring buffer */ |
@@ -538,7 +564,7 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
538 | * If we failed to teardown gpadl, | 564 | * If we failed to teardown gpadl, |
539 | * it is perhaps better to leak memory. | 565 | * it is perhaps better to leak memory. |
540 | */ | 566 | */ |
541 | return ret; | 567 | goto out; |
542 | } | 568 | } |
543 | } | 569 | } |
544 | 570 | ||
@@ -549,12 +575,9 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
549 | free_pages((unsigned long)channel->ringbuffer_pages, | 575 | free_pages((unsigned long)channel->ringbuffer_pages, |
550 | get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); | 576 | get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); |
551 | 577 | ||
552 | /* | 578 | out: |
553 | * If the channel has been rescinded; process device removal. | 579 | tasklet_enable(tasklet); |
554 | */ | 580 | |
555 | if (channel->rescind) | ||
556 | hv_process_channel_removal(channel, | ||
557 | channel->offermsg.child_relid); | ||
558 | return ret; | 581 | return ret; |
559 | } | 582 | } |
560 | 583 | ||
@@ -630,10 +653,19 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer, | |||
630 | * on the ring. We will not signal if more data is | 653 | * on the ring. We will not signal if more data is |
631 | * to be placed. | 654 | * to be placed. |
632 | * | 655 | * |
656 | * Based on the channel signal state, we will decide | ||
657 | * which signaling policy will be applied. | ||
658 | * | ||
633 | * If we cannot write to the ring-buffer; signal the host | 659 | * If we cannot write to the ring-buffer; signal the host |
634 | * even if we may not have written anything. This is a rare | 660 | * even if we may not have written anything. This is a rare |
635 | * enough condition that it should not matter. | 661 | * enough condition that it should not matter. |
636 | */ | 662 | */ |
663 | |||
664 | if (channel->signal_policy) | ||
665 | signal = true; | ||
666 | else | ||
667 | kick_q = true; | ||
668 | |||
637 | if (((ret == 0) && kick_q && signal) || (ret)) | 669 | if (((ret == 0) && kick_q && signal) || (ret)) |
638 | vmbus_setevent(channel); | 670 | vmbus_setevent(channel); |
639 | 671 | ||
@@ -733,10 +765,19 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, | |||
733 | * on the ring. We will not signal if more data is | 765 | * on the ring. We will not signal if more data is |
734 | * to be placed. | 766 | * to be placed. |
735 | * | 767 | * |
768 | * Based on the channel signal state, we will decide | ||
769 | * which signaling policy will be applied. | ||
770 | * | ||
736 | * If we cannot write to the ring-buffer; signal the host | 771 | * If we cannot write to the ring-buffer; signal the host |
737 | * even if we may not have written anything. This is a rare | 772 | * even if we may not have written anything. This is a rare |
738 | * enough condition that it should not matter. | 773 | * enough condition that it should not matter. |
739 | */ | 774 | */ |
775 | |||
776 | if (channel->signal_policy) | ||
777 | signal = true; | ||
778 | else | ||
779 | kick_q = true; | ||
780 | |||
740 | if (((ret == 0) && kick_q && signal) || (ret)) | 781 | if (((ret == 0) && kick_q && signal) || (ret)) |
741 | vmbus_setevent(channel); | 782 | vmbus_setevent(channel); |
742 | 783 | ||
@@ -881,46 +922,29 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer); | |||
881 | * | 922 | * |
882 | * Mainly used by Hyper-V drivers. | 923 | * Mainly used by Hyper-V drivers. |
883 | */ | 924 | */ |
884 | int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, | 925 | static inline int |
885 | u32 bufferlen, u32 *buffer_actual_len, u64 *requestid) | 926 | __vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, |
927 | u32 bufferlen, u32 *buffer_actual_len, u64 *requestid, | ||
928 | bool raw) | ||
886 | { | 929 | { |
887 | struct vmpacket_descriptor desc; | ||
888 | u32 packetlen; | ||
889 | u32 userlen; | ||
890 | int ret; | 930 | int ret; |
891 | bool signal = false; | 931 | bool signal = false; |
892 | 932 | ||
893 | *buffer_actual_len = 0; | 933 | ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen, |
894 | *requestid = 0; | 934 | buffer_actual_len, requestid, &signal, raw); |
895 | |||
896 | |||
897 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, | ||
898 | sizeof(struct vmpacket_descriptor)); | ||
899 | if (ret != 0) | ||
900 | return 0; | ||
901 | |||
902 | packetlen = desc.len8 << 3; | ||
903 | userlen = packetlen - (desc.offset8 << 3); | ||
904 | |||
905 | *buffer_actual_len = userlen; | ||
906 | |||
907 | if (userlen > bufferlen) { | ||
908 | |||
909 | pr_err("Buffer too small - got %d needs %d\n", | ||
910 | bufferlen, userlen); | ||
911 | return -ETOOSMALL; | ||
912 | } | ||
913 | |||
914 | *requestid = desc.trans_id; | ||
915 | |||
916 | /* Copy over the packet to the user buffer */ | ||
917 | ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen, | ||
918 | (desc.offset8 << 3), &signal); | ||
919 | 935 | ||
920 | if (signal) | 936 | if (signal) |
921 | vmbus_setevent(channel); | 937 | vmbus_setevent(channel); |
922 | 938 | ||
923 | return 0; | 939 | return ret; |
940 | } | ||
941 | |||
942 | int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, | ||
943 | u32 bufferlen, u32 *buffer_actual_len, | ||
944 | u64 *requestid) | ||
945 | { | ||
946 | return __vmbus_recvpacket(channel, buffer, bufferlen, | ||
947 | buffer_actual_len, requestid, false); | ||
924 | } | 948 | } |
925 | EXPORT_SYMBOL(vmbus_recvpacket); | 949 | EXPORT_SYMBOL(vmbus_recvpacket); |
926 | 950 | ||
@@ -931,37 +955,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, | |||
931 | u32 bufferlen, u32 *buffer_actual_len, | 955 | u32 bufferlen, u32 *buffer_actual_len, |
932 | u64 *requestid) | 956 | u64 *requestid) |
933 | { | 957 | { |
934 | struct vmpacket_descriptor desc; | 958 | return __vmbus_recvpacket(channel, buffer, bufferlen, |
935 | u32 packetlen; | 959 | buffer_actual_len, requestid, true); |
936 | int ret; | ||
937 | bool signal = false; | ||
938 | |||
939 | *buffer_actual_len = 0; | ||
940 | *requestid = 0; | ||
941 | |||
942 | |||
943 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, | ||
944 | sizeof(struct vmpacket_descriptor)); | ||
945 | if (ret != 0) | ||
946 | return 0; | ||
947 | |||
948 | |||
949 | packetlen = desc.len8 << 3; | ||
950 | |||
951 | *buffer_actual_len = packetlen; | ||
952 | |||
953 | if (packetlen > bufferlen) | ||
954 | return -ENOBUFS; | ||
955 | |||
956 | *requestid = desc.trans_id; | ||
957 | |||
958 | /* Copy over the entire packet to the user buffer */ | ||
959 | ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0, | ||
960 | &signal); | ||
961 | |||
962 | if (signal) | ||
963 | vmbus_setevent(channel); | ||
964 | |||
965 | return ret; | ||
966 | } | 960 | } |
967 | EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); | 961 | EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 652afd11a9ef..1c1ad47042c5 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -177,19 +177,24 @@ static void percpu_channel_deq(void *arg) | |||
177 | } | 177 | } |
178 | 178 | ||
179 | 179 | ||
180 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | 180 | static void vmbus_release_relid(u32 relid) |
181 | { | 181 | { |
182 | struct vmbus_channel_relid_released msg; | 182 | struct vmbus_channel_relid_released msg; |
183 | unsigned long flags; | ||
184 | struct vmbus_channel *primary_channel; | ||
185 | 183 | ||
186 | memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); | 184 | memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); |
187 | msg.child_relid = relid; | 185 | msg.child_relid = relid; |
188 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; | 186 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; |
189 | vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); | 187 | vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); |
188 | } | ||
190 | 189 | ||
191 | if (channel == NULL) | 190 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) |
192 | return; | 191 | { |
192 | unsigned long flags; | ||
193 | struct vmbus_channel *primary_channel; | ||
194 | |||
195 | vmbus_release_relid(relid); | ||
196 | |||
197 | BUG_ON(!channel->rescind); | ||
193 | 198 | ||
194 | if (channel->target_cpu != get_cpu()) { | 199 | if (channel->target_cpu != get_cpu()) { |
195 | put_cpu(); | 200 | put_cpu(); |
@@ -201,9 +206,9 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | |||
201 | } | 206 | } |
202 | 207 | ||
203 | if (channel->primary_channel == NULL) { | 208 | if (channel->primary_channel == NULL) { |
204 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 209 | mutex_lock(&vmbus_connection.channel_mutex); |
205 | list_del(&channel->listentry); | 210 | list_del(&channel->listentry); |
206 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 211 | mutex_unlock(&vmbus_connection.channel_mutex); |
207 | 212 | ||
208 | primary_channel = channel; | 213 | primary_channel = channel; |
209 | } else { | 214 | } else { |
@@ -230,9 +235,7 @@ void vmbus_free_channels(void) | |||
230 | 235 | ||
231 | list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list, | 236 | list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list, |
232 | listentry) { | 237 | listentry) { |
233 | /* if we don't set rescind to true, vmbus_close_internal() | 238 | /* hv_process_channel_removal() needs this */ |
234 | * won't invoke hv_process_channel_removal(). | ||
235 | */ | ||
236 | channel->rescind = true; | 239 | channel->rescind = true; |
237 | 240 | ||
238 | vmbus_device_unregister(channel->device_obj); | 241 | vmbus_device_unregister(channel->device_obj); |
@@ -250,7 +253,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
250 | unsigned long flags; | 253 | unsigned long flags; |
251 | 254 | ||
252 | /* Make sure this is a new offer */ | 255 | /* Make sure this is a new offer */ |
253 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 256 | mutex_lock(&vmbus_connection.channel_mutex); |
254 | 257 | ||
255 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { | 258 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { |
256 | if (!uuid_le_cmp(channel->offermsg.offer.if_type, | 259 | if (!uuid_le_cmp(channel->offermsg.offer.if_type, |
@@ -266,7 +269,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
266 | list_add_tail(&newchannel->listentry, | 269 | list_add_tail(&newchannel->listentry, |
267 | &vmbus_connection.chn_list); | 270 | &vmbus_connection.chn_list); |
268 | 271 | ||
269 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 272 | mutex_unlock(&vmbus_connection.channel_mutex); |
270 | 273 | ||
271 | if (!fnew) { | 274 | if (!fnew) { |
272 | /* | 275 | /* |
@@ -336,9 +339,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
336 | return; | 339 | return; |
337 | 340 | ||
338 | err_deq_chan: | 341 | err_deq_chan: |
339 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 342 | vmbus_release_relid(newchannel->offermsg.child_relid); |
343 | |||
344 | mutex_lock(&vmbus_connection.channel_mutex); | ||
340 | list_del(&newchannel->listentry); | 345 | list_del(&newchannel->listentry); |
341 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 346 | mutex_unlock(&vmbus_connection.channel_mutex); |
342 | 347 | ||
343 | if (newchannel->target_cpu != get_cpu()) { | 348 | if (newchannel->target_cpu != get_cpu()) { |
344 | put_cpu(); | 349 | put_cpu(); |
@@ -356,8 +361,10 @@ err_free_chan: | |||
356 | enum { | 361 | enum { |
357 | IDE = 0, | 362 | IDE = 0, |
358 | SCSI, | 363 | SCSI, |
364 | FC, | ||
359 | NIC, | 365 | NIC, |
360 | ND_NIC, | 366 | ND_NIC, |
367 | PCIE, | ||
361 | MAX_PERF_CHN, | 368 | MAX_PERF_CHN, |
362 | }; | 369 | }; |
363 | 370 | ||
@@ -371,10 +378,14 @@ static const struct hv_vmbus_device_id hp_devs[] = { | |||
371 | { HV_IDE_GUID, }, | 378 | { HV_IDE_GUID, }, |
372 | /* Storage - SCSI */ | 379 | /* Storage - SCSI */ |
373 | { HV_SCSI_GUID, }, | 380 | { HV_SCSI_GUID, }, |
381 | /* Storage - FC */ | ||
382 | { HV_SYNTHFC_GUID, }, | ||
374 | /* Network */ | 383 | /* Network */ |
375 | { HV_NIC_GUID, }, | 384 | { HV_NIC_GUID, }, |
376 | /* NetworkDirect Guest RDMA */ | 385 | /* NetworkDirect Guest RDMA */ |
377 | { HV_ND_GUID, }, | 386 | { HV_ND_GUID, }, |
387 | /* PCI Express Pass Through */ | ||
388 | { HV_PCIE_GUID, }, | ||
378 | }; | 389 | }; |
379 | 390 | ||
380 | 391 | ||
@@ -405,8 +416,7 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui | |||
405 | struct cpumask *alloced_mask; | 416 | struct cpumask *alloced_mask; |
406 | 417 | ||
407 | for (i = IDE; i < MAX_PERF_CHN; i++) { | 418 | for (i = IDE; i < MAX_PERF_CHN; i++) { |
408 | if (!memcmp(type_guid->b, hp_devs[i].guid, | 419 | if (!uuid_le_cmp(*type_guid, hp_devs[i].guid)) { |
409 | sizeof(uuid_le))) { | ||
410 | perf_chn = true; | 420 | perf_chn = true; |
411 | break; | 421 | break; |
412 | } | 422 | } |
@@ -585,7 +595,11 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) | |||
585 | channel = relid2channel(rescind->child_relid); | 595 | channel = relid2channel(rescind->child_relid); |
586 | 596 | ||
587 | if (channel == NULL) { | 597 | if (channel == NULL) { |
588 | hv_process_channel_removal(NULL, rescind->child_relid); | 598 | /* |
599 | * This is very impossible, because in | ||
600 | * vmbus_process_offer(), we have already invoked | ||
601 | * vmbus_release_relid() on error. | ||
602 | */ | ||
589 | return; | 603 | return; |
590 | } | 604 | } |
591 | 605 | ||
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 4fc2e8836e60..3dc5a9c7fad6 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c | |||
@@ -83,10 +83,13 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, | |||
83 | msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); | 83 | msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); |
84 | msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); | 84 | msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); |
85 | msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); | 85 | msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); |
86 | if (version >= VERSION_WIN8_1) { | 86 | /* |
87 | msg->target_vcpu = hv_context.vp_index[get_cpu()]; | 87 | * We want all channel messages to be delivered on CPU 0. |
88 | put_cpu(); | 88 | * This has been the behavior pre-win8. This is not |
89 | } | 89 | * perf issue and having all channel messages delivered on CPU 0 |
90 | * would be ok. | ||
91 | */ | ||
92 | msg->target_vcpu = 0; | ||
90 | 93 | ||
91 | /* | 94 | /* |
92 | * Add to list before we send the request since we may | 95 | * Add to list before we send the request since we may |
@@ -146,7 +149,7 @@ int vmbus_connect(void) | |||
146 | spin_lock_init(&vmbus_connection.channelmsg_lock); | 149 | spin_lock_init(&vmbus_connection.channelmsg_lock); |
147 | 150 | ||
148 | INIT_LIST_HEAD(&vmbus_connection.chn_list); | 151 | INIT_LIST_HEAD(&vmbus_connection.chn_list); |
149 | spin_lock_init(&vmbus_connection.channel_lock); | 152 | mutex_init(&vmbus_connection.channel_mutex); |
150 | 153 | ||
151 | /* | 154 | /* |
152 | * Setup the vmbus event connection for channel interrupt | 155 | * Setup the vmbus event connection for channel interrupt |
@@ -282,11 +285,10 @@ struct vmbus_channel *relid2channel(u32 relid) | |||
282 | { | 285 | { |
283 | struct vmbus_channel *channel; | 286 | struct vmbus_channel *channel; |
284 | struct vmbus_channel *found_channel = NULL; | 287 | struct vmbus_channel *found_channel = NULL; |
285 | unsigned long flags; | ||
286 | struct list_head *cur, *tmp; | 288 | struct list_head *cur, *tmp; |
287 | struct vmbus_channel *cur_sc; | 289 | struct vmbus_channel *cur_sc; |
288 | 290 | ||
289 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 291 | mutex_lock(&vmbus_connection.channel_mutex); |
290 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { | 292 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { |
291 | if (channel->offermsg.child_relid == relid) { | 293 | if (channel->offermsg.child_relid == relid) { |
292 | found_channel = channel; | 294 | found_channel = channel; |
@@ -305,7 +307,7 @@ struct vmbus_channel *relid2channel(u32 relid) | |||
305 | } | 307 | } |
306 | } | 308 | } |
307 | } | 309 | } |
308 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 310 | mutex_unlock(&vmbus_connection.channel_mutex); |
309 | 311 | ||
310 | return found_channel; | 312 | return found_channel; |
311 | } | 313 | } |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 6341be8739ae..11bca51ef5ff 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -89,9 +89,9 @@ static int query_hypervisor_info(void) | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * do_hypercall- Invoke the specified hypercall | 92 | * hv_do_hypercall- Invoke the specified hypercall |
93 | */ | 93 | */ |
94 | static u64 do_hypercall(u64 control, void *input, void *output) | 94 | u64 hv_do_hypercall(u64 control, void *input, void *output) |
95 | { | 95 | { |
96 | u64 input_address = (input) ? virt_to_phys(input) : 0; | 96 | u64 input_address = (input) ? virt_to_phys(input) : 0; |
97 | u64 output_address = (output) ? virt_to_phys(output) : 0; | 97 | u64 output_address = (output) ? virt_to_phys(output) : 0; |
@@ -132,6 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) | |||
132 | return hv_status_lo | ((u64)hv_status_hi << 32); | 132 | return hv_status_lo | ((u64)hv_status_hi << 32); |
133 | #endif /* !x86_64 */ | 133 | #endif /* !x86_64 */ |
134 | } | 134 | } |
135 | EXPORT_SYMBOL_GPL(hv_do_hypercall); | ||
135 | 136 | ||
136 | #ifdef CONFIG_X86_64 | 137 | #ifdef CONFIG_X86_64 |
137 | static cycle_t read_hv_clock_tsc(struct clocksource *arg) | 138 | static cycle_t read_hv_clock_tsc(struct clocksource *arg) |
@@ -139,7 +140,7 @@ static cycle_t read_hv_clock_tsc(struct clocksource *arg) | |||
139 | cycle_t current_tick; | 140 | cycle_t current_tick; |
140 | struct ms_hyperv_tsc_page *tsc_pg = hv_context.tsc_page; | 141 | struct ms_hyperv_tsc_page *tsc_pg = hv_context.tsc_page; |
141 | 142 | ||
142 | if (tsc_pg->tsc_sequence != -1) { | 143 | if (tsc_pg->tsc_sequence != 0) { |
143 | /* | 144 | /* |
144 | * Use the tsc page to compute the value. | 145 | * Use the tsc page to compute the value. |
145 | */ | 146 | */ |
@@ -161,7 +162,7 @@ static cycle_t read_hv_clock_tsc(struct clocksource *arg) | |||
161 | if (tsc_pg->tsc_sequence == sequence) | 162 | if (tsc_pg->tsc_sequence == sequence) |
162 | return current_tick; | 163 | return current_tick; |
163 | 164 | ||
164 | if (tsc_pg->tsc_sequence != -1) | 165 | if (tsc_pg->tsc_sequence != 0) |
165 | continue; | 166 | continue; |
166 | /* | 167 | /* |
167 | * Fallback using MSR method. | 168 | * Fallback using MSR method. |
@@ -192,9 +193,7 @@ int hv_init(void) | |||
192 | { | 193 | { |
193 | int max_leaf; | 194 | int max_leaf; |
194 | union hv_x64_msr_hypercall_contents hypercall_msr; | 195 | union hv_x64_msr_hypercall_contents hypercall_msr; |
195 | union hv_x64_msr_hypercall_contents tsc_msr; | ||
196 | void *virtaddr = NULL; | 196 | void *virtaddr = NULL; |
197 | void *va_tsc = NULL; | ||
198 | 197 | ||
199 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); | 198 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); |
200 | memset(hv_context.synic_message_page, 0, | 199 | memset(hv_context.synic_message_page, 0, |
@@ -240,6 +239,9 @@ int hv_init(void) | |||
240 | 239 | ||
241 | #ifdef CONFIG_X86_64 | 240 | #ifdef CONFIG_X86_64 |
242 | if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { | 241 | if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) { |
242 | union hv_x64_msr_hypercall_contents tsc_msr; | ||
243 | void *va_tsc; | ||
244 | |||
243 | va_tsc = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL); | 245 | va_tsc = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL); |
244 | if (!va_tsc) | 246 | if (!va_tsc) |
245 | goto cleanup; | 247 | goto cleanup; |
@@ -315,7 +317,7 @@ int hv_post_message(union hv_connection_id connection_id, | |||
315 | { | 317 | { |
316 | 318 | ||
317 | struct hv_input_post_message *aligned_msg; | 319 | struct hv_input_post_message *aligned_msg; |
318 | u16 status; | 320 | u64 status; |
319 | 321 | ||
320 | if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) | 322 | if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) |
321 | return -EMSGSIZE; | 323 | return -EMSGSIZE; |
@@ -329,11 +331,10 @@ int hv_post_message(union hv_connection_id connection_id, | |||
329 | aligned_msg->payload_size = payload_size; | 331 | aligned_msg->payload_size = payload_size; |
330 | memcpy((void *)aligned_msg->payload, payload, payload_size); | 332 | memcpy((void *)aligned_msg->payload, payload, payload_size); |
331 | 333 | ||
332 | status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL) | 334 | status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL); |
333 | & 0xFFFF; | ||
334 | 335 | ||
335 | put_cpu(); | 336 | put_cpu(); |
336 | return status; | 337 | return status & 0xFFFF; |
337 | } | 338 | } |
338 | 339 | ||
339 | 340 | ||
@@ -343,13 +344,13 @@ int hv_post_message(union hv_connection_id connection_id, | |||
343 | * | 344 | * |
344 | * This involves a hypercall. | 345 | * This involves a hypercall. |
345 | */ | 346 | */ |
346 | u16 hv_signal_event(void *con_id) | 347 | int hv_signal_event(void *con_id) |
347 | { | 348 | { |
348 | u16 status; | 349 | u64 status; |
349 | 350 | ||
350 | status = (do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL) & 0xFFFF); | 351 | status = hv_do_hypercall(HVCALL_SIGNAL_EVENT, con_id, NULL); |
351 | 352 | ||
352 | return status; | 353 | return status & 0xFFFF; |
353 | } | 354 | } |
354 | 355 | ||
355 | static int hv_ce_set_next_event(unsigned long delta, | 356 | static int hv_ce_set_next_event(unsigned long delta, |
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c index db4b887b889d..c37a71e13de0 100644 --- a/drivers/hv/hv_fcopy.c +++ b/drivers/hv/hv_fcopy.c | |||
@@ -51,7 +51,6 @@ static struct { | |||
51 | struct hv_fcopy_hdr *fcopy_msg; /* current message */ | 51 | struct hv_fcopy_hdr *fcopy_msg; /* current message */ |
52 | struct vmbus_channel *recv_channel; /* chn we got the request */ | 52 | struct vmbus_channel *recv_channel; /* chn we got the request */ |
53 | u64 recv_req_id; /* request ID. */ | 53 | u64 recv_req_id; /* request ID. */ |
54 | void *fcopy_context; /* for the channel callback */ | ||
55 | } fcopy_transaction; | 54 | } fcopy_transaction; |
56 | 55 | ||
57 | static void fcopy_respond_to_host(int error); | 56 | static void fcopy_respond_to_host(int error); |
@@ -67,6 +66,13 @@ static struct hvutil_transport *hvt; | |||
67 | */ | 66 | */ |
68 | static int dm_reg_value; | 67 | static int dm_reg_value; |
69 | 68 | ||
69 | static void fcopy_poll_wrapper(void *channel) | ||
70 | { | ||
71 | /* Transaction is finished, reset the state here to avoid races. */ | ||
72 | fcopy_transaction.state = HVUTIL_READY; | ||
73 | hv_fcopy_onchannelcallback(channel); | ||
74 | } | ||
75 | |||
70 | static void fcopy_timeout_func(struct work_struct *dummy) | 76 | static void fcopy_timeout_func(struct work_struct *dummy) |
71 | { | 77 | { |
72 | /* | 78 | /* |
@@ -74,13 +80,7 @@ static void fcopy_timeout_func(struct work_struct *dummy) | |||
74 | * process the pending transaction. | 80 | * process the pending transaction. |
75 | */ | 81 | */ |
76 | fcopy_respond_to_host(HV_E_FAIL); | 82 | fcopy_respond_to_host(HV_E_FAIL); |
77 | 83 | hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper); | |
78 | /* Transaction is finished, reset the state. */ | ||
79 | if (fcopy_transaction.state > HVUTIL_READY) | ||
80 | fcopy_transaction.state = HVUTIL_READY; | ||
81 | |||
82 | hv_poll_channel(fcopy_transaction.fcopy_context, | ||
83 | hv_fcopy_onchannelcallback); | ||
84 | } | 84 | } |
85 | 85 | ||
86 | static int fcopy_handle_handshake(u32 version) | 86 | static int fcopy_handle_handshake(u32 version) |
@@ -108,9 +108,7 @@ static int fcopy_handle_handshake(u32 version) | |||
108 | return -EINVAL; | 108 | return -EINVAL; |
109 | } | 109 | } |
110 | pr_debug("FCP: userspace daemon ver. %d registered\n", version); | 110 | pr_debug("FCP: userspace daemon ver. %d registered\n", version); |
111 | fcopy_transaction.state = HVUTIL_READY; | 111 | hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper); |
112 | hv_poll_channel(fcopy_transaction.fcopy_context, | ||
113 | hv_fcopy_onchannelcallback); | ||
114 | return 0; | 112 | return 0; |
115 | } | 113 | } |
116 | 114 | ||
@@ -227,15 +225,8 @@ void hv_fcopy_onchannelcallback(void *context) | |||
227 | int util_fw_version; | 225 | int util_fw_version; |
228 | int fcopy_srv_version; | 226 | int fcopy_srv_version; |
229 | 227 | ||
230 | if (fcopy_transaction.state > HVUTIL_READY) { | 228 | if (fcopy_transaction.state > HVUTIL_READY) |
231 | /* | ||
232 | * We will defer processing this callback once | ||
233 | * the current transaction is complete. | ||
234 | */ | ||
235 | fcopy_transaction.fcopy_context = context; | ||
236 | return; | 229 | return; |
237 | } | ||
238 | fcopy_transaction.fcopy_context = NULL; | ||
239 | 230 | ||
240 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, | 231 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, |
241 | &requestid); | 232 | &requestid); |
@@ -275,7 +266,8 @@ void hv_fcopy_onchannelcallback(void *context) | |||
275 | * Send the information to the user-level daemon. | 266 | * Send the information to the user-level daemon. |
276 | */ | 267 | */ |
277 | schedule_work(&fcopy_send_work); | 268 | schedule_work(&fcopy_send_work); |
278 | schedule_delayed_work(&fcopy_timeout_work, 5*HZ); | 269 | schedule_delayed_work(&fcopy_timeout_work, |
270 | HV_UTIL_TIMEOUT * HZ); | ||
279 | return; | 271 | return; |
280 | } | 272 | } |
281 | icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; | 273 | icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; |
@@ -304,9 +296,8 @@ static int fcopy_on_msg(void *msg, int len) | |||
304 | if (cancel_delayed_work_sync(&fcopy_timeout_work)) { | 296 | if (cancel_delayed_work_sync(&fcopy_timeout_work)) { |
305 | fcopy_transaction.state = HVUTIL_USERSPACE_RECV; | 297 | fcopy_transaction.state = HVUTIL_USERSPACE_RECV; |
306 | fcopy_respond_to_host(*val); | 298 | fcopy_respond_to_host(*val); |
307 | fcopy_transaction.state = HVUTIL_READY; | 299 | hv_poll_channel(fcopy_transaction.recv_channel, |
308 | hv_poll_channel(fcopy_transaction.fcopy_context, | 300 | fcopy_poll_wrapper); |
309 | hv_fcopy_onchannelcallback); | ||
310 | } | 301 | } |
311 | 302 | ||
312 | return 0; | 303 | return 0; |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 74c38a9f34a6..d4ab81bcd515 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -66,7 +66,6 @@ static struct { | |||
66 | struct hv_kvp_msg *kvp_msg; /* current message */ | 66 | struct hv_kvp_msg *kvp_msg; /* current message */ |
67 | struct vmbus_channel *recv_channel; /* chn we got the request */ | 67 | struct vmbus_channel *recv_channel; /* chn we got the request */ |
68 | u64 recv_req_id; /* request ID. */ | 68 | u64 recv_req_id; /* request ID. */ |
69 | void *kvp_context; /* for the channel callback */ | ||
70 | } kvp_transaction; | 69 | } kvp_transaction; |
71 | 70 | ||
72 | /* | 71 | /* |
@@ -94,6 +93,13 @@ static struct hvutil_transport *hvt; | |||
94 | */ | 93 | */ |
95 | #define HV_DRV_VERSION "3.1" | 94 | #define HV_DRV_VERSION "3.1" |
96 | 95 | ||
96 | static void kvp_poll_wrapper(void *channel) | ||
97 | { | ||
98 | /* Transaction is finished, reset the state here to avoid races. */ | ||
99 | kvp_transaction.state = HVUTIL_READY; | ||
100 | hv_kvp_onchannelcallback(channel); | ||
101 | } | ||
102 | |||
97 | static void | 103 | static void |
98 | kvp_register(int reg_value) | 104 | kvp_register(int reg_value) |
99 | { | 105 | { |
@@ -121,12 +127,7 @@ static void kvp_timeout_func(struct work_struct *dummy) | |||
121 | */ | 127 | */ |
122 | kvp_respond_to_host(NULL, HV_E_FAIL); | 128 | kvp_respond_to_host(NULL, HV_E_FAIL); |
123 | 129 | ||
124 | /* Transaction is finished, reset the state. */ | 130 | hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); |
125 | if (kvp_transaction.state > HVUTIL_READY) | ||
126 | kvp_transaction.state = HVUTIL_READY; | ||
127 | |||
128 | hv_poll_channel(kvp_transaction.kvp_context, | ||
129 | hv_kvp_onchannelcallback); | ||
130 | } | 131 | } |
131 | 132 | ||
132 | static int kvp_handle_handshake(struct hv_kvp_msg *msg) | 133 | static int kvp_handle_handshake(struct hv_kvp_msg *msg) |
@@ -153,7 +154,7 @@ static int kvp_handle_handshake(struct hv_kvp_msg *msg) | |||
153 | pr_debug("KVP: userspace daemon ver. %d registered\n", | 154 | pr_debug("KVP: userspace daemon ver. %d registered\n", |
154 | KVP_OP_REGISTER); | 155 | KVP_OP_REGISTER); |
155 | kvp_register(dm_reg_value); | 156 | kvp_register(dm_reg_value); |
156 | kvp_transaction.state = HVUTIL_READY; | 157 | hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); |
157 | 158 | ||
158 | return 0; | 159 | return 0; |
159 | } | 160 | } |
@@ -218,9 +219,7 @@ static int kvp_on_msg(void *msg, int len) | |||
218 | */ | 219 | */ |
219 | if (cancel_delayed_work_sync(&kvp_timeout_work)) { | 220 | if (cancel_delayed_work_sync(&kvp_timeout_work)) { |
220 | kvp_respond_to_host(message, error); | 221 | kvp_respond_to_host(message, error); |
221 | kvp_transaction.state = HVUTIL_READY; | 222 | hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); |
222 | hv_poll_channel(kvp_transaction.kvp_context, | ||
223 | hv_kvp_onchannelcallback); | ||
224 | } | 223 | } |
225 | 224 | ||
226 | return 0; | 225 | return 0; |
@@ -596,15 +595,8 @@ void hv_kvp_onchannelcallback(void *context) | |||
596 | int util_fw_version; | 595 | int util_fw_version; |
597 | int kvp_srv_version; | 596 | int kvp_srv_version; |
598 | 597 | ||
599 | if (kvp_transaction.state > HVUTIL_READY) { | 598 | if (kvp_transaction.state > HVUTIL_READY) |
600 | /* | ||
601 | * We will defer processing this callback once | ||
602 | * the current transaction is complete. | ||
603 | */ | ||
604 | kvp_transaction.kvp_context = context; | ||
605 | return; | 599 | return; |
606 | } | ||
607 | kvp_transaction.kvp_context = NULL; | ||
608 | 600 | ||
609 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen, | 601 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen, |
610 | &requestid); | 602 | &requestid); |
@@ -668,7 +660,8 @@ void hv_kvp_onchannelcallback(void *context) | |||
668 | * user-mode not responding. | 660 | * user-mode not responding. |
669 | */ | 661 | */ |
670 | schedule_work(&kvp_sendkey_work); | 662 | schedule_work(&kvp_sendkey_work); |
671 | schedule_delayed_work(&kvp_timeout_work, 5*HZ); | 663 | schedule_delayed_work(&kvp_timeout_work, |
664 | HV_UTIL_TIMEOUT * HZ); | ||
672 | 665 | ||
673 | return; | 666 | return; |
674 | 667 | ||
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 815405f2e777..67def4a831c8 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c | |||
@@ -53,7 +53,6 @@ static struct { | |||
53 | struct vmbus_channel *recv_channel; /* chn we got the request */ | 53 | struct vmbus_channel *recv_channel; /* chn we got the request */ |
54 | u64 recv_req_id; /* request ID. */ | 54 | u64 recv_req_id; /* request ID. */ |
55 | struct hv_vss_msg *msg; /* current message */ | 55 | struct hv_vss_msg *msg; /* current message */ |
56 | void *vss_context; /* for the channel callback */ | ||
57 | } vss_transaction; | 56 | } vss_transaction; |
58 | 57 | ||
59 | 58 | ||
@@ -74,6 +73,13 @@ static void vss_timeout_func(struct work_struct *dummy); | |||
74 | static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func); | 73 | static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func); |
75 | static DECLARE_WORK(vss_send_op_work, vss_send_op); | 74 | static DECLARE_WORK(vss_send_op_work, vss_send_op); |
76 | 75 | ||
76 | static void vss_poll_wrapper(void *channel) | ||
77 | { | ||
78 | /* Transaction is finished, reset the state here to avoid races. */ | ||
79 | vss_transaction.state = HVUTIL_READY; | ||
80 | hv_vss_onchannelcallback(channel); | ||
81 | } | ||
82 | |||
77 | /* | 83 | /* |
78 | * Callback when data is received from user mode. | 84 | * Callback when data is received from user mode. |
79 | */ | 85 | */ |
@@ -86,12 +92,7 @@ static void vss_timeout_func(struct work_struct *dummy) | |||
86 | pr_warn("VSS: timeout waiting for daemon to reply\n"); | 92 | pr_warn("VSS: timeout waiting for daemon to reply\n"); |
87 | vss_respond_to_host(HV_E_FAIL); | 93 | vss_respond_to_host(HV_E_FAIL); |
88 | 94 | ||
89 | /* Transaction is finished, reset the state. */ | 95 | hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper); |
90 | if (vss_transaction.state > HVUTIL_READY) | ||
91 | vss_transaction.state = HVUTIL_READY; | ||
92 | |||
93 | hv_poll_channel(vss_transaction.vss_context, | ||
94 | hv_vss_onchannelcallback); | ||
95 | } | 96 | } |
96 | 97 | ||
97 | static int vss_handle_handshake(struct hv_vss_msg *vss_msg) | 98 | static int vss_handle_handshake(struct hv_vss_msg *vss_msg) |
@@ -112,7 +113,7 @@ static int vss_handle_handshake(struct hv_vss_msg *vss_msg) | |||
112 | default: | 113 | default: |
113 | return -EINVAL; | 114 | return -EINVAL; |
114 | } | 115 | } |
115 | vss_transaction.state = HVUTIL_READY; | 116 | hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper); |
116 | pr_debug("VSS: userspace daemon ver. %d registered\n", dm_reg_value); | 117 | pr_debug("VSS: userspace daemon ver. %d registered\n", dm_reg_value); |
117 | return 0; | 118 | return 0; |
118 | } | 119 | } |
@@ -138,9 +139,8 @@ static int vss_on_msg(void *msg, int len) | |||
138 | if (cancel_delayed_work_sync(&vss_timeout_work)) { | 139 | if (cancel_delayed_work_sync(&vss_timeout_work)) { |
139 | vss_respond_to_host(vss_msg->error); | 140 | vss_respond_to_host(vss_msg->error); |
140 | /* Transaction is finished, reset the state. */ | 141 | /* Transaction is finished, reset the state. */ |
141 | vss_transaction.state = HVUTIL_READY; | 142 | hv_poll_channel(vss_transaction.recv_channel, |
142 | hv_poll_channel(vss_transaction.vss_context, | 143 | vss_poll_wrapper); |
143 | hv_vss_onchannelcallback); | ||
144 | } | 144 | } |
145 | } else { | 145 | } else { |
146 | /* This is a spurious call! */ | 146 | /* This is a spurious call! */ |
@@ -238,15 +238,8 @@ void hv_vss_onchannelcallback(void *context) | |||
238 | struct icmsg_hdr *icmsghdrp; | 238 | struct icmsg_hdr *icmsghdrp; |
239 | struct icmsg_negotiate *negop = NULL; | 239 | struct icmsg_negotiate *negop = NULL; |
240 | 240 | ||
241 | if (vss_transaction.state > HVUTIL_READY) { | 241 | if (vss_transaction.state > HVUTIL_READY) |
242 | /* | ||
243 | * We will defer processing this callback once | ||
244 | * the current transaction is complete. | ||
245 | */ | ||
246 | vss_transaction.vss_context = context; | ||
247 | return; | 242 | return; |
248 | } | ||
249 | vss_transaction.vss_context = NULL; | ||
250 | 243 | ||
251 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, | 244 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, |
252 | &requestid); | 245 | &requestid); |
@@ -338,6 +331,11 @@ static void vss_on_reset(void) | |||
338 | int | 331 | int |
339 | hv_vss_init(struct hv_util_service *srv) | 332 | hv_vss_init(struct hv_util_service *srv) |
340 | { | 333 | { |
334 | if (vmbus_proto_version < VERSION_WIN8_1) { | ||
335 | pr_warn("Integration service 'Backup (volume snapshot)'" | ||
336 | " not supported on this host version.\n"); | ||
337 | return -ENOTSUPP; | ||
338 | } | ||
341 | recv_buffer = srv->recv_buffer; | 339 | recv_buffer = srv->recv_buffer; |
342 | 340 | ||
343 | /* | 341 | /* |
diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c index 6a9d80a5332d..4f42c0e20c20 100644 --- a/drivers/hv/hv_utils_transport.c +++ b/drivers/hv/hv_utils_transport.c | |||
@@ -27,11 +27,9 @@ static struct list_head hvt_list = LIST_HEAD_INIT(hvt_list); | |||
27 | 27 | ||
28 | static void hvt_reset(struct hvutil_transport *hvt) | 28 | static void hvt_reset(struct hvutil_transport *hvt) |
29 | { | 29 | { |
30 | mutex_lock(&hvt->outmsg_lock); | ||
31 | kfree(hvt->outmsg); | 30 | kfree(hvt->outmsg); |
32 | hvt->outmsg = NULL; | 31 | hvt->outmsg = NULL; |
33 | hvt->outmsg_len = 0; | 32 | hvt->outmsg_len = 0; |
34 | mutex_unlock(&hvt->outmsg_lock); | ||
35 | if (hvt->on_reset) | 33 | if (hvt->on_reset) |
36 | hvt->on_reset(); | 34 | hvt->on_reset(); |
37 | } | 35 | } |
@@ -44,10 +42,17 @@ static ssize_t hvt_op_read(struct file *file, char __user *buf, | |||
44 | 42 | ||
45 | hvt = container_of(file->f_op, struct hvutil_transport, fops); | 43 | hvt = container_of(file->f_op, struct hvutil_transport, fops); |
46 | 44 | ||
47 | if (wait_event_interruptible(hvt->outmsg_q, hvt->outmsg_len > 0)) | 45 | if (wait_event_interruptible(hvt->outmsg_q, hvt->outmsg_len > 0 || |
46 | hvt->mode != HVUTIL_TRANSPORT_CHARDEV)) | ||
48 | return -EINTR; | 47 | return -EINTR; |
49 | 48 | ||
50 | mutex_lock(&hvt->outmsg_lock); | 49 | mutex_lock(&hvt->lock); |
50 | |||
51 | if (hvt->mode == HVUTIL_TRANSPORT_DESTROY) { | ||
52 | ret = -EBADF; | ||
53 | goto out_unlock; | ||
54 | } | ||
55 | |||
51 | if (!hvt->outmsg) { | 56 | if (!hvt->outmsg) { |
52 | ret = -EAGAIN; | 57 | ret = -EAGAIN; |
53 | goto out_unlock; | 58 | goto out_unlock; |
@@ -68,7 +73,7 @@ static ssize_t hvt_op_read(struct file *file, char __user *buf, | |||
68 | hvt->outmsg_len = 0; | 73 | hvt->outmsg_len = 0; |
69 | 74 | ||
70 | out_unlock: | 75 | out_unlock: |
71 | mutex_unlock(&hvt->outmsg_lock); | 76 | mutex_unlock(&hvt->lock); |
72 | return ret; | 77 | return ret; |
73 | } | 78 | } |
74 | 79 | ||
@@ -77,19 +82,22 @@ static ssize_t hvt_op_write(struct file *file, const char __user *buf, | |||
77 | { | 82 | { |
78 | struct hvutil_transport *hvt; | 83 | struct hvutil_transport *hvt; |
79 | u8 *inmsg; | 84 | u8 *inmsg; |
85 | int ret; | ||
80 | 86 | ||
81 | hvt = container_of(file->f_op, struct hvutil_transport, fops); | 87 | hvt = container_of(file->f_op, struct hvutil_transport, fops); |
82 | 88 | ||
83 | inmsg = kzalloc(count, GFP_KERNEL); | 89 | inmsg = memdup_user(buf, count); |
84 | if (copy_from_user(inmsg, buf, count)) { | 90 | if (IS_ERR(inmsg)) |
85 | kfree(inmsg); | 91 | return PTR_ERR(inmsg); |
86 | return -EFAULT; | 92 | |
87 | } | 93 | if (hvt->mode == HVUTIL_TRANSPORT_DESTROY) |
88 | if (hvt->on_msg(inmsg, count)) | 94 | ret = -EBADF; |
89 | return -EFAULT; | 95 | else |
96 | ret = hvt->on_msg(inmsg, count); | ||
97 | |||
90 | kfree(inmsg); | 98 | kfree(inmsg); |
91 | 99 | ||
92 | return count; | 100 | return ret ? ret : count; |
93 | } | 101 | } |
94 | 102 | ||
95 | static unsigned int hvt_op_poll(struct file *file, poll_table *wait) | 103 | static unsigned int hvt_op_poll(struct file *file, poll_table *wait) |
@@ -99,6 +107,10 @@ static unsigned int hvt_op_poll(struct file *file, poll_table *wait) | |||
99 | hvt = container_of(file->f_op, struct hvutil_transport, fops); | 107 | hvt = container_of(file->f_op, struct hvutil_transport, fops); |
100 | 108 | ||
101 | poll_wait(file, &hvt->outmsg_q, wait); | 109 | poll_wait(file, &hvt->outmsg_q, wait); |
110 | |||
111 | if (hvt->mode == HVUTIL_TRANSPORT_DESTROY) | ||
112 | return POLLERR | POLLHUP; | ||
113 | |||
102 | if (hvt->outmsg_len > 0) | 114 | if (hvt->outmsg_len > 0) |
103 | return POLLIN | POLLRDNORM; | 115 | return POLLIN | POLLRDNORM; |
104 | 116 | ||
@@ -108,40 +120,68 @@ static unsigned int hvt_op_poll(struct file *file, poll_table *wait) | |||
108 | static int hvt_op_open(struct inode *inode, struct file *file) | 120 | static int hvt_op_open(struct inode *inode, struct file *file) |
109 | { | 121 | { |
110 | struct hvutil_transport *hvt; | 122 | struct hvutil_transport *hvt; |
123 | int ret = 0; | ||
124 | bool issue_reset = false; | ||
111 | 125 | ||
112 | hvt = container_of(file->f_op, struct hvutil_transport, fops); | 126 | hvt = container_of(file->f_op, struct hvutil_transport, fops); |
113 | 127 | ||
114 | /* | 128 | mutex_lock(&hvt->lock); |
115 | * Switching to CHARDEV mode. We switch bach to INIT when device | 129 | |
116 | * gets released. | 130 | if (hvt->mode == HVUTIL_TRANSPORT_DESTROY) { |
117 | */ | 131 | ret = -EBADF; |
118 | if (hvt->mode == HVUTIL_TRANSPORT_INIT) | 132 | } else if (hvt->mode == HVUTIL_TRANSPORT_INIT) { |
133 | /* | ||
134 | * Switching to CHARDEV mode. We switch bach to INIT when | ||
135 | * device gets released. | ||
136 | */ | ||
119 | hvt->mode = HVUTIL_TRANSPORT_CHARDEV; | 137 | hvt->mode = HVUTIL_TRANSPORT_CHARDEV; |
138 | } | ||
120 | else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) { | 139 | else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) { |
121 | /* | 140 | /* |
122 | * We're switching from netlink communication to using char | 141 | * We're switching from netlink communication to using char |
123 | * device. Issue the reset first. | 142 | * device. Issue the reset first. |
124 | */ | 143 | */ |
125 | hvt_reset(hvt); | 144 | issue_reset = true; |
126 | hvt->mode = HVUTIL_TRANSPORT_CHARDEV; | 145 | hvt->mode = HVUTIL_TRANSPORT_CHARDEV; |
127 | } else | 146 | } else { |
128 | return -EBUSY; | 147 | ret = -EBUSY; |
148 | } | ||
129 | 149 | ||
130 | return 0; | 150 | if (issue_reset) |
151 | hvt_reset(hvt); | ||
152 | |||
153 | mutex_unlock(&hvt->lock); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static void hvt_transport_free(struct hvutil_transport *hvt) | ||
159 | { | ||
160 | misc_deregister(&hvt->mdev); | ||
161 | kfree(hvt->outmsg); | ||
162 | kfree(hvt); | ||
131 | } | 163 | } |
132 | 164 | ||
133 | static int hvt_op_release(struct inode *inode, struct file *file) | 165 | static int hvt_op_release(struct inode *inode, struct file *file) |
134 | { | 166 | { |
135 | struct hvutil_transport *hvt; | 167 | struct hvutil_transport *hvt; |
168 | int mode_old; | ||
136 | 169 | ||
137 | hvt = container_of(file->f_op, struct hvutil_transport, fops); | 170 | hvt = container_of(file->f_op, struct hvutil_transport, fops); |
138 | 171 | ||
139 | hvt->mode = HVUTIL_TRANSPORT_INIT; | 172 | mutex_lock(&hvt->lock); |
173 | mode_old = hvt->mode; | ||
174 | if (hvt->mode != HVUTIL_TRANSPORT_DESTROY) | ||
175 | hvt->mode = HVUTIL_TRANSPORT_INIT; | ||
140 | /* | 176 | /* |
141 | * Cleanup message buffers to avoid spurious messages when the daemon | 177 | * Cleanup message buffers to avoid spurious messages when the daemon |
142 | * connects back. | 178 | * connects back. |
143 | */ | 179 | */ |
144 | hvt_reset(hvt); | 180 | hvt_reset(hvt); |
181 | mutex_unlock(&hvt->lock); | ||
182 | |||
183 | if (mode_old == HVUTIL_TRANSPORT_DESTROY) | ||
184 | hvt_transport_free(hvt); | ||
145 | 185 | ||
146 | return 0; | 186 | return 0; |
147 | } | 187 | } |
@@ -168,6 +208,7 @@ static void hvt_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
168 | * Switching to NETLINK mode. Switching to CHARDEV happens when someone | 208 | * Switching to NETLINK mode. Switching to CHARDEV happens when someone |
169 | * opens the device. | 209 | * opens the device. |
170 | */ | 210 | */ |
211 | mutex_lock(&hvt->lock); | ||
171 | if (hvt->mode == HVUTIL_TRANSPORT_INIT) | 212 | if (hvt->mode == HVUTIL_TRANSPORT_INIT) |
172 | hvt->mode = HVUTIL_TRANSPORT_NETLINK; | 213 | hvt->mode = HVUTIL_TRANSPORT_NETLINK; |
173 | 214 | ||
@@ -175,6 +216,7 @@ static void hvt_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
175 | hvt_found->on_msg(msg->data, msg->len); | 216 | hvt_found->on_msg(msg->data, msg->len); |
176 | else | 217 | else |
177 | pr_warn("hvt_cn_callback: unexpected netlink message!\n"); | 218 | pr_warn("hvt_cn_callback: unexpected netlink message!\n"); |
219 | mutex_unlock(&hvt->lock); | ||
178 | } | 220 | } |
179 | 221 | ||
180 | int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len) | 222 | int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len) |
@@ -182,7 +224,8 @@ int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len) | |||
182 | struct cn_msg *cn_msg; | 224 | struct cn_msg *cn_msg; |
183 | int ret = 0; | 225 | int ret = 0; |
184 | 226 | ||
185 | if (hvt->mode == HVUTIL_TRANSPORT_INIT) { | 227 | if (hvt->mode == HVUTIL_TRANSPORT_INIT || |
228 | hvt->mode == HVUTIL_TRANSPORT_DESTROY) { | ||
186 | return -EINVAL; | 229 | return -EINVAL; |
187 | } else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) { | 230 | } else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) { |
188 | cn_msg = kzalloc(sizeof(*cn_msg) + len, GFP_ATOMIC); | 231 | cn_msg = kzalloc(sizeof(*cn_msg) + len, GFP_ATOMIC); |
@@ -197,18 +240,26 @@ int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len) | |||
197 | return ret; | 240 | return ret; |
198 | } | 241 | } |
199 | /* HVUTIL_TRANSPORT_CHARDEV */ | 242 | /* HVUTIL_TRANSPORT_CHARDEV */ |
200 | mutex_lock(&hvt->outmsg_lock); | 243 | mutex_lock(&hvt->lock); |
244 | if (hvt->mode != HVUTIL_TRANSPORT_CHARDEV) { | ||
245 | ret = -EINVAL; | ||
246 | goto out_unlock; | ||
247 | } | ||
248 | |||
201 | if (hvt->outmsg) { | 249 | if (hvt->outmsg) { |
202 | /* Previous message wasn't received */ | 250 | /* Previous message wasn't received */ |
203 | ret = -EFAULT; | 251 | ret = -EFAULT; |
204 | goto out_unlock; | 252 | goto out_unlock; |
205 | } | 253 | } |
206 | hvt->outmsg = kzalloc(len, GFP_KERNEL); | 254 | hvt->outmsg = kzalloc(len, GFP_KERNEL); |
207 | memcpy(hvt->outmsg, msg, len); | 255 | if (hvt->outmsg) { |
208 | hvt->outmsg_len = len; | 256 | memcpy(hvt->outmsg, msg, len); |
209 | wake_up_interruptible(&hvt->outmsg_q); | 257 | hvt->outmsg_len = len; |
258 | wake_up_interruptible(&hvt->outmsg_q); | ||
259 | } else | ||
260 | ret = -ENOMEM; | ||
210 | out_unlock: | 261 | out_unlock: |
211 | mutex_unlock(&hvt->outmsg_lock); | 262 | mutex_unlock(&hvt->lock); |
212 | return ret; | 263 | return ret; |
213 | } | 264 | } |
214 | 265 | ||
@@ -239,7 +290,7 @@ struct hvutil_transport *hvutil_transport_init(const char *name, | |||
239 | hvt->mdev.fops = &hvt->fops; | 290 | hvt->mdev.fops = &hvt->fops; |
240 | 291 | ||
241 | init_waitqueue_head(&hvt->outmsg_q); | 292 | init_waitqueue_head(&hvt->outmsg_q); |
242 | mutex_init(&hvt->outmsg_lock); | 293 | mutex_init(&hvt->lock); |
243 | 294 | ||
244 | spin_lock(&hvt_list_lock); | 295 | spin_lock(&hvt_list_lock); |
245 | list_add(&hvt->list, &hvt_list); | 296 | list_add(&hvt->list, &hvt_list); |
@@ -265,12 +316,25 @@ err_free_hvt: | |||
265 | 316 | ||
266 | void hvutil_transport_destroy(struct hvutil_transport *hvt) | 317 | void hvutil_transport_destroy(struct hvutil_transport *hvt) |
267 | { | 318 | { |
319 | int mode_old; | ||
320 | |||
321 | mutex_lock(&hvt->lock); | ||
322 | mode_old = hvt->mode; | ||
323 | hvt->mode = HVUTIL_TRANSPORT_DESTROY; | ||
324 | wake_up_interruptible(&hvt->outmsg_q); | ||
325 | mutex_unlock(&hvt->lock); | ||
326 | |||
327 | /* | ||
328 | * In case we were in 'chardev' mode we still have an open fd so we | ||
329 | * have to defer freeing the device. Netlink interface can be freed | ||
330 | * now. | ||
331 | */ | ||
268 | spin_lock(&hvt_list_lock); | 332 | spin_lock(&hvt_list_lock); |
269 | list_del(&hvt->list); | 333 | list_del(&hvt->list); |
270 | spin_unlock(&hvt_list_lock); | 334 | spin_unlock(&hvt_list_lock); |
271 | if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0) | 335 | if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0) |
272 | cn_del_callback(&hvt->cn_id); | 336 | cn_del_callback(&hvt->cn_id); |
273 | misc_deregister(&hvt->mdev); | 337 | |
274 | kfree(hvt->outmsg); | 338 | if (mode_old != HVUTIL_TRANSPORT_CHARDEV) |
275 | kfree(hvt); | 339 | hvt_transport_free(hvt); |
276 | } | 340 | } |
diff --git a/drivers/hv/hv_utils_transport.h b/drivers/hv/hv_utils_transport.h index 314c76ce1b07..06254a165a18 100644 --- a/drivers/hv/hv_utils_transport.h +++ b/drivers/hv/hv_utils_transport.h | |||
@@ -25,6 +25,7 @@ enum hvutil_transport_mode { | |||
25 | HVUTIL_TRANSPORT_INIT = 0, | 25 | HVUTIL_TRANSPORT_INIT = 0, |
26 | HVUTIL_TRANSPORT_NETLINK, | 26 | HVUTIL_TRANSPORT_NETLINK, |
27 | HVUTIL_TRANSPORT_CHARDEV, | 27 | HVUTIL_TRANSPORT_CHARDEV, |
28 | HVUTIL_TRANSPORT_DESTROY, | ||
28 | }; | 29 | }; |
29 | 30 | ||
30 | struct hvutil_transport { | 31 | struct hvutil_transport { |
@@ -38,7 +39,7 @@ struct hvutil_transport { | |||
38 | u8 *outmsg; /* message to the userspace */ | 39 | u8 *outmsg; /* message to the userspace */ |
39 | int outmsg_len; /* its length */ | 40 | int outmsg_len; /* its length */ |
40 | wait_queue_head_t outmsg_q; /* poll/read wait queue */ | 41 | wait_queue_head_t outmsg_q; /* poll/read wait queue */ |
41 | struct mutex outmsg_lock; /* protects outmsg */ | 42 | struct mutex lock; /* protects struct members */ |
42 | }; | 43 | }; |
43 | 44 | ||
44 | struct hvutil_transport *hvutil_transport_init(const char *name, | 45 | struct hvutil_transport *hvutil_transport_init(const char *name, |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 678663e2085f..4ebc796b4f33 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -31,6 +31,11 @@ | |||
31 | #include <linux/hyperv.h> | 31 | #include <linux/hyperv.h> |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Timeout for services such as KVP and fcopy. | ||
35 | */ | ||
36 | #define HV_UTIL_TIMEOUT 30 | ||
37 | |||
38 | /* | ||
34 | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent | 39 | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent |
35 | * is set by CPUID(HVCPUID_VERSION_FEATURES). | 40 | * is set by CPUID(HVCPUID_VERSION_FEATURES). |
36 | */ | 41 | */ |
@@ -496,7 +501,7 @@ extern int hv_post_message(union hv_connection_id connection_id, | |||
496 | enum hv_message_type message_type, | 501 | enum hv_message_type message_type, |
497 | void *payload, size_t payload_size); | 502 | void *payload, size_t payload_size); |
498 | 503 | ||
499 | extern u16 hv_signal_event(void *con_id); | 504 | extern int hv_signal_event(void *con_id); |
500 | 505 | ||
501 | extern int hv_synic_alloc(void); | 506 | extern int hv_synic_alloc(void); |
502 | 507 | ||
@@ -528,14 +533,9 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info, | |||
528 | struct kvec *kv_list, | 533 | struct kvec *kv_list, |
529 | u32 kv_count, bool *signal); | 534 | u32 kv_count, bool *signal); |
530 | 535 | ||
531 | int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer, | 536 | int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, |
532 | u32 buflen); | 537 | void *buffer, u32 buflen, u32 *buffer_actual_len, |
533 | 538 | u64 *requestid, bool *signal, bool raw); | |
534 | int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info, | ||
535 | void *buffer, | ||
536 | u32 buflen, | ||
537 | u32 offset, bool *signal); | ||
538 | |||
539 | 539 | ||
540 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, | 540 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, |
541 | struct hv_ring_buffer_debug_info *debug_info); | 541 | struct hv_ring_buffer_debug_info *debug_info); |
@@ -592,7 +592,7 @@ struct vmbus_connection { | |||
592 | 592 | ||
593 | /* List of channels */ | 593 | /* List of channels */ |
594 | struct list_head chn_list; | 594 | struct list_head chn_list; |
595 | spinlock_t channel_lock; | 595 | struct mutex channel_mutex; |
596 | 596 | ||
597 | struct workqueue_struct *work_queue; | 597 | struct workqueue_struct *work_queue; |
598 | }; | 598 | }; |
@@ -673,11 +673,7 @@ static inline void hv_poll_channel(struct vmbus_channel *channel, | |||
673 | if (!channel) | 673 | if (!channel) |
674 | return; | 674 | return; |
675 | 675 | ||
676 | if (channel->target_cpu != smp_processor_id()) | 676 | smp_call_function_single(channel->target_cpu, cb, channel, true); |
677 | smp_call_function_single(channel->target_cpu, | ||
678 | cb, channel, true); | ||
679 | else | ||
680 | cb(channel); | ||
681 | } | 677 | } |
682 | 678 | ||
683 | enum hvutil_device_state { | 679 | enum hvutil_device_state { |
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 70a1a9a22f87..b53702ce692f 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c | |||
@@ -112,9 +112,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, | |||
112 | u32 read_loc = rbi->ring_buffer->read_index; | 112 | u32 read_loc = rbi->ring_buffer->read_index; |
113 | u32 pending_sz = rbi->ring_buffer->pending_send_sz; | 113 | u32 pending_sz = rbi->ring_buffer->pending_send_sz; |
114 | 114 | ||
115 | /* | 115 | /* If the other end is not blocked on write don't bother. */ |
116 | * If the other end is not blocked on write don't bother. | ||
117 | */ | ||
118 | if (pending_sz == 0) | 116 | if (pending_sz == 0) |
119 | return false; | 117 | return false; |
120 | 118 | ||
@@ -128,12 +126,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, | |||
128 | return false; | 126 | return false; |
129 | } | 127 | } |
130 | 128 | ||
131 | /* | 129 | /* Get the next write location for the specified ring buffer. */ |
132 | * hv_get_next_write_location() | ||
133 | * | ||
134 | * Get the next write location for the specified ring buffer | ||
135 | * | ||
136 | */ | ||
137 | static inline u32 | 130 | static inline u32 |
138 | hv_get_next_write_location(struct hv_ring_buffer_info *ring_info) | 131 | hv_get_next_write_location(struct hv_ring_buffer_info *ring_info) |
139 | { | 132 | { |
@@ -142,12 +135,7 @@ hv_get_next_write_location(struct hv_ring_buffer_info *ring_info) | |||
142 | return next; | 135 | return next; |
143 | } | 136 | } |
144 | 137 | ||
145 | /* | 138 | /* Set the next write location for the specified ring buffer. */ |
146 | * hv_set_next_write_location() | ||
147 | * | ||
148 | * Set the next write location for the specified ring buffer | ||
149 | * | ||
150 | */ | ||
151 | static inline void | 139 | static inline void |
152 | hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, | 140 | hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, |
153 | u32 next_write_location) | 141 | u32 next_write_location) |
@@ -155,11 +143,7 @@ hv_set_next_write_location(struct hv_ring_buffer_info *ring_info, | |||
155 | ring_info->ring_buffer->write_index = next_write_location; | 143 | ring_info->ring_buffer->write_index = next_write_location; |
156 | } | 144 | } |
157 | 145 | ||
158 | /* | 146 | /* Get the next read location for the specified ring buffer. */ |
159 | * hv_get_next_read_location() | ||
160 | * | ||
161 | * Get the next read location for the specified ring buffer | ||
162 | */ | ||
163 | static inline u32 | 147 | static inline u32 |
164 | hv_get_next_read_location(struct hv_ring_buffer_info *ring_info) | 148 | hv_get_next_read_location(struct hv_ring_buffer_info *ring_info) |
165 | { | 149 | { |
@@ -169,10 +153,8 @@ hv_get_next_read_location(struct hv_ring_buffer_info *ring_info) | |||
169 | } | 153 | } |
170 | 154 | ||
171 | /* | 155 | /* |
172 | * hv_get_next_readlocation_withoffset() | ||
173 | * | ||
174 | * Get the next read location + offset for the specified ring buffer. | 156 | * Get the next read location + offset for the specified ring buffer. |
175 | * This allows the caller to skip | 157 | * This allows the caller to skip. |
176 | */ | 158 | */ |
177 | static inline u32 | 159 | static inline u32 |
178 | hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info, | 160 | hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info, |
@@ -186,13 +168,7 @@ hv_get_next_readlocation_withoffset(struct hv_ring_buffer_info *ring_info, | |||
186 | return next; | 168 | return next; |
187 | } | 169 | } |
188 | 170 | ||
189 | /* | 171 | /* Set the next read location for the specified ring buffer. */ |
190 | * | ||
191 | * hv_set_next_read_location() | ||
192 | * | ||
193 | * Set the next read location for the specified ring buffer | ||
194 | * | ||
195 | */ | ||
196 | static inline void | 172 | static inline void |
197 | hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, | 173 | hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, |
198 | u32 next_read_location) | 174 | u32 next_read_location) |
@@ -201,12 +177,7 @@ hv_set_next_read_location(struct hv_ring_buffer_info *ring_info, | |||
201 | } | 177 | } |
202 | 178 | ||
203 | 179 | ||
204 | /* | 180 | /* Get the start of the ring buffer. */ |
205 | * | ||
206 | * hv_get_ring_buffer() | ||
207 | * | ||
208 | * Get the start of the ring buffer | ||
209 | */ | ||
210 | static inline void * | 181 | static inline void * |
211 | hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info) | 182 | hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info) |
212 | { | 183 | { |
@@ -214,25 +185,14 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info) | |||
214 | } | 185 | } |
215 | 186 | ||
216 | 187 | ||
217 | /* | 188 | /* Get the size of the ring buffer. */ |
218 | * | ||
219 | * hv_get_ring_buffersize() | ||
220 | * | ||
221 | * Get the size of the ring buffer | ||
222 | */ | ||
223 | static inline u32 | 189 | static inline u32 |
224 | hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info) | 190 | hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info) |
225 | { | 191 | { |
226 | return ring_info->ring_datasize; | 192 | return ring_info->ring_datasize; |
227 | } | 193 | } |
228 | 194 | ||
229 | /* | 195 | /* Get the read and write indices as u64 of the specified ring buffer. */ |
230 | * | ||
231 | * hv_get_ring_bufferindices() | ||
232 | * | ||
233 | * Get the read and write indices as u64 of the specified ring buffer | ||
234 | * | ||
235 | */ | ||
236 | static inline u64 | 196 | static inline u64 |
237 | hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) | 197 | hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) |
238 | { | 198 | { |
@@ -240,12 +200,8 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) | |||
240 | } | 200 | } |
241 | 201 | ||
242 | /* | 202 | /* |
243 | * | ||
244 | * hv_copyfrom_ringbuffer() | ||
245 | * | ||
246 | * Helper routine to copy to source from ring buffer. | 203 | * Helper routine to copy to source from ring buffer. |
247 | * Assume there is enough room. Handles wrap-around in src case only!! | 204 | * Assume there is enough room. Handles wrap-around in src case only!! |
248 | * | ||
249 | */ | 205 | */ |
250 | static u32 hv_copyfrom_ringbuffer( | 206 | static u32 hv_copyfrom_ringbuffer( |
251 | struct hv_ring_buffer_info *ring_info, | 207 | struct hv_ring_buffer_info *ring_info, |
@@ -277,12 +233,8 @@ static u32 hv_copyfrom_ringbuffer( | |||
277 | 233 | ||
278 | 234 | ||
279 | /* | 235 | /* |
280 | * | ||
281 | * hv_copyto_ringbuffer() | ||
282 | * | ||
283 | * Helper routine to copy from source to ring buffer. | 236 | * Helper routine to copy from source to ring buffer. |
284 | * Assume there is enough room. Handles wrap-around in dest case only!! | 237 | * Assume there is enough room. Handles wrap-around in dest case only!! |
285 | * | ||
286 | */ | 238 | */ |
287 | static u32 hv_copyto_ringbuffer( | 239 | static u32 hv_copyto_ringbuffer( |
288 | struct hv_ring_buffer_info *ring_info, | 240 | struct hv_ring_buffer_info *ring_info, |
@@ -308,13 +260,7 @@ static u32 hv_copyto_ringbuffer( | |||
308 | return start_write_offset; | 260 | return start_write_offset; |
309 | } | 261 | } |
310 | 262 | ||
311 | /* | 263 | /* Get various debug metrics for the specified ring buffer. */ |
312 | * | ||
313 | * hv_ringbuffer_get_debuginfo() | ||
314 | * | ||
315 | * Get various debug metrics for the specified ring buffer | ||
316 | * | ||
317 | */ | ||
318 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, | 264 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, |
319 | struct hv_ring_buffer_debug_info *debug_info) | 265 | struct hv_ring_buffer_debug_info *debug_info) |
320 | { | 266 | { |
@@ -337,13 +283,7 @@ void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, | |||
337 | } | 283 | } |
338 | } | 284 | } |
339 | 285 | ||
340 | /* | 286 | /* Initialize the ring buffer. */ |
341 | * | ||
342 | * hv_ringbuffer_init() | ||
343 | * | ||
344 | *Initialize the ring buffer | ||
345 | * | ||
346 | */ | ||
347 | int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, | 287 | int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, |
348 | void *buffer, u32 buflen) | 288 | void *buffer, u32 buflen) |
349 | { | 289 | { |
@@ -356,9 +296,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, | |||
356 | ring_info->ring_buffer->read_index = | 296 | ring_info->ring_buffer->read_index = |
357 | ring_info->ring_buffer->write_index = 0; | 297 | ring_info->ring_buffer->write_index = 0; |
358 | 298 | ||
359 | /* | 299 | /* Set the feature bit for enabling flow control. */ |
360 | * Set the feature bit for enabling flow control. | ||
361 | */ | ||
362 | ring_info->ring_buffer->feature_bits.value = 1; | 300 | ring_info->ring_buffer->feature_bits.value = 1; |
363 | 301 | ||
364 | ring_info->ring_size = buflen; | 302 | ring_info->ring_size = buflen; |
@@ -369,24 +307,12 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, | |||
369 | return 0; | 307 | return 0; |
370 | } | 308 | } |
371 | 309 | ||
372 | /* | 310 | /* Cleanup the ring buffer. */ |
373 | * | ||
374 | * hv_ringbuffer_cleanup() | ||
375 | * | ||
376 | * Cleanup the ring buffer | ||
377 | * | ||
378 | */ | ||
379 | void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) | 311 | void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) |
380 | { | 312 | { |
381 | } | 313 | } |
382 | 314 | ||
383 | /* | 315 | /* Write to the ring buffer. */ |
384 | * | ||
385 | * hv_ringbuffer_write() | ||
386 | * | ||
387 | * Write to the ring buffer | ||
388 | * | ||
389 | */ | ||
390 | int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, | 316 | int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, |
391 | struct kvec *kv_list, u32 kv_count, bool *signal) | 317 | struct kvec *kv_list, u32 kv_count, bool *signal) |
392 | { | 318 | { |
@@ -411,10 +337,11 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, | |||
411 | &bytes_avail_toread, | 337 | &bytes_avail_toread, |
412 | &bytes_avail_towrite); | 338 | &bytes_avail_towrite); |
413 | 339 | ||
414 | 340 | /* | |
415 | /* If there is only room for the packet, assume it is full. */ | 341 | * If there is only room for the packet, assume it is full. |
416 | /* Otherwise, the next time around, we think the ring buffer */ | 342 | * Otherwise, the next time around, we think the ring buffer |
417 | /* is empty since the read index == write index */ | 343 | * is empty since the read index == write index. |
344 | */ | ||
418 | if (bytes_avail_towrite <= totalbytes_towrite) { | 345 | if (bytes_avail_towrite <= totalbytes_towrite) { |
419 | spin_unlock_irqrestore(&outring_info->ring_lock, flags); | 346 | spin_unlock_irqrestore(&outring_info->ring_lock, flags); |
420 | return -EAGAIN; | 347 | return -EAGAIN; |
@@ -453,80 +380,59 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, | |||
453 | return 0; | 380 | return 0; |
454 | } | 381 | } |
455 | 382 | ||
456 | 383 | int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, | |
457 | /* | 384 | void *buffer, u32 buflen, u32 *buffer_actual_len, |
458 | * | 385 | u64 *requestid, bool *signal, bool raw) |
459 | * hv_ringbuffer_peek() | ||
460 | * | ||
461 | * Read without advancing the read index | ||
462 | * | ||
463 | */ | ||
464 | int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info, | ||
465 | void *Buffer, u32 buflen) | ||
466 | { | ||
467 | u32 bytes_avail_towrite; | ||
468 | u32 bytes_avail_toread; | ||
469 | u32 next_read_location = 0; | ||
470 | unsigned long flags; | ||
471 | |||
472 | spin_lock_irqsave(&Inring_info->ring_lock, flags); | ||
473 | |||
474 | hv_get_ringbuffer_availbytes(Inring_info, | ||
475 | &bytes_avail_toread, | ||
476 | &bytes_avail_towrite); | ||
477 | |||
478 | /* Make sure there is something to read */ | ||
479 | if (bytes_avail_toread < buflen) { | ||
480 | |||
481 | spin_unlock_irqrestore(&Inring_info->ring_lock, flags); | ||
482 | |||
483 | return -EAGAIN; | ||
484 | } | ||
485 | |||
486 | /* Convert to byte offset */ | ||
487 | next_read_location = hv_get_next_read_location(Inring_info); | ||
488 | |||
489 | next_read_location = hv_copyfrom_ringbuffer(Inring_info, | ||
490 | Buffer, | ||
491 | buflen, | ||
492 | next_read_location); | ||
493 | |||
494 | spin_unlock_irqrestore(&Inring_info->ring_lock, flags); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | |||
500 | /* | ||
501 | * | ||
502 | * hv_ringbuffer_read() | ||
503 | * | ||
504 | * Read and advance the read index | ||
505 | * | ||
506 | */ | ||
507 | int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, | ||
508 | u32 buflen, u32 offset, bool *signal) | ||
509 | { | 386 | { |
510 | u32 bytes_avail_towrite; | 387 | u32 bytes_avail_towrite; |
511 | u32 bytes_avail_toread; | 388 | u32 bytes_avail_toread; |
512 | u32 next_read_location = 0; | 389 | u32 next_read_location = 0; |
513 | u64 prev_indices = 0; | 390 | u64 prev_indices = 0; |
514 | unsigned long flags; | 391 | unsigned long flags; |
392 | struct vmpacket_descriptor desc; | ||
393 | u32 offset; | ||
394 | u32 packetlen; | ||
395 | int ret = 0; | ||
515 | 396 | ||
516 | if (buflen <= 0) | 397 | if (buflen <= 0) |
517 | return -EINVAL; | 398 | return -EINVAL; |
518 | 399 | ||
519 | spin_lock_irqsave(&inring_info->ring_lock, flags); | 400 | spin_lock_irqsave(&inring_info->ring_lock, flags); |
520 | 401 | ||
402 | *buffer_actual_len = 0; | ||
403 | *requestid = 0; | ||
404 | |||
521 | hv_get_ringbuffer_availbytes(inring_info, | 405 | hv_get_ringbuffer_availbytes(inring_info, |
522 | &bytes_avail_toread, | 406 | &bytes_avail_toread, |
523 | &bytes_avail_towrite); | 407 | &bytes_avail_towrite); |
524 | 408 | ||
525 | /* Make sure there is something to read */ | 409 | /* Make sure there is something to read */ |
526 | if (bytes_avail_toread < buflen) { | 410 | if (bytes_avail_toread < sizeof(desc)) { |
527 | spin_unlock_irqrestore(&inring_info->ring_lock, flags); | 411 | /* |
412 | * No error is set when there is even no header, drivers are | ||
413 | * supposed to analyze buffer_actual_len. | ||
414 | */ | ||
415 | goto out_unlock; | ||
416 | } | ||
528 | 417 | ||
529 | return -EAGAIN; | 418 | next_read_location = hv_get_next_read_location(inring_info); |
419 | next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc, | ||
420 | sizeof(desc), | ||
421 | next_read_location); | ||
422 | |||
423 | offset = raw ? 0 : (desc.offset8 << 3); | ||
424 | packetlen = (desc.len8 << 3) - offset; | ||
425 | *buffer_actual_len = packetlen; | ||
426 | *requestid = desc.trans_id; | ||
427 | |||
428 | if (bytes_avail_toread < packetlen + offset) { | ||
429 | ret = -EAGAIN; | ||
430 | goto out_unlock; | ||
431 | } | ||
432 | |||
433 | if (packetlen > buflen) { | ||
434 | ret = -ENOBUFS; | ||
435 | goto out_unlock; | ||
530 | } | 436 | } |
531 | 437 | ||
532 | next_read_location = | 438 | next_read_location = |
@@ -534,7 +440,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, | |||
534 | 440 | ||
535 | next_read_location = hv_copyfrom_ringbuffer(inring_info, | 441 | next_read_location = hv_copyfrom_ringbuffer(inring_info, |
536 | buffer, | 442 | buffer, |
537 | buflen, | 443 | packetlen, |
538 | next_read_location); | 444 | next_read_location); |
539 | 445 | ||
540 | next_read_location = hv_copyfrom_ringbuffer(inring_info, | 446 | next_read_location = hv_copyfrom_ringbuffer(inring_info, |
@@ -542,17 +448,19 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, | |||
542 | sizeof(u64), | 448 | sizeof(u64), |
543 | next_read_location); | 449 | next_read_location); |
544 | 450 | ||
545 | /* Make sure all reads are done before we update the read index since */ | 451 | /* |
546 | /* the writer may start writing to the read area once the read index */ | 452 | * Make sure all reads are done before we update the read index since |
547 | /*is updated */ | 453 | * the writer may start writing to the read area once the read index |
454 | * is updated. | ||
455 | */ | ||
548 | mb(); | 456 | mb(); |
549 | 457 | ||
550 | /* Update the read index */ | 458 | /* Update the read index */ |
551 | hv_set_next_read_location(inring_info, next_read_location); | 459 | hv_set_next_read_location(inring_info, next_read_location); |
552 | 460 | ||
553 | spin_unlock_irqrestore(&inring_info->ring_lock, flags); | ||
554 | |||
555 | *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info); | 461 | *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info); |
556 | 462 | ||
557 | return 0; | 463 | out_unlock: |
464 | spin_unlock_irqrestore(&inring_info->ring_lock, flags); | ||
465 | return ret; | ||
558 | } | 466 | } |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index f19b6f7a467a..328e4c3808e0 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -47,7 +47,6 @@ static struct acpi_device *hv_acpi_dev; | |||
47 | 47 | ||
48 | static struct tasklet_struct msg_dpc; | 48 | static struct tasklet_struct msg_dpc; |
49 | static struct completion probe_event; | 49 | static struct completion probe_event; |
50 | static int irq; | ||
51 | 50 | ||
52 | 51 | ||
53 | static void hyperv_report_panic(struct pt_regs *regs) | 52 | static void hyperv_report_panic(struct pt_regs *regs) |
@@ -531,9 +530,9 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) | |||
531 | 530 | ||
532 | static const uuid_le null_guid; | 531 | static const uuid_le null_guid; |
533 | 532 | ||
534 | static inline bool is_null_guid(const __u8 *guid) | 533 | static inline bool is_null_guid(const uuid_le *guid) |
535 | { | 534 | { |
536 | if (memcmp(guid, &null_guid, sizeof(uuid_le))) | 535 | if (uuid_le_cmp(*guid, null_guid)) |
537 | return false; | 536 | return false; |
538 | return true; | 537 | return true; |
539 | } | 538 | } |
@@ -544,10 +543,10 @@ static inline bool is_null_guid(const __u8 *guid) | |||
544 | */ | 543 | */ |
545 | static const struct hv_vmbus_device_id *hv_vmbus_get_id( | 544 | static const struct hv_vmbus_device_id *hv_vmbus_get_id( |
546 | const struct hv_vmbus_device_id *id, | 545 | const struct hv_vmbus_device_id *id, |
547 | const __u8 *guid) | 546 | const uuid_le *guid) |
548 | { | 547 | { |
549 | for (; !is_null_guid(id->guid); id++) | 548 | for (; !is_null_guid(&id->guid); id++) |
550 | if (!memcmp(&id->guid, guid, sizeof(uuid_le))) | 549 | if (!uuid_le_cmp(id->guid, *guid)) |
551 | return id; | 550 | return id; |
552 | 551 | ||
553 | return NULL; | 552 | return NULL; |
@@ -563,7 +562,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver) | |||
563 | struct hv_driver *drv = drv_to_hv_drv(driver); | 562 | struct hv_driver *drv = drv_to_hv_drv(driver); |
564 | struct hv_device *hv_dev = device_to_hv_device(device); | 563 | struct hv_device *hv_dev = device_to_hv_device(device); |
565 | 564 | ||
566 | if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b)) | 565 | if (hv_vmbus_get_id(drv->id_table, &hv_dev->dev_type)) |
567 | return 1; | 566 | return 1; |
568 | 567 | ||
569 | return 0; | 568 | return 0; |
@@ -580,7 +579,7 @@ static int vmbus_probe(struct device *child_device) | |||
580 | struct hv_device *dev = device_to_hv_device(child_device); | 579 | struct hv_device *dev = device_to_hv_device(child_device); |
581 | const struct hv_vmbus_device_id *dev_id; | 580 | const struct hv_vmbus_device_id *dev_id; |
582 | 581 | ||
583 | dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b); | 582 | dev_id = hv_vmbus_get_id(drv->id_table, &dev->dev_type); |
584 | if (drv->probe) { | 583 | if (drv->probe) { |
585 | ret = drv->probe(dev, dev_id); | 584 | ret = drv->probe(dev, dev_id); |
586 | if (ret != 0) | 585 | if (ret != 0) |
@@ -602,23 +601,11 @@ static int vmbus_remove(struct device *child_device) | |||
602 | { | 601 | { |
603 | struct hv_driver *drv; | 602 | struct hv_driver *drv; |
604 | struct hv_device *dev = device_to_hv_device(child_device); | 603 | struct hv_device *dev = device_to_hv_device(child_device); |
605 | u32 relid = dev->channel->offermsg.child_relid; | ||
606 | 604 | ||
607 | if (child_device->driver) { | 605 | if (child_device->driver) { |
608 | drv = drv_to_hv_drv(child_device->driver); | 606 | drv = drv_to_hv_drv(child_device->driver); |
609 | if (drv->remove) | 607 | if (drv->remove) |
610 | drv->remove(dev); | 608 | drv->remove(dev); |
611 | else { | ||
612 | hv_process_channel_removal(dev->channel, relid); | ||
613 | pr_err("remove not set for driver %s\n", | ||
614 | dev_name(child_device)); | ||
615 | } | ||
616 | } else { | ||
617 | /* | ||
618 | * We don't have a driver for this device; deal with the | ||
619 | * rescind message by removing the channel. | ||
620 | */ | ||
621 | hv_process_channel_removal(dev->channel, relid); | ||
622 | } | 609 | } |
623 | 610 | ||
624 | return 0; | 611 | return 0; |
@@ -653,7 +640,10 @@ static void vmbus_shutdown(struct device *child_device) | |||
653 | static void vmbus_device_release(struct device *device) | 640 | static void vmbus_device_release(struct device *device) |
654 | { | 641 | { |
655 | struct hv_device *hv_dev = device_to_hv_device(device); | 642 | struct hv_device *hv_dev = device_to_hv_device(device); |
643 | struct vmbus_channel *channel = hv_dev->channel; | ||
656 | 644 | ||
645 | hv_process_channel_removal(channel, | ||
646 | channel->offermsg.child_relid); | ||
657 | kfree(hv_dev); | 647 | kfree(hv_dev); |
658 | 648 | ||
659 | } | 649 | } |
@@ -835,10 +825,9 @@ static void vmbus_isr(void) | |||
835 | * Here, we | 825 | * Here, we |
836 | * - initialize the vmbus driver context | 826 | * - initialize the vmbus driver context |
837 | * - invoke the vmbus hv main init routine | 827 | * - invoke the vmbus hv main init routine |
838 | * - get the irq resource | ||
839 | * - retrieve the channel offers | 828 | * - retrieve the channel offers |
840 | */ | 829 | */ |
841 | static int vmbus_bus_init(int irq) | 830 | static int vmbus_bus_init(void) |
842 | { | 831 | { |
843 | int ret; | 832 | int ret; |
844 | 833 | ||
@@ -867,7 +856,7 @@ static int vmbus_bus_init(int irq) | |||
867 | on_each_cpu(hv_synic_init, NULL, 1); | 856 | on_each_cpu(hv_synic_init, NULL, 1); |
868 | ret = vmbus_connect(); | 857 | ret = vmbus_connect(); |
869 | if (ret) | 858 | if (ret) |
870 | goto err_alloc; | 859 | goto err_connect; |
871 | 860 | ||
872 | if (vmbus_proto_version > VERSION_WIN7) | 861 | if (vmbus_proto_version > VERSION_WIN7) |
873 | cpu_hotplug_disable(); | 862 | cpu_hotplug_disable(); |
@@ -885,6 +874,8 @@ static int vmbus_bus_init(int irq) | |||
885 | 874 | ||
886 | return 0; | 875 | return 0; |
887 | 876 | ||
877 | err_connect: | ||
878 | on_each_cpu(hv_synic_cleanup, NULL, 1); | ||
888 | err_alloc: | 879 | err_alloc: |
889 | hv_synic_free(); | 880 | hv_synic_free(); |
890 | hv_remove_vmbus_irq(); | 881 | hv_remove_vmbus_irq(); |
@@ -1031,9 +1022,6 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) | |||
1031 | struct resource **prev_res = NULL; | 1022 | struct resource **prev_res = NULL; |
1032 | 1023 | ||
1033 | switch (res->type) { | 1024 | switch (res->type) { |
1034 | case ACPI_RESOURCE_TYPE_IRQ: | ||
1035 | irq = res->data.irq.interrupts[0]; | ||
1036 | return AE_OK; | ||
1037 | 1025 | ||
1038 | /* | 1026 | /* |
1039 | * "Address" descriptors are for bus windows. Ignore | 1027 | * "Address" descriptors are for bus windows. Ignore |
@@ -1075,12 +1063,28 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) | |||
1075 | new_res->start = start; | 1063 | new_res->start = start; |
1076 | new_res->end = end; | 1064 | new_res->end = end; |
1077 | 1065 | ||
1066 | /* | ||
1067 | * Stick ranges from higher in address space at the front of the list. | ||
1068 | * If two ranges are adjacent, merge them. | ||
1069 | */ | ||
1078 | do { | 1070 | do { |
1079 | if (!*old_res) { | 1071 | if (!*old_res) { |
1080 | *old_res = new_res; | 1072 | *old_res = new_res; |
1081 | break; | 1073 | break; |
1082 | } | 1074 | } |
1083 | 1075 | ||
1076 | if (((*old_res)->end + 1) == new_res->start) { | ||
1077 | (*old_res)->end = new_res->end; | ||
1078 | kfree(new_res); | ||
1079 | break; | ||
1080 | } | ||
1081 | |||
1082 | if ((*old_res)->start == new_res->end + 1) { | ||
1083 | (*old_res)->start = new_res->start; | ||
1084 | kfree(new_res); | ||
1085 | break; | ||
1086 | } | ||
1087 | |||
1084 | if ((*old_res)->end < new_res->start) { | 1088 | if ((*old_res)->end < new_res->start) { |
1085 | new_res->sibling = *old_res; | 1089 | new_res->sibling = *old_res; |
1086 | if (prev_res) | 1090 | if (prev_res) |
@@ -1191,6 +1195,23 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, | |||
1191 | } | 1195 | } |
1192 | EXPORT_SYMBOL_GPL(vmbus_allocate_mmio); | 1196 | EXPORT_SYMBOL_GPL(vmbus_allocate_mmio); |
1193 | 1197 | ||
1198 | /** | ||
1199 | * vmbus_cpu_number_to_vp_number() - Map CPU to VP. | ||
1200 | * @cpu_number: CPU number in Linux terms | ||
1201 | * | ||
1202 | * This function returns the mapping between the Linux processor | ||
1203 | * number and the hypervisor's virtual processor number, useful | ||
1204 | * in making hypercalls and such that talk about specific | ||
1205 | * processors. | ||
1206 | * | ||
1207 | * Return: Virtual processor number in Hyper-V terms | ||
1208 | */ | ||
1209 | int vmbus_cpu_number_to_vp_number(int cpu_number) | ||
1210 | { | ||
1211 | return hv_context.vp_index[cpu_number]; | ||
1212 | } | ||
1213 | EXPORT_SYMBOL_GPL(vmbus_cpu_number_to_vp_number); | ||
1214 | |||
1194 | static int vmbus_acpi_add(struct acpi_device *device) | 1215 | static int vmbus_acpi_add(struct acpi_device *device) |
1195 | { | 1216 | { |
1196 | acpi_status result; | 1217 | acpi_status result; |
@@ -1275,7 +1296,7 @@ static int __init hv_acpi_init(void) | |||
1275 | init_completion(&probe_event); | 1296 | init_completion(&probe_event); |
1276 | 1297 | ||
1277 | /* | 1298 | /* |
1278 | * Get irq resources first. | 1299 | * Get ACPI resources first. |
1279 | */ | 1300 | */ |
1280 | ret = acpi_bus_register_driver(&vmbus_acpi_driver); | 1301 | ret = acpi_bus_register_driver(&vmbus_acpi_driver); |
1281 | 1302 | ||
@@ -1288,12 +1309,7 @@ static int __init hv_acpi_init(void) | |||
1288 | goto cleanup; | 1309 | goto cleanup; |
1289 | } | 1310 | } |
1290 | 1311 | ||
1291 | if (irq <= 0) { | 1312 | ret = vmbus_bus_init(); |
1292 | ret = -ENODEV; | ||
1293 | goto cleanup; | ||
1294 | } | ||
1295 | |||
1296 | ret = vmbus_bus_init(irq); | ||
1297 | if (ret) | 1313 | if (ret) |
1298 | goto cleanup; | 1314 | goto cleanup; |
1299 | 1315 | ||
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 6c8921140f02..c85935f3525a 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig | |||
@@ -8,7 +8,7 @@ menuconfig CORESIGHT | |||
8 | This framework provides a kernel interface for the CoreSight debug | 8 | This framework provides a kernel interface for the CoreSight debug |
9 | and trace drivers to register themselves with. It's intended to build | 9 | and trace drivers to register themselves with. It's intended to build |
10 | a topological view of the CoreSight components based on a DT | 10 | a topological view of the CoreSight components based on a DT |
11 | specification and configure the right serie of components when a | 11 | specification and configure the right series of components when a |
12 | trace source gets enabled. | 12 | trace source gets enabled. |
13 | 13 | ||
14 | if CORESIGHT | 14 | if CORESIGHT |
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index e25492137d8b..93738dfbf631 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c | |||
@@ -548,7 +548,7 @@ static int coresight_name_match(struct device *dev, void *data) | |||
548 | to_match = data; | 548 | to_match = data; |
549 | i_csdev = to_coresight_device(dev); | 549 | i_csdev = to_coresight_device(dev); |
550 | 550 | ||
551 | if (!strcmp(to_match, dev_name(&i_csdev->dev))) | 551 | if (to_match && !strcmp(to_match, dev_name(&i_csdev->dev))) |
552 | return 1; | 552 | return 1; |
553 | 553 | ||
554 | return 0; | 554 | return 0; |
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index e74e5d6e5f9f..c948866edf87 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c | |||
@@ -412,16 +412,6 @@ static int hv_kbd_remove(struct hv_device *hv_dev) | |||
412 | return 0; | 412 | return 0; |
413 | } | 413 | } |
414 | 414 | ||
415 | /* | ||
416 | * Keyboard GUID | ||
417 | * {f912ad6d-2b17-48ea-bd65-f927a61c7684} | ||
418 | */ | ||
419 | #define HV_KBD_GUID \ | ||
420 | .guid = { \ | ||
421 | 0x6d, 0xad, 0x12, 0xf9, 0x17, 0x2b, 0xea, 0x48, \ | ||
422 | 0xbd, 0x65, 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84 \ | ||
423 | } | ||
424 | |||
425 | static const struct hv_vmbus_device_id id_table[] = { | 415 | static const struct hv_vmbus_device_id id_table[] = { |
426 | /* Keyboard guid */ | 416 | /* Keyboard guid */ |
427 | { HV_KBD_GUID, }, | 417 | { HV_KBD_GUID, }, |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index b2f2486b3d75..677d0362f334 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -657,7 +657,9 @@ out: | |||
657 | * @file: pointer to file structure | 657 | * @file: pointer to file structure |
658 | * @band: band bitmap | 658 | * @band: band bitmap |
659 | * | 659 | * |
660 | * Return: poll mask | 660 | * Return: negative on error, |
661 | * 0 if it did no changes, | ||
662 | * and positive a process was added or deleted | ||
661 | */ | 663 | */ |
662 | static int mei_fasync(int fd, struct file *file, int band) | 664 | static int mei_fasync(int fd, struct file *file, int band) |
663 | { | 665 | { |
@@ -665,7 +667,7 @@ static int mei_fasync(int fd, struct file *file, int band) | |||
665 | struct mei_cl *cl = file->private_data; | 667 | struct mei_cl *cl = file->private_data; |
666 | 668 | ||
667 | if (!mei_cl_is_connected(cl)) | 669 | if (!mei_cl_is_connected(cl)) |
668 | return POLLERR; | 670 | return -ENODEV; |
669 | 671 | ||
670 | return fasync_helper(fd, file, band, &cl->ev_async); | 672 | return fasync_helper(fd, file, band, &cl->ev_async); |
671 | } | 673 | } |
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 5ce5ef211bdb..3308427ed9f7 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Parallel-port resource manager code. | 2 | * Parallel-port resource manager code. |
3 | * | 3 | * |
4 | * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> | 4 | * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> |
5 | * Tim Waugh <tim@cyberelk.demon.co.uk> | 5 | * Tim Waugh <tim@cyberelk.demon.co.uk> |
6 | * Jose Renau <renau@acm.org> | 6 | * Jose Renau <renau@acm.org> |
@@ -54,16 +54,16 @@ static LIST_HEAD(drivers); | |||
54 | static DEFINE_MUTEX(registration_lock); | 54 | static DEFINE_MUTEX(registration_lock); |
55 | 55 | ||
56 | /* What you can do to a port that's gone away.. */ | 56 | /* What you can do to a port that's gone away.. */ |
57 | static void dead_write_lines (struct parport *p, unsigned char b){} | 57 | static void dead_write_lines(struct parport *p, unsigned char b){} |
58 | static unsigned char dead_read_lines (struct parport *p) { return 0; } | 58 | static unsigned char dead_read_lines(struct parport *p) { return 0; } |
59 | static unsigned char dead_frob_lines (struct parport *p, unsigned char b, | 59 | static unsigned char dead_frob_lines(struct parport *p, unsigned char b, |
60 | unsigned char c) { return 0; } | 60 | unsigned char c) { return 0; } |
61 | static void dead_onearg (struct parport *p){} | 61 | static void dead_onearg(struct parport *p){} |
62 | static void dead_initstate (struct pardevice *d, struct parport_state *s) { } | 62 | static void dead_initstate(struct pardevice *d, struct parport_state *s) { } |
63 | static void dead_state (struct parport *p, struct parport_state *s) { } | 63 | static void dead_state(struct parport *p, struct parport_state *s) { } |
64 | static size_t dead_write (struct parport *p, const void *b, size_t l, int f) | 64 | static size_t dead_write(struct parport *p, const void *b, size_t l, int f) |
65 | { return 0; } | 65 | { return 0; } |
66 | static size_t dead_read (struct parport *p, void *b, size_t l, int f) | 66 | static size_t dead_read(struct parport *p, void *b, size_t l, int f) |
67 | { return 0; } | 67 | { return 0; } |
68 | static struct parport_operations dead_ops = { | 68 | static struct parport_operations dead_ops = { |
69 | .write_data = dead_write_lines, /* data */ | 69 | .write_data = dead_write_lines, /* data */ |
@@ -93,7 +93,7 @@ static struct parport_operations dead_ops = { | |||
93 | .ecp_write_data = dead_write, /* ecp */ | 93 | .ecp_write_data = dead_write, /* ecp */ |
94 | .ecp_read_data = dead_read, | 94 | .ecp_read_data = dead_read, |
95 | .ecp_write_addr = dead_write, | 95 | .ecp_write_addr = dead_write, |
96 | 96 | ||
97 | .compat_write_data = dead_write, /* compat */ | 97 | .compat_write_data = dead_write, /* compat */ |
98 | .nibble_read_data = dead_read, /* nibble */ | 98 | .nibble_read_data = dead_read, /* nibble */ |
99 | .byte_read_data = dead_read, /* byte */ | 99 | .byte_read_data = dead_read, /* byte */ |
@@ -148,7 +148,7 @@ void parport_bus_exit(void) | |||
148 | /* | 148 | /* |
149 | * iterates through all the drivers registered with the bus and sends the port | 149 | * iterates through all the drivers registered with the bus and sends the port |
150 | * details to the match_port callback of the driver, so that the driver can | 150 | * details to the match_port callback of the driver, so that the driver can |
151 | * know about the new port that just regsitered with the bus and decide if it | 151 | * know about the new port that just registered with the bus and decide if it |
152 | * wants to use this new port. | 152 | * wants to use this new port. |
153 | */ | 153 | */ |
154 | static int driver_check(struct device_driver *dev_drv, void *_port) | 154 | static int driver_check(struct device_driver *dev_drv, void *_port) |
@@ -194,7 +194,7 @@ static void detach_driver_chain(struct parport *port) | |||
194 | struct parport_driver *drv; | 194 | struct parport_driver *drv; |
195 | /* caller has exclusive registration_lock */ | 195 | /* caller has exclusive registration_lock */ |
196 | list_for_each_entry(drv, &drivers, list) | 196 | list_for_each_entry(drv, &drivers, list) |
197 | drv->detach (port); | 197 | drv->detach(port); |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * call the detach function of the drivers registered in | 200 | * call the detach function of the drivers registered in |
@@ -205,11 +205,13 @@ static void detach_driver_chain(struct parport *port) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | /* Ask kmod for some lowlevel drivers. */ | 207 | /* Ask kmod for some lowlevel drivers. */ |
208 | static void get_lowlevel_driver (void) | 208 | static void get_lowlevel_driver(void) |
209 | { | 209 | { |
210 | /* There is no actual module called this: you should set | 210 | /* |
211 | * up an alias for modutils. */ | 211 | * There is no actual module called this: you should set |
212 | request_module ("parport_lowlevel"); | 212 | * up an alias for modutils. |
213 | */ | ||
214 | request_module("parport_lowlevel"); | ||
213 | } | 215 | } |
214 | 216 | ||
215 | /* | 217 | /* |
@@ -265,7 +267,7 @@ int __parport_register_driver(struct parport_driver *drv, struct module *owner, | |||
265 | const char *mod_name) | 267 | const char *mod_name) |
266 | { | 268 | { |
267 | if (list_empty(&portlist)) | 269 | if (list_empty(&portlist)) |
268 | get_lowlevel_driver (); | 270 | get_lowlevel_driver(); |
269 | 271 | ||
270 | if (drv->devmodel) { | 272 | if (drv->devmodel) { |
271 | /* using device model */ | 273 | /* using device model */ |
@@ -328,7 +330,7 @@ static int port_detach(struct device *dev, void *_drv) | |||
328 | * finished by the time this function returns. | 330 | * finished by the time this function returns. |
329 | **/ | 331 | **/ |
330 | 332 | ||
331 | void parport_unregister_driver (struct parport_driver *drv) | 333 | void parport_unregister_driver(struct parport_driver *drv) |
332 | { | 334 | { |
333 | struct parport *port; | 335 | struct parport *port; |
334 | 336 | ||
@@ -343,6 +345,7 @@ void parport_unregister_driver (struct parport_driver *drv) | |||
343 | } | 345 | } |
344 | mutex_unlock(®istration_lock); | 346 | mutex_unlock(®istration_lock); |
345 | } | 347 | } |
348 | EXPORT_SYMBOL(parport_unregister_driver); | ||
346 | 349 | ||
347 | static void free_port(struct device *dev) | 350 | static void free_port(struct device *dev) |
348 | { | 351 | { |
@@ -372,12 +375,13 @@ static void free_port(struct device *dev) | |||
372 | * until the matching parport_put_port() call. | 375 | * until the matching parport_put_port() call. |
373 | **/ | 376 | **/ |
374 | 377 | ||
375 | struct parport *parport_get_port (struct parport *port) | 378 | struct parport *parport_get_port(struct parport *port) |
376 | { | 379 | { |
377 | struct device *dev = get_device(&port->bus_dev); | 380 | struct device *dev = get_device(&port->bus_dev); |
378 | 381 | ||
379 | return to_parport_dev(dev); | 382 | return to_parport_dev(dev); |
380 | } | 383 | } |
384 | EXPORT_SYMBOL(parport_get_port); | ||
381 | 385 | ||
382 | void parport_del_port(struct parport *port) | 386 | void parport_del_port(struct parport *port) |
383 | { | 387 | { |
@@ -394,10 +398,11 @@ EXPORT_SYMBOL(parport_del_port); | |||
394 | * zero (port is no longer used), free_port is called. | 398 | * zero (port is no longer used), free_port is called. |
395 | **/ | 399 | **/ |
396 | 400 | ||
397 | void parport_put_port (struct parport *port) | 401 | void parport_put_port(struct parport *port) |
398 | { | 402 | { |
399 | put_device(&port->bus_dev); | 403 | put_device(&port->bus_dev); |
400 | } | 404 | } |
405 | EXPORT_SYMBOL(parport_put_port); | ||
401 | 406 | ||
402 | /** | 407 | /** |
403 | * parport_register_port - register a parallel port | 408 | * parport_register_port - register a parallel port |
@@ -439,10 +444,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
439 | int ret; | 444 | int ret; |
440 | 445 | ||
441 | tmp = kzalloc(sizeof(struct parport), GFP_KERNEL); | 446 | tmp = kzalloc(sizeof(struct parport), GFP_KERNEL); |
442 | if (!tmp) { | 447 | if (!tmp) |
443 | printk(KERN_WARNING "parport: memory squeeze\n"); | ||
444 | return NULL; | 448 | return NULL; |
445 | } | ||
446 | 449 | ||
447 | /* Init our structure */ | 450 | /* Init our structure */ |
448 | tmp->base = base; | 451 | tmp->base = base; |
@@ -450,12 +453,12 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
450 | tmp->dma = dma; | 453 | tmp->dma = dma; |
451 | tmp->muxport = tmp->daisy = tmp->muxsel = -1; | 454 | tmp->muxport = tmp->daisy = tmp->muxsel = -1; |
452 | tmp->modes = 0; | 455 | tmp->modes = 0; |
453 | INIT_LIST_HEAD(&tmp->list); | 456 | INIT_LIST_HEAD(&tmp->list); |
454 | tmp->devices = tmp->cad = NULL; | 457 | tmp->devices = tmp->cad = NULL; |
455 | tmp->flags = 0; | 458 | tmp->flags = 0; |
456 | tmp->ops = ops; | 459 | tmp->ops = ops; |
457 | tmp->physport = tmp; | 460 | tmp->physport = tmp; |
458 | memset (tmp->probe_info, 0, 5 * sizeof (struct parport_device_info)); | 461 | memset(tmp->probe_info, 0, 5 * sizeof(struct parport_device_info)); |
459 | rwlock_init(&tmp->cad_lock); | 462 | rwlock_init(&tmp->cad_lock); |
460 | spin_lock_init(&tmp->waitlist_lock); | 463 | spin_lock_init(&tmp->waitlist_lock); |
461 | spin_lock_init(&tmp->pardevice_lock); | 464 | spin_lock_init(&tmp->pardevice_lock); |
@@ -463,12 +466,11 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
463 | tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; | 466 | tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; |
464 | sema_init(&tmp->ieee1284.irq, 0); | 467 | sema_init(&tmp->ieee1284.irq, 0); |
465 | tmp->spintime = parport_default_spintime; | 468 | tmp->spintime = parport_default_spintime; |
466 | atomic_set (&tmp->ref_count, 1); | 469 | atomic_set(&tmp->ref_count, 1); |
467 | INIT_LIST_HEAD(&tmp->full_list); | 470 | INIT_LIST_HEAD(&tmp->full_list); |
468 | 471 | ||
469 | name = kmalloc(15, GFP_KERNEL); | 472 | name = kmalloc(15, GFP_KERNEL); |
470 | if (!name) { | 473 | if (!name) { |
471 | printk(KERN_ERR "parport: memory squeeze\n"); | ||
472 | kfree(tmp); | 474 | kfree(tmp); |
473 | return NULL; | 475 | return NULL; |
474 | } | 476 | } |
@@ -508,6 +510,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
508 | 510 | ||
509 | return tmp; | 511 | return tmp; |
510 | } | 512 | } |
513 | EXPORT_SYMBOL(parport_register_port); | ||
511 | 514 | ||
512 | /** | 515 | /** |
513 | * parport_announce_port - tell device drivers about a parallel port | 516 | * parport_announce_port - tell device drivers about a parallel port |
@@ -521,7 +524,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
521 | * functions will be called, with @port as the parameter. | 524 | * functions will be called, with @port as the parameter. |
522 | **/ | 525 | **/ |
523 | 526 | ||
524 | void parport_announce_port (struct parport *port) | 527 | void parport_announce_port(struct parport *port) |
525 | { | 528 | { |
526 | int i; | 529 | int i; |
527 | 530 | ||
@@ -531,9 +534,8 @@ void parport_announce_port (struct parport *port) | |||
531 | #endif | 534 | #endif |
532 | 535 | ||
533 | if (!port->dev) | 536 | if (!port->dev) |
534 | printk(KERN_WARNING "%s: fix this legacy " | 537 | printk(KERN_WARNING "%s: fix this legacy no-device port driver!\n", |
535 | "no-device port driver!\n", | 538 | port->name); |
536 | port->name); | ||
537 | 539 | ||
538 | parport_proc_register(port); | 540 | parport_proc_register(port); |
539 | mutex_lock(®istration_lock); | 541 | mutex_lock(®istration_lock); |
@@ -547,7 +549,7 @@ void parport_announce_port (struct parport *port) | |||
547 | spin_unlock_irq(&parportlist_lock); | 549 | spin_unlock_irq(&parportlist_lock); |
548 | 550 | ||
549 | /* Let drivers know that new port(s) has arrived. */ | 551 | /* Let drivers know that new port(s) has arrived. */ |
550 | attach_driver_chain (port); | 552 | attach_driver_chain(port); |
551 | for (i = 1; i < 3; i++) { | 553 | for (i = 1; i < 3; i++) { |
552 | struct parport *slave = port->slaves[i-1]; | 554 | struct parport *slave = port->slaves[i-1]; |
553 | if (slave) | 555 | if (slave) |
@@ -555,6 +557,7 @@ void parport_announce_port (struct parport *port) | |||
555 | } | 557 | } |
556 | mutex_unlock(®istration_lock); | 558 | mutex_unlock(®istration_lock); |
557 | } | 559 | } |
560 | EXPORT_SYMBOL(parport_announce_port); | ||
558 | 561 | ||
559 | /** | 562 | /** |
560 | * parport_remove_port - deregister a parallel port | 563 | * parport_remove_port - deregister a parallel port |
@@ -582,7 +585,7 @@ void parport_remove_port(struct parport *port) | |||
582 | mutex_lock(®istration_lock); | 585 | mutex_lock(®istration_lock); |
583 | 586 | ||
584 | /* Spread the word. */ | 587 | /* Spread the word. */ |
585 | detach_driver_chain (port); | 588 | detach_driver_chain(port); |
586 | 589 | ||
587 | #ifdef CONFIG_PARPORT_1284 | 590 | #ifdef CONFIG_PARPORT_1284 |
588 | /* Forget the IEEE1284.3 topology of the port. */ | 591 | /* Forget the IEEE1284.3 topology of the port. */ |
@@ -616,6 +619,7 @@ void parport_remove_port(struct parport *port) | |||
616 | parport_put_port(slave); | 619 | parport_put_port(slave); |
617 | } | 620 | } |
618 | } | 621 | } |
622 | EXPORT_SYMBOL(parport_remove_port); | ||
619 | 623 | ||
620 | /** | 624 | /** |
621 | * parport_register_device - register a device on a parallel port | 625 | * parport_register_device - register a device on a parallel port |
@@ -689,14 +693,14 @@ void parport_remove_port(struct parport *port) | |||
689 | struct pardevice * | 693 | struct pardevice * |
690 | parport_register_device(struct parport *port, const char *name, | 694 | parport_register_device(struct parport *port, const char *name, |
691 | int (*pf)(void *), void (*kf)(void *), | 695 | int (*pf)(void *), void (*kf)(void *), |
692 | void (*irq_func)(void *), | 696 | void (*irq_func)(void *), |
693 | int flags, void *handle) | 697 | int flags, void *handle) |
694 | { | 698 | { |
695 | struct pardevice *tmp; | 699 | struct pardevice *tmp; |
696 | 700 | ||
697 | if (port->physport->flags & PARPORT_FLAG_EXCL) { | 701 | if (port->physport->flags & PARPORT_FLAG_EXCL) { |
698 | /* An exclusive device is registered. */ | 702 | /* An exclusive device is registered. */ |
699 | printk (KERN_DEBUG "%s: no more devices allowed\n", | 703 | printk(KERN_DEBUG "%s: no more devices allowed\n", |
700 | port->name); | 704 | port->name); |
701 | return NULL; | 705 | return NULL; |
702 | } | 706 | } |
@@ -722,28 +726,24 @@ parport_register_device(struct parport *port, const char *name, | |||
722 | } | 726 | } |
723 | } | 727 | } |
724 | 728 | ||
725 | /* We up our own module reference count, and that of the port | 729 | /* |
726 | on which a device is to be registered, to ensure that | 730 | * We up our own module reference count, and that of the port |
727 | neither of us gets unloaded while we sleep in (e.g.) | 731 | * on which a device is to be registered, to ensure that |
728 | kmalloc. | 732 | * neither of us gets unloaded while we sleep in (e.g.) |
729 | */ | 733 | * kmalloc. |
730 | if (!try_module_get(port->ops->owner)) { | 734 | */ |
735 | if (!try_module_get(port->ops->owner)) | ||
731 | return NULL; | 736 | return NULL; |
732 | } | 737 | |
733 | 738 | parport_get_port(port); | |
734 | parport_get_port (port); | ||
735 | 739 | ||
736 | tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); | 740 | tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); |
737 | if (tmp == NULL) { | 741 | if (!tmp) |
738 | printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); | ||
739 | goto out; | 742 | goto out; |
740 | } | ||
741 | 743 | ||
742 | tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL); | 744 | tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL); |
743 | if (tmp->state == NULL) { | 745 | if (!tmp->state) |
744 | printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); | ||
745 | goto out_free_pardevice; | 746 | goto out_free_pardevice; |
746 | } | ||
747 | 747 | ||
748 | tmp->name = name; | 748 | tmp->name = name; |
749 | tmp->port = port; | 749 | tmp->port = port; |
@@ -767,19 +767,21 @@ parport_register_device(struct parport *port, const char *name, | |||
767 | 767 | ||
768 | if (flags & PARPORT_DEV_EXCL) { | 768 | if (flags & PARPORT_DEV_EXCL) { |
769 | if (port->physport->devices) { | 769 | if (port->physport->devices) { |
770 | spin_unlock (&port->physport->pardevice_lock); | 770 | spin_unlock(&port->physport->pardevice_lock); |
771 | printk (KERN_DEBUG | 771 | printk(KERN_DEBUG |
772 | "%s: cannot grant exclusive access for " | 772 | "%s: cannot grant exclusive access for device %s\n", |
773 | "device %s\n", port->name, name); | 773 | port->name, name); |
774 | goto out_free_all; | 774 | goto out_free_all; |
775 | } | 775 | } |
776 | port->flags |= PARPORT_FLAG_EXCL; | 776 | port->flags |= PARPORT_FLAG_EXCL; |
777 | } | 777 | } |
778 | 778 | ||
779 | tmp->next = port->physport->devices; | 779 | tmp->next = port->physport->devices; |
780 | wmb(); /* Make sure that tmp->next is written before it's | 780 | wmb(); /* |
781 | added to the list; see comments marked 'no locking | 781 | * Make sure that tmp->next is written before it's |
782 | required' */ | 782 | * added to the list; see comments marked 'no locking |
783 | * required' | ||
784 | */ | ||
783 | if (port->physport->devices) | 785 | if (port->physport->devices) |
784 | port->physport->devices->prev = tmp; | 786 | port->physport->devices->prev = tmp; |
785 | port->physport->devices = tmp; | 787 | port->physport->devices = tmp; |
@@ -805,11 +807,12 @@ parport_register_device(struct parport *port, const char *name, | |||
805 | out_free_pardevice: | 807 | out_free_pardevice: |
806 | kfree(tmp); | 808 | kfree(tmp); |
807 | out: | 809 | out: |
808 | parport_put_port (port); | 810 | parport_put_port(port); |
809 | module_put(port->ops->owner); | 811 | module_put(port->ops->owner); |
810 | 812 | ||
811 | return NULL; | 813 | return NULL; |
812 | } | 814 | } |
815 | EXPORT_SYMBOL(parport_register_device); | ||
813 | 816 | ||
814 | static void free_pardevice(struct device *dev) | 817 | static void free_pardevice(struct device *dev) |
815 | { | 818 | { |
@@ -968,7 +971,7 @@ void parport_unregister_device(struct pardevice *dev) | |||
968 | struct parport *port; | 971 | struct parport *port; |
969 | 972 | ||
970 | #ifdef PARPORT_PARANOID | 973 | #ifdef PARPORT_PARANOID |
971 | if (dev == NULL) { | 974 | if (!dev) { |
972 | printk(KERN_ERR "parport_unregister_device: passed NULL\n"); | 975 | printk(KERN_ERR "parport_unregister_device: passed NULL\n"); |
973 | return; | 976 | return; |
974 | } | 977 | } |
@@ -985,7 +988,7 @@ void parport_unregister_device(struct pardevice *dev) | |||
985 | if (port->cad == dev) { | 988 | if (port->cad == dev) { |
986 | printk(KERN_DEBUG "%s: %s forgot to release port\n", | 989 | printk(KERN_DEBUG "%s: %s forgot to release port\n", |
987 | port->name, dev->name); | 990 | port->name, dev->name); |
988 | parport_release (dev); | 991 | parport_release(dev); |
989 | } | 992 | } |
990 | 993 | ||
991 | spin_lock(&port->pardevice_lock); | 994 | spin_lock(&port->pardevice_lock); |
@@ -1001,8 +1004,10 @@ void parport_unregister_device(struct pardevice *dev) | |||
1001 | 1004 | ||
1002 | spin_unlock(&port->pardevice_lock); | 1005 | spin_unlock(&port->pardevice_lock); |
1003 | 1006 | ||
1004 | /* Make sure we haven't left any pointers around in the wait | 1007 | /* |
1005 | * list. */ | 1008 | * Make sure we haven't left any pointers around in the wait |
1009 | * list. | ||
1010 | */ | ||
1006 | spin_lock_irq(&port->waitlist_lock); | 1011 | spin_lock_irq(&port->waitlist_lock); |
1007 | if (dev->waitprev || dev->waitnext || port->waithead == dev) { | 1012 | if (dev->waitprev || dev->waitnext || port->waithead == dev) { |
1008 | if (dev->waitprev) | 1013 | if (dev->waitprev) |
@@ -1023,8 +1028,9 @@ void parport_unregister_device(struct pardevice *dev) | |||
1023 | kfree(dev); | 1028 | kfree(dev); |
1024 | 1029 | ||
1025 | module_put(port->ops->owner); | 1030 | module_put(port->ops->owner); |
1026 | parport_put_port (port); | 1031 | parport_put_port(port); |
1027 | } | 1032 | } |
1033 | EXPORT_SYMBOL(parport_unregister_device); | ||
1028 | 1034 | ||
1029 | /** | 1035 | /** |
1030 | * parport_find_number - find a parallel port by number | 1036 | * parport_find_number - find a parallel port by number |
@@ -1038,23 +1044,24 @@ void parport_unregister_device(struct pardevice *dev) | |||
1038 | * gives you, use parport_put_port(). | 1044 | * gives you, use parport_put_port(). |
1039 | */ | 1045 | */ |
1040 | 1046 | ||
1041 | struct parport *parport_find_number (int number) | 1047 | struct parport *parport_find_number(int number) |
1042 | { | 1048 | { |
1043 | struct parport *port, *result = NULL; | 1049 | struct parport *port, *result = NULL; |
1044 | 1050 | ||
1045 | if (list_empty(&portlist)) | 1051 | if (list_empty(&portlist)) |
1046 | get_lowlevel_driver (); | 1052 | get_lowlevel_driver(); |
1047 | 1053 | ||
1048 | spin_lock (&parportlist_lock); | 1054 | spin_lock(&parportlist_lock); |
1049 | list_for_each_entry(port, &portlist, list) { | 1055 | list_for_each_entry(port, &portlist, list) { |
1050 | if (port->number == number) { | 1056 | if (port->number == number) { |
1051 | result = parport_get_port (port); | 1057 | result = parport_get_port(port); |
1052 | break; | 1058 | break; |
1053 | } | 1059 | } |
1054 | } | 1060 | } |
1055 | spin_unlock (&parportlist_lock); | 1061 | spin_unlock(&parportlist_lock); |
1056 | return result; | 1062 | return result; |
1057 | } | 1063 | } |
1064 | EXPORT_SYMBOL(parport_find_number); | ||
1058 | 1065 | ||
1059 | /** | 1066 | /** |
1060 | * parport_find_base - find a parallel port by base address | 1067 | * parport_find_base - find a parallel port by base address |
@@ -1068,23 +1075,24 @@ struct parport *parport_find_number (int number) | |||
1068 | * gives you, use parport_put_port(). | 1075 | * gives you, use parport_put_port(). |
1069 | */ | 1076 | */ |
1070 | 1077 | ||
1071 | struct parport *parport_find_base (unsigned long base) | 1078 | struct parport *parport_find_base(unsigned long base) |
1072 | { | 1079 | { |
1073 | struct parport *port, *result = NULL; | 1080 | struct parport *port, *result = NULL; |
1074 | 1081 | ||
1075 | if (list_empty(&portlist)) | 1082 | if (list_empty(&portlist)) |
1076 | get_lowlevel_driver (); | 1083 | get_lowlevel_driver(); |
1077 | 1084 | ||
1078 | spin_lock (&parportlist_lock); | 1085 | spin_lock(&parportlist_lock); |
1079 | list_for_each_entry(port, &portlist, list) { | 1086 | list_for_each_entry(port, &portlist, list) { |
1080 | if (port->base == base) { | 1087 | if (port->base == base) { |
1081 | result = parport_get_port (port); | 1088 | result = parport_get_port(port); |
1082 | break; | 1089 | break; |
1083 | } | 1090 | } |
1084 | } | 1091 | } |
1085 | spin_unlock (&parportlist_lock); | 1092 | spin_unlock(&parportlist_lock); |
1086 | return result; | 1093 | return result; |
1087 | } | 1094 | } |
1095 | EXPORT_SYMBOL(parport_find_base); | ||
1088 | 1096 | ||
1089 | /** | 1097 | /** |
1090 | * parport_claim - claim access to a parallel port device | 1098 | * parport_claim - claim access to a parallel port device |
@@ -1111,8 +1119,9 @@ int parport_claim(struct pardevice *dev) | |||
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | /* Preempt any current device */ | 1121 | /* Preempt any current device */ |
1114 | write_lock_irqsave (&port->cad_lock, flags); | 1122 | write_lock_irqsave(&port->cad_lock, flags); |
1115 | if ((oldcad = port->cad) != NULL) { | 1123 | oldcad = port->cad; |
1124 | if (oldcad) { | ||
1116 | if (oldcad->preempt) { | 1125 | if (oldcad->preempt) { |
1117 | if (oldcad->preempt(oldcad->private)) | 1126 | if (oldcad->preempt(oldcad->private)) |
1118 | goto blocked; | 1127 | goto blocked; |
@@ -1121,8 +1130,10 @@ int parport_claim(struct pardevice *dev) | |||
1121 | goto blocked; | 1130 | goto blocked; |
1122 | 1131 | ||
1123 | if (port->cad != oldcad) { | 1132 | if (port->cad != oldcad) { |
1124 | /* I think we'll actually deadlock rather than | 1133 | /* |
1125 | get here, but just in case.. */ | 1134 | * I think we'll actually deadlock rather than |
1135 | * get here, but just in case.. | ||
1136 | */ | ||
1126 | printk(KERN_WARNING | 1137 | printk(KERN_WARNING |
1127 | "%s: %s released port when preempted!\n", | 1138 | "%s: %s released port when preempted!\n", |
1128 | port->name, oldcad->name); | 1139 | port->name, oldcad->name); |
@@ -1136,7 +1147,7 @@ int parport_claim(struct pardevice *dev) | |||
1136 | dev->waiting = 0; | 1147 | dev->waiting = 0; |
1137 | 1148 | ||
1138 | /* Take ourselves out of the wait list again. */ | 1149 | /* Take ourselves out of the wait list again. */ |
1139 | spin_lock_irq (&port->waitlist_lock); | 1150 | spin_lock_irq(&port->waitlist_lock); |
1140 | if (dev->waitprev) | 1151 | if (dev->waitprev) |
1141 | dev->waitprev->waitnext = dev->waitnext; | 1152 | dev->waitprev->waitnext = dev->waitnext; |
1142 | else | 1153 | else |
@@ -1145,7 +1156,7 @@ int parport_claim(struct pardevice *dev) | |||
1145 | dev->waitnext->waitprev = dev->waitprev; | 1156 | dev->waitnext->waitprev = dev->waitprev; |
1146 | else | 1157 | else |
1147 | port->waittail = dev->waitprev; | 1158 | port->waittail = dev->waitprev; |
1148 | spin_unlock_irq (&port->waitlist_lock); | 1159 | spin_unlock_irq(&port->waitlist_lock); |
1149 | dev->waitprev = dev->waitnext = NULL; | 1160 | dev->waitprev = dev->waitnext = NULL; |
1150 | } | 1161 | } |
1151 | 1162 | ||
@@ -1162,7 +1173,7 @@ int parport_claim(struct pardevice *dev) | |||
1162 | /* If it's a daisy chain device, select it. */ | 1173 | /* If it's a daisy chain device, select it. */ |
1163 | if (dev->daisy >= 0) { | 1174 | if (dev->daisy >= 0) { |
1164 | /* This could be lazier. */ | 1175 | /* This could be lazier. */ |
1165 | if (!parport_daisy_select (port, dev->daisy, | 1176 | if (!parport_daisy_select(port, dev->daisy, |
1166 | IEEE1284_MODE_COMPAT)) | 1177 | IEEE1284_MODE_COMPAT)) |
1167 | port->daisy = dev->daisy; | 1178 | port->daisy = dev->daisy; |
1168 | } | 1179 | } |
@@ -1175,13 +1186,15 @@ int parport_claim(struct pardevice *dev) | |||
1175 | return 0; | 1186 | return 0; |
1176 | 1187 | ||
1177 | blocked: | 1188 | blocked: |
1178 | /* If this is the first time we tried to claim the port, register an | 1189 | /* |
1179 | interest. This is only allowed for devices sleeping in | 1190 | * If this is the first time we tried to claim the port, register an |
1180 | parport_claim_or_block(), or those with a wakeup function. */ | 1191 | * interest. This is only allowed for devices sleeping in |
1192 | * parport_claim_or_block(), or those with a wakeup function. | ||
1193 | */ | ||
1181 | 1194 | ||
1182 | /* The cad_lock is still held for writing here */ | 1195 | /* The cad_lock is still held for writing here */ |
1183 | if (dev->waiting & 2 || dev->wakeup) { | 1196 | if (dev->waiting & 2 || dev->wakeup) { |
1184 | spin_lock (&port->waitlist_lock); | 1197 | spin_lock(&port->waitlist_lock); |
1185 | if (test_and_set_bit(0, &dev->waiting) == 0) { | 1198 | if (test_and_set_bit(0, &dev->waiting) == 0) { |
1186 | /* First add ourselves to the end of the wait list. */ | 1199 | /* First add ourselves to the end of the wait list. */ |
1187 | dev->waitnext = NULL; | 1200 | dev->waitnext = NULL; |
@@ -1192,11 +1205,12 @@ blocked: | |||
1192 | } else | 1205 | } else |
1193 | port->waithead = port->waittail = dev; | 1206 | port->waithead = port->waittail = dev; |
1194 | } | 1207 | } |
1195 | spin_unlock (&port->waitlist_lock); | 1208 | spin_unlock(&port->waitlist_lock); |
1196 | } | 1209 | } |
1197 | write_unlock_irqrestore (&port->cad_lock, flags); | 1210 | write_unlock_irqrestore(&port->cad_lock, flags); |
1198 | return -EAGAIN; | 1211 | return -EAGAIN; |
1199 | } | 1212 | } |
1213 | EXPORT_SYMBOL(parport_claim); | ||
1200 | 1214 | ||
1201 | /** | 1215 | /** |
1202 | * parport_claim_or_block - claim access to a parallel port device | 1216 | * parport_claim_or_block - claim access to a parallel port device |
@@ -1212,8 +1226,10 @@ int parport_claim_or_block(struct pardevice *dev) | |||
1212 | { | 1226 | { |
1213 | int r; | 1227 | int r; |
1214 | 1228 | ||
1215 | /* Signal to parport_claim() that we can wait even without a | 1229 | /* |
1216 | wakeup function. */ | 1230 | * Signal to parport_claim() that we can wait even without a |
1231 | * wakeup function. | ||
1232 | */ | ||
1217 | dev->waiting = 2; | 1233 | dev->waiting = 2; |
1218 | 1234 | ||
1219 | /* Try to claim the port. If this fails, we need to sleep. */ | 1235 | /* Try to claim the port. If this fails, we need to sleep. */ |
@@ -1231,14 +1247,15 @@ int parport_claim_or_block(struct pardevice *dev) | |||
1231 | * See also parport_release() | 1247 | * See also parport_release() |
1232 | */ | 1248 | */ |
1233 | 1249 | ||
1234 | /* If dev->waiting is clear now, an interrupt | 1250 | /* |
1235 | gave us the port and we would deadlock if we slept. */ | 1251 | * If dev->waiting is clear now, an interrupt |
1252 | * gave us the port and we would deadlock if we slept. | ||
1253 | */ | ||
1236 | if (dev->waiting) { | 1254 | if (dev->waiting) { |
1237 | wait_event_interruptible(dev->wait_q, | 1255 | wait_event_interruptible(dev->wait_q, |
1238 | !dev->waiting); | 1256 | !dev->waiting); |
1239 | if (signal_pending (current)) { | 1257 | if (signal_pending(current)) |
1240 | return -EINTR; | 1258 | return -EINTR; |
1241 | } | ||
1242 | r = 1; | 1259 | r = 1; |
1243 | } else { | 1260 | } else { |
1244 | r = 0; | 1261 | r = 0; |
@@ -1250,15 +1267,15 @@ int parport_claim_or_block(struct pardevice *dev) | |||
1250 | 1267 | ||
1251 | #ifdef PARPORT_DEBUG_SHARING | 1268 | #ifdef PARPORT_DEBUG_SHARING |
1252 | if (dev->port->physport->cad != dev) | 1269 | if (dev->port->physport->cad != dev) |
1253 | printk(KERN_DEBUG "%s: exiting parport_claim_or_block " | 1270 | printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n", |
1254 | "but %s owns port!\n", dev->name, | 1271 | dev->name, dev->port->physport->cad ? |
1255 | dev->port->physport->cad ? | ||
1256 | dev->port->physport->cad->name:"nobody"); | 1272 | dev->port->physport->cad->name:"nobody"); |
1257 | #endif | 1273 | #endif |
1258 | } | 1274 | } |
1259 | dev->waiting = 0; | 1275 | dev->waiting = 0; |
1260 | return r; | 1276 | return r; |
1261 | } | 1277 | } |
1278 | EXPORT_SYMBOL(parport_claim_or_block); | ||
1262 | 1279 | ||
1263 | /** | 1280 | /** |
1264 | * parport_release - give up access to a parallel port device | 1281 | * parport_release - give up access to a parallel port device |
@@ -1278,9 +1295,9 @@ void parport_release(struct pardevice *dev) | |||
1278 | /* Make sure that dev is the current device */ | 1295 | /* Make sure that dev is the current device */ |
1279 | write_lock_irqsave(&port->cad_lock, flags); | 1296 | write_lock_irqsave(&port->cad_lock, flags); |
1280 | if (port->cad != dev) { | 1297 | if (port->cad != dev) { |
1281 | write_unlock_irqrestore (&port->cad_lock, flags); | 1298 | write_unlock_irqrestore(&port->cad_lock, flags); |
1282 | printk(KERN_WARNING "%s: %s tried to release parport " | 1299 | printk(KERN_WARNING "%s: %s tried to release parport when not owner\n", |
1283 | "when not owner\n", port->name, dev->name); | 1300 | port->name, dev->name); |
1284 | return; | 1301 | return; |
1285 | } | 1302 | } |
1286 | 1303 | ||
@@ -1293,7 +1310,7 @@ void parport_release(struct pardevice *dev) | |||
1293 | 1310 | ||
1294 | /* If this is a daisy device, deselect it. */ | 1311 | /* If this is a daisy device, deselect it. */ |
1295 | if (dev->daisy >= 0) { | 1312 | if (dev->daisy >= 0) { |
1296 | parport_daisy_deselect_all (port); | 1313 | parport_daisy_deselect_all(port); |
1297 | port->daisy = -1; | 1314 | port->daisy = -1; |
1298 | } | 1315 | } |
1299 | #endif | 1316 | #endif |
@@ -1304,8 +1321,10 @@ void parport_release(struct pardevice *dev) | |||
1304 | /* Save control registers */ | 1321 | /* Save control registers */ |
1305 | port->ops->save_state(port, dev->state); | 1322 | port->ops->save_state(port, dev->state); |
1306 | 1323 | ||
1307 | /* If anybody is waiting, find out who's been there longest and | 1324 | /* |
1308 | then wake them up. (Note: no locking required) */ | 1325 | * If anybody is waiting, find out who's been there longest and |
1326 | * then wake them up. (Note: no locking required) | ||
1327 | */ | ||
1309 | /* !!! LOCKING IS NEEDED HERE */ | 1328 | /* !!! LOCKING IS NEEDED HERE */ |
1310 | for (pd = port->waithead; pd; pd = pd->waitnext) { | 1329 | for (pd = port->waithead; pd; pd = pd->waitnext) { |
1311 | if (pd->waiting & 2) { /* sleeping in claim_or_block */ | 1330 | if (pd->waiting & 2) { /* sleeping in claim_or_block */ |
@@ -1322,14 +1341,17 @@ void parport_release(struct pardevice *dev) | |||
1322 | } | 1341 | } |
1323 | } | 1342 | } |
1324 | 1343 | ||
1325 | /* Nobody was waiting, so walk the list to see if anyone is | 1344 | /* |
1326 | interested in being woken up. (Note: no locking required) */ | 1345 | * Nobody was waiting, so walk the list to see if anyone is |
1346 | * interested in being woken up. (Note: no locking required) | ||
1347 | */ | ||
1327 | /* !!! LOCKING IS NEEDED HERE */ | 1348 | /* !!! LOCKING IS NEEDED HERE */ |
1328 | for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) { | 1349 | for (pd = port->devices; !port->cad && pd; pd = pd->next) { |
1329 | if (pd->wakeup && pd != dev) | 1350 | if (pd->wakeup && pd != dev) |
1330 | pd->wakeup(pd->private); | 1351 | pd->wakeup(pd->private); |
1331 | } | 1352 | } |
1332 | } | 1353 | } |
1354 | EXPORT_SYMBOL(parport_release); | ||
1333 | 1355 | ||
1334 | irqreturn_t parport_irq_handler(int irq, void *dev_id) | 1356 | irqreturn_t parport_irq_handler(int irq, void *dev_id) |
1335 | { | 1357 | { |
@@ -1339,22 +1361,6 @@ irqreturn_t parport_irq_handler(int irq, void *dev_id) | |||
1339 | 1361 | ||
1340 | return IRQ_HANDLED; | 1362 | return IRQ_HANDLED; |
1341 | } | 1363 | } |
1342 | |||
1343 | /* Exported symbols for modules. */ | ||
1344 | |||
1345 | EXPORT_SYMBOL(parport_claim); | ||
1346 | EXPORT_SYMBOL(parport_claim_or_block); | ||
1347 | EXPORT_SYMBOL(parport_release); | ||
1348 | EXPORT_SYMBOL(parport_register_port); | ||
1349 | EXPORT_SYMBOL(parport_announce_port); | ||
1350 | EXPORT_SYMBOL(parport_remove_port); | ||
1351 | EXPORT_SYMBOL(parport_unregister_driver); | ||
1352 | EXPORT_SYMBOL(parport_register_device); | ||
1353 | EXPORT_SYMBOL(parport_unregister_device); | ||
1354 | EXPORT_SYMBOL(parport_get_port); | ||
1355 | EXPORT_SYMBOL(parport_put_port); | ||
1356 | EXPORT_SYMBOL(parport_find_number); | ||
1357 | EXPORT_SYMBOL(parport_find_base); | ||
1358 | EXPORT_SYMBOL(parport_irq_handler); | 1364 | EXPORT_SYMBOL(parport_irq_handler); |
1359 | 1365 | ||
1360 | MODULE_LICENSE("GPL"); | 1366 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 8fdc17b84739..753dbad0bf94 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -141,8 +141,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, | |||
141 | { | 141 | { |
142 | u32 read_loc, write_loc, dsize; | 142 | u32 read_loc, write_loc, dsize; |
143 | 143 | ||
144 | smp_read_barrier_depends(); | ||
145 | |||
146 | /* Capture the read/write indices before they changed */ | 144 | /* Capture the read/write indices before they changed */ |
147 | read_loc = rbi->ring_buffer->read_index; | 145 | read_loc = rbi->ring_buffer->read_index; |
148 | write_loc = rbi->ring_buffer->write_index; | 146 | write_loc = rbi->ring_buffer->write_index; |
@@ -630,6 +628,11 @@ struct hv_input_signal_event_buffer { | |||
630 | struct hv_input_signal_event event; | 628 | struct hv_input_signal_event event; |
631 | }; | 629 | }; |
632 | 630 | ||
631 | enum hv_signal_policy { | ||
632 | HV_SIGNAL_POLICY_DEFAULT = 0, | ||
633 | HV_SIGNAL_POLICY_EXPLICIT, | ||
634 | }; | ||
635 | |||
633 | struct vmbus_channel { | 636 | struct vmbus_channel { |
634 | /* Unique channel id */ | 637 | /* Unique channel id */ |
635 | int id; | 638 | int id; |
@@ -757,8 +760,21 @@ struct vmbus_channel { | |||
757 | * link up channels based on their CPU affinity. | 760 | * link up channels based on their CPU affinity. |
758 | */ | 761 | */ |
759 | struct list_head percpu_list; | 762 | struct list_head percpu_list; |
763 | /* | ||
764 | * Host signaling policy: The default policy will be | ||
765 | * based on the ring buffer state. We will also support | ||
766 | * a policy where the client driver can have explicit | ||
767 | * signaling control. | ||
768 | */ | ||
769 | enum hv_signal_policy signal_policy; | ||
760 | }; | 770 | }; |
761 | 771 | ||
772 | static inline void set_channel_signal_state(struct vmbus_channel *c, | ||
773 | enum hv_signal_policy policy) | ||
774 | { | ||
775 | c->signal_policy = policy; | ||
776 | } | ||
777 | |||
762 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) | 778 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) |
763 | { | 779 | { |
764 | c->batched_reading = state; | 780 | c->batched_reading = state; |
@@ -983,16 +999,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, | |||
983 | resource_size_t size, resource_size_t align, | 999 | resource_size_t size, resource_size_t align, |
984 | bool fb_overlap_ok); | 1000 | bool fb_overlap_ok); |
985 | 1001 | ||
986 | /** | 1002 | int vmbus_cpu_number_to_vp_number(int cpu_number); |
987 | * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device | 1003 | u64 hv_do_hypercall(u64 control, void *input, void *output); |
988 | * | ||
989 | * This macro is used to create a struct hv_vmbus_device_id that matches a | ||
990 | * specific device. | ||
991 | */ | ||
992 | #define VMBUS_DEVICE(g0, g1, g2, g3, g4, g5, g6, g7, \ | ||
993 | g8, g9, ga, gb, gc, gd, ge, gf) \ | ||
994 | .guid = { g0, g1, g2, g3, g4, g5, g6, g7, \ | ||
995 | g8, g9, ga, gb, gc, gd, ge, gf }, | ||
996 | 1004 | ||
997 | /* | 1005 | /* |
998 | * GUID definitions of various offer types - services offered to the guest. | 1006 | * GUID definitions of various offer types - services offered to the guest. |
@@ -1003,118 +1011,102 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, | |||
1003 | * {f8615163-df3e-46c5-913f-f2d2f965ed0e} | 1011 | * {f8615163-df3e-46c5-913f-f2d2f965ed0e} |
1004 | */ | 1012 | */ |
1005 | #define HV_NIC_GUID \ | 1013 | #define HV_NIC_GUID \ |
1006 | .guid = { \ | 1014 | .guid = UUID_LE(0xf8615163, 0xdf3e, 0x46c5, 0x91, 0x3f, \ |
1007 | 0x63, 0x51, 0x61, 0xf8, 0x3e, 0xdf, 0xc5, 0x46, \ | 1015 | 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e) |
1008 | 0x91, 0x3f, 0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e \ | ||
1009 | } | ||
1010 | 1016 | ||
1011 | /* | 1017 | /* |
1012 | * IDE GUID | 1018 | * IDE GUID |
1013 | * {32412632-86cb-44a2-9b5c-50d1417354f5} | 1019 | * {32412632-86cb-44a2-9b5c-50d1417354f5} |
1014 | */ | 1020 | */ |
1015 | #define HV_IDE_GUID \ | 1021 | #define HV_IDE_GUID \ |
1016 | .guid = { \ | 1022 | .guid = UUID_LE(0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, \ |
1017 | 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, \ | 1023 | 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) |
1018 | 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 \ | ||
1019 | } | ||
1020 | 1024 | ||
1021 | /* | 1025 | /* |
1022 | * SCSI GUID | 1026 | * SCSI GUID |
1023 | * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} | 1027 | * {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} |
1024 | */ | 1028 | */ |
1025 | #define HV_SCSI_GUID \ | 1029 | #define HV_SCSI_GUID \ |
1026 | .guid = { \ | 1030 | .guid = UUID_LE(0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, \ |
1027 | 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, \ | 1031 | 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) |
1028 | 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f \ | ||
1029 | } | ||
1030 | 1032 | ||
1031 | /* | 1033 | /* |
1032 | * Shutdown GUID | 1034 | * Shutdown GUID |
1033 | * {0e0b6031-5213-4934-818b-38d90ced39db} | 1035 | * {0e0b6031-5213-4934-818b-38d90ced39db} |
1034 | */ | 1036 | */ |
1035 | #define HV_SHUTDOWN_GUID \ | 1037 | #define HV_SHUTDOWN_GUID \ |
1036 | .guid = { \ | 1038 | .guid = UUID_LE(0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8b, \ |
1037 | 0x31, 0x60, 0x0b, 0x0e, 0x13, 0x52, 0x34, 0x49, \ | 1039 | 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb) |
1038 | 0x81, 0x8b, 0x38, 0xd9, 0x0c, 0xed, 0x39, 0xdb \ | ||
1039 | } | ||
1040 | 1040 | ||
1041 | /* | 1041 | /* |
1042 | * Time Synch GUID | 1042 | * Time Synch GUID |
1043 | * {9527E630-D0AE-497b-ADCE-E80AB0175CAF} | 1043 | * {9527E630-D0AE-497b-ADCE-E80AB0175CAF} |
1044 | */ | 1044 | */ |
1045 | #define HV_TS_GUID \ | 1045 | #define HV_TS_GUID \ |
1046 | .guid = { \ | 1046 | .guid = UUID_LE(0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, \ |
1047 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, \ | 1047 | 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) |
1048 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf \ | ||
1049 | } | ||
1050 | 1048 | ||
1051 | /* | 1049 | /* |
1052 | * Heartbeat GUID | 1050 | * Heartbeat GUID |
1053 | * {57164f39-9115-4e78-ab55-382f3bd5422d} | 1051 | * {57164f39-9115-4e78-ab55-382f3bd5422d} |
1054 | */ | 1052 | */ |
1055 | #define HV_HEART_BEAT_GUID \ | 1053 | #define HV_HEART_BEAT_GUID \ |
1056 | .guid = { \ | 1054 | .guid = UUID_LE(0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, \ |
1057 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, \ | 1055 | 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) |
1058 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d \ | ||
1059 | } | ||
1060 | 1056 | ||
1061 | /* | 1057 | /* |
1062 | * KVP GUID | 1058 | * KVP GUID |
1063 | * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6} | 1059 | * {a9a0f4e7-5a45-4d96-b827-8a841e8c03e6} |
1064 | */ | 1060 | */ |
1065 | #define HV_KVP_GUID \ | 1061 | #define HV_KVP_GUID \ |
1066 | .guid = { \ | 1062 | .guid = UUID_LE(0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, \ |
1067 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, \ | 1063 | 0x8a, 0x84, 0x1e, 0x8c, 0x03, 0xe6) |
1068 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 \ | ||
1069 | } | ||
1070 | 1064 | ||
1071 | /* | 1065 | /* |
1072 | * Dynamic memory GUID | 1066 | * Dynamic memory GUID |
1073 | * {525074dc-8985-46e2-8057-a307dc18a502} | 1067 | * {525074dc-8985-46e2-8057-a307dc18a502} |
1074 | */ | 1068 | */ |
1075 | #define HV_DM_GUID \ | 1069 | #define HV_DM_GUID \ |
1076 | .guid = { \ | 1070 | .guid = UUID_LE(0x525074dc, 0x8985, 0x46e2, 0x80, 0x57, \ |
1077 | 0xdc, 0x74, 0x50, 0X52, 0x85, 0x89, 0xe2, 0x46, \ | 1071 | 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02) |
1078 | 0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02 \ | ||
1079 | } | ||
1080 | 1072 | ||
1081 | /* | 1073 | /* |
1082 | * Mouse GUID | 1074 | * Mouse GUID |
1083 | * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a} | 1075 | * {cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a} |
1084 | */ | 1076 | */ |
1085 | #define HV_MOUSE_GUID \ | 1077 | #define HV_MOUSE_GUID \ |
1086 | .guid = { \ | 1078 | .guid = UUID_LE(0xcfa8b69e, 0x5b4a, 0x4cc0, 0xb9, 0x8b, \ |
1087 | 0x9e, 0xb6, 0xa8, 0xcf, 0x4a, 0x5b, 0xc0, 0x4c, \ | 1079 | 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a) |
1088 | 0xb9, 0x8b, 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a \ | 1080 | |
1089 | } | 1081 | /* |
1082 | * Keyboard GUID | ||
1083 | * {f912ad6d-2b17-48ea-bd65-f927a61c7684} | ||
1084 | */ | ||
1085 | #define HV_KBD_GUID \ | ||
1086 | .guid = UUID_LE(0xf912ad6d, 0x2b17, 0x48ea, 0xbd, 0x65, \ | ||
1087 | 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84) | ||
1090 | 1088 | ||
1091 | /* | 1089 | /* |
1092 | * VSS (Backup/Restore) GUID | 1090 | * VSS (Backup/Restore) GUID |
1093 | */ | 1091 | */ |
1094 | #define HV_VSS_GUID \ | 1092 | #define HV_VSS_GUID \ |
1095 | .guid = { \ | 1093 | .guid = UUID_LE(0x35fa2e29, 0xea23, 0x4236, 0x96, 0xae, \ |
1096 | 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42, \ | 1094 | 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40) |
1097 | 0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40 \ | ||
1098 | } | ||
1099 | /* | 1095 | /* |
1100 | * Synthetic Video GUID | 1096 | * Synthetic Video GUID |
1101 | * {DA0A7802-E377-4aac-8E77-0558EB1073F8} | 1097 | * {DA0A7802-E377-4aac-8E77-0558EB1073F8} |
1102 | */ | 1098 | */ |
1103 | #define HV_SYNTHVID_GUID \ | 1099 | #define HV_SYNTHVID_GUID \ |
1104 | .guid = { \ | 1100 | .guid = UUID_LE(0xda0a7802, 0xe377, 0x4aac, 0x8e, 0x77, \ |
1105 | 0x02, 0x78, 0x0a, 0xda, 0x77, 0xe3, 0xac, 0x4a, \ | 1101 | 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8) |
1106 | 0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \ | ||
1107 | } | ||
1108 | 1102 | ||
1109 | /* | 1103 | /* |
1110 | * Synthetic FC GUID | 1104 | * Synthetic FC GUID |
1111 | * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda} | 1105 | * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda} |
1112 | */ | 1106 | */ |
1113 | #define HV_SYNTHFC_GUID \ | 1107 | #define HV_SYNTHFC_GUID \ |
1114 | .guid = { \ | 1108 | .guid = UUID_LE(0x2f9bcc4a, 0x0069, 0x4af3, 0xb7, 0x6b, \ |
1115 | 0x4A, 0xCC, 0x9B, 0x2F, 0x69, 0x00, 0xF3, 0x4A, \ | 1109 | 0x6f, 0xd0, 0xbe, 0x52, 0x8c, 0xda) |
1116 | 0xB7, 0x6B, 0x6F, 0xD0, 0xBE, 0x52, 0x8C, 0xDA \ | ||
1117 | } | ||
1118 | 1110 | ||
1119 | /* | 1111 | /* |
1120 | * Guest File Copy Service | 1112 | * Guest File Copy Service |
@@ -1122,20 +1114,25 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, | |||
1122 | */ | 1114 | */ |
1123 | 1115 | ||
1124 | #define HV_FCOPY_GUID \ | 1116 | #define HV_FCOPY_GUID \ |
1125 | .guid = { \ | 1117 | .guid = UUID_LE(0x34d14be3, 0xdee4, 0x41c8, 0x9a, 0xe7, \ |
1126 | 0xE3, 0x4B, 0xD1, 0x34, 0xE4, 0xDE, 0xC8, 0x41, \ | 1118 | 0x6b, 0x17, 0x49, 0x77, 0xc1, 0x92) |
1127 | 0x9A, 0xE7, 0x6B, 0x17, 0x49, 0x77, 0xC1, 0x92 \ | ||
1128 | } | ||
1129 | 1119 | ||
1130 | /* | 1120 | /* |
1131 | * NetworkDirect. This is the guest RDMA service. | 1121 | * NetworkDirect. This is the guest RDMA service. |
1132 | * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501} | 1122 | * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501} |
1133 | */ | 1123 | */ |
1134 | #define HV_ND_GUID \ | 1124 | #define HV_ND_GUID \ |
1135 | .guid = { \ | 1125 | .guid = UUID_LE(0x8c2eaf3d, 0x32a7, 0x4b09, 0xab, 0x99, \ |
1136 | 0x3d, 0xaf, 0x2e, 0x8c, 0xa7, 0x32, 0x09, 0x4b, \ | 1126 | 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01) |
1137 | 0xab, 0x99, 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01 \ | 1127 | |
1138 | } | 1128 | /* |
1129 | * PCI Express Pass Through | ||
1130 | * {44C4F61D-4444-4400-9D52-802E27EDE19F} | ||
1131 | */ | ||
1132 | |||
1133 | #define HV_PCIE_GUID \ | ||
1134 | .guid = UUID_LE(0x44c4f61d, 0x4444, 0x4400, 0x9d, 0x52, \ | ||
1135 | 0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f) | ||
1139 | 1136 | ||
1140 | /* | 1137 | /* |
1141 | * Common header for Hyper-V ICs | 1138 | * Common header for Hyper-V ICs |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 64f36e09a790..6e4c645e1c0d 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -404,7 +404,7 @@ struct virtio_device_id { | |||
404 | * For Hyper-V devices we use the device guid as the id. | 404 | * For Hyper-V devices we use the device guid as the id. |
405 | */ | 405 | */ |
406 | struct hv_vmbus_device_id { | 406 | struct hv_vmbus_device_id { |
407 | __u8 guid[16]; | 407 | uuid_le guid; |
408 | kernel_ulong_t driver_data; /* Data private to the driver */ | 408 | kernel_ulong_t driver_data; /* Data private to the driver */ |
409 | }; | 409 | }; |
410 | 410 | ||
diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index e4c0a35d6417..e347b24ef9fb 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h | |||
@@ -313,6 +313,7 @@ enum hv_kvp_exchg_pool { | |||
313 | #define HV_INVALIDARG 0x80070057 | 313 | #define HV_INVALIDARG 0x80070057 |
314 | #define HV_GUID_NOTFOUND 0x80041002 | 314 | #define HV_GUID_NOTFOUND 0x80041002 |
315 | #define HV_ERROR_ALREADY_EXISTS 0x80070050 | 315 | #define HV_ERROR_ALREADY_EXISTS 0x80070050 |
316 | #define HV_ERROR_DISK_FULL 0x80070070 | ||
316 | 317 | ||
317 | #define ADDR_FAMILY_NONE 0x00 | 318 | #define ADDR_FAMILY_NONE 0x00 |
318 | #define ADDR_FAMILY_IPV4 0x01 | 319 | #define ADDR_FAMILY_IPV4 0x01 |
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 2f4b7ffd5570..d8f6c094cce5 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py | |||
@@ -8,11 +8,14 @@ | |||
8 | # Licensed under the terms of the GNU GPL License version 2 | 8 | # Licensed under the terms of the GNU GPL License version 2 |
9 | 9 | ||
10 | 10 | ||
11 | import difflib | ||
11 | import os | 12 | import os |
12 | import re | 13 | import re |
14 | import signal | ||
13 | import sys | 15 | import sys |
14 | from subprocess import Popen, PIPE, STDOUT | 16 | from multiprocessing import Pool, cpu_count |
15 | from optparse import OptionParser | 17 | from optparse import OptionParser |
18 | from subprocess import Popen, PIPE, STDOUT | ||
16 | 19 | ||
17 | 20 | ||
18 | # regex expressions | 21 | # regex expressions |
@@ -26,7 +29,7 @@ SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" | |||
26 | 29 | ||
27 | # regex objects | 30 | # regex objects |
28 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") | 31 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") |
29 | REGEX_FEATURE = re.compile(r'(?!\B"[^"]*)' + FEATURE + r'(?![^"]*"\B)') | 32 | REGEX_FEATURE = re.compile(r'(?!\B)' + FEATURE + r'(?!\B)') |
30 | REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) | 33 | REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) |
31 | REGEX_KCONFIG_DEF = re.compile(DEF) | 34 | REGEX_KCONFIG_DEF = re.compile(DEF) |
32 | REGEX_KCONFIG_EXPR = re.compile(EXPR) | 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) |
@@ -34,6 +37,7 @@ REGEX_KCONFIG_STMT = re.compile(STMT) | |||
34 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") | 37 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") |
35 | REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") | 38 | REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") |
36 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") | 39 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") |
40 | REGEX_QUOTES = re.compile("(\"(.*?)\")") | ||
37 | 41 | ||
38 | 42 | ||
39 | def parse_options(): | 43 | def parse_options(): |
@@ -71,6 +75,9 @@ def parse_options(): | |||
71 | "the pattern needs to be a Python regex. To " | 75 | "the pattern needs to be a Python regex. To " |
72 | "ignore defconfigs, specify -i '.*defconfig'.") | 76 | "ignore defconfigs, specify -i '.*defconfig'.") |
73 | 77 | ||
78 | parser.add_option('-s', '--sim', dest='sim', action='store', default="", | ||
79 | help="Print a list of maximum 10 string-similar symbols.") | ||
80 | |||
74 | parser.add_option('', '--force', dest='force', action='store_true', | 81 | parser.add_option('', '--force', dest='force', action='store_true', |
75 | default=False, | 82 | default=False, |
76 | help="Reset current Git tree even when it's dirty.") | 83 | help="Reset current Git tree even when it's dirty.") |
@@ -109,6 +116,18 @@ def main(): | |||
109 | """Main function of this module.""" | 116 | """Main function of this module.""" |
110 | opts = parse_options() | 117 | opts = parse_options() |
111 | 118 | ||
119 | if opts.sim and not opts.commit and not opts.diff: | ||
120 | sims = find_sims(opts.sim, opts.ignore) | ||
121 | if sims: | ||
122 | print "%s: %s" % (yel("Similar symbols"), ', '.join(sims)) | ||
123 | else: | ||
124 | print "%s: no similar symbols found" % yel("Similar symbols") | ||
125 | sys.exit(0) | ||
126 | |||
127 | # dictionary of (un)defined symbols | ||
128 | defined = {} | ||
129 | undefined = {} | ||
130 | |||
112 | if opts.commit or opts.diff: | 131 | if opts.commit or opts.diff: |
113 | head = get_head() | 132 | head = get_head() |
114 | 133 | ||
@@ -127,40 +146,56 @@ def main(): | |||
127 | 146 | ||
128 | # get undefined items before the commit | 147 | # get undefined items before the commit |
129 | execute("git reset --hard %s" % commit_a) | 148 | execute("git reset --hard %s" % commit_a) |
130 | undefined_a = check_symbols(opts.ignore) | 149 | undefined_a, _ = check_symbols(opts.ignore) |
131 | 150 | ||
132 | # get undefined items for the commit | 151 | # get undefined items for the commit |
133 | execute("git reset --hard %s" % commit_b) | 152 | execute("git reset --hard %s" % commit_b) |
134 | undefined_b = check_symbols(opts.ignore) | 153 | undefined_b, defined = check_symbols(opts.ignore) |
135 | 154 | ||
136 | # report cases that are present for the commit but not before | 155 | # report cases that are present for the commit but not before |
137 | for feature in sorted(undefined_b): | 156 | for feature in sorted(undefined_b): |
138 | # feature has not been undefined before | 157 | # feature has not been undefined before |
139 | if not feature in undefined_a: | 158 | if not feature in undefined_a: |
140 | files = sorted(undefined_b.get(feature)) | 159 | files = sorted(undefined_b.get(feature)) |
141 | print "%s\t%s" % (yel(feature), ", ".join(files)) | 160 | undefined[feature] = files |
142 | if opts.find: | ||
143 | commits = find_commits(feature, opts.diff) | ||
144 | print red(commits) | ||
145 | # check if there are new files that reference the undefined feature | 161 | # check if there are new files that reference the undefined feature |
146 | else: | 162 | else: |
147 | files = sorted(undefined_b.get(feature) - | 163 | files = sorted(undefined_b.get(feature) - |
148 | undefined_a.get(feature)) | 164 | undefined_a.get(feature)) |
149 | if files: | 165 | if files: |
150 | print "%s\t%s" % (yel(feature), ", ".join(files)) | 166 | undefined[feature] = files |
151 | if opts.find: | ||
152 | commits = find_commits(feature, opts.diff) | ||
153 | print red(commits) | ||
154 | 167 | ||
155 | # reset to head | 168 | # reset to head |
156 | execute("git reset --hard %s" % head) | 169 | execute("git reset --hard %s" % head) |
157 | 170 | ||
158 | # default to check the entire tree | 171 | # default to check the entire tree |
159 | else: | 172 | else: |
160 | undefined = check_symbols(opts.ignore) | 173 | undefined, defined = check_symbols(opts.ignore) |
161 | for feature in sorted(undefined): | 174 | |
162 | files = sorted(undefined.get(feature)) | 175 | # now print the output |
163 | print "%s\t%s" % (yel(feature), ", ".join(files)) | 176 | for feature in sorted(undefined): |
177 | print red(feature) | ||
178 | |||
179 | files = sorted(undefined.get(feature)) | ||
180 | print "%s: %s" % (yel("Referencing files"), ", ".join(files)) | ||
181 | |||
182 | sims = find_sims(feature, opts.ignore, defined) | ||
183 | sims_out = yel("Similar symbols") | ||
184 | if sims: | ||
185 | print "%s: %s" % (sims_out, ', '.join(sims)) | ||
186 | else: | ||
187 | print "%s: %s" % (sims_out, "no similar symbols found") | ||
188 | |||
189 | if opts.find: | ||
190 | print "%s:" % yel("Commits changing symbol") | ||
191 | commits = find_commits(feature, opts.diff) | ||
192 | if commits: | ||
193 | for commit in commits: | ||
194 | commit = commit.split(" ", 1) | ||
195 | print "\t- %s (\"%s\")" % (yel(commit[0]), commit[1]) | ||
196 | else: | ||
197 | print "\t- no commit found" | ||
198 | print # new line | ||
164 | 199 | ||
165 | 200 | ||
166 | def yel(string): | 201 | def yel(string): |
@@ -190,7 +225,7 @@ def find_commits(symbol, diff): | |||
190 | """Find commits changing %symbol in the given range of %diff.""" | 225 | """Find commits changing %symbol in the given range of %diff.""" |
191 | commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s" | 226 | commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s" |
192 | % (symbol, diff)) | 227 | % (symbol, diff)) |
193 | return commits | 228 | return [x for x in commits.split("\n") if x] |
194 | 229 | ||
195 | 230 | ||
196 | def tree_is_dirty(): | 231 | def tree_is_dirty(): |
@@ -209,43 +244,107 @@ def get_head(): | |||
209 | return stdout.strip('\n') | 244 | return stdout.strip('\n') |
210 | 245 | ||
211 | 246 | ||
212 | def check_symbols(ignore): | 247 | def partition(lst, size): |
213 | """Find undefined Kconfig symbols and return a dict with the symbol as key | 248 | """Partition list @lst into eveni-sized lists of size @size.""" |
214 | and a list of referencing files as value. Files matching %ignore are not | 249 | return [lst[i::size] for i in xrange(size)] |
215 | checked for undefined symbols.""" | 250 | |
216 | source_files = [] | 251 | |
217 | kconfig_files = [] | 252 | def init_worker(): |
218 | defined_features = set() | 253 | """Set signal handler to ignore SIGINT.""" |
219 | referenced_features = dict() # {feature: [files]} | 254 | signal.signal(signal.SIGINT, signal.SIG_IGN) |
255 | |||
256 | |||
257 | def find_sims(symbol, ignore, defined = []): | ||
258 | """Return a list of max. ten Kconfig symbols that are string-similar to | ||
259 | @symbol.""" | ||
260 | if defined: | ||
261 | return sorted(difflib.get_close_matches(symbol, set(defined), 10)) | ||
262 | |||
263 | pool = Pool(cpu_count(), init_worker) | ||
264 | kfiles = [] | ||
265 | for gitfile in get_files(): | ||
266 | if REGEX_FILE_KCONFIG.match(gitfile): | ||
267 | kfiles.append(gitfile) | ||
220 | 268 | ||
269 | arglist = [] | ||
270 | for part in partition(kfiles, cpu_count()): | ||
271 | arglist.append((part, ignore)) | ||
272 | |||
273 | for res in pool.map(parse_kconfig_files, arglist): | ||
274 | defined.extend(res[0]) | ||
275 | |||
276 | return sorted(difflib.get_close_matches(symbol, set(defined), 10)) | ||
277 | |||
278 | |||
279 | def get_files(): | ||
280 | """Return a list of all files in the current git directory.""" | ||
221 | # use 'git ls-files' to get the worklist | 281 | # use 'git ls-files' to get the worklist |
222 | stdout = execute("git ls-files") | 282 | stdout = execute("git ls-files") |
223 | if len(stdout) > 0 and stdout[-1] == "\n": | 283 | if len(stdout) > 0 and stdout[-1] == "\n": |
224 | stdout = stdout[:-1] | 284 | stdout = stdout[:-1] |
225 | 285 | ||
286 | files = [] | ||
226 | for gitfile in stdout.rsplit("\n"): | 287 | for gitfile in stdout.rsplit("\n"): |
227 | if ".git" in gitfile or "ChangeLog" in gitfile or \ | 288 | if ".git" in gitfile or "ChangeLog" in gitfile or \ |
228 | ".log" in gitfile or os.path.isdir(gitfile) or \ | 289 | ".log" in gitfile or os.path.isdir(gitfile) or \ |
229 | gitfile.startswith("tools/"): | 290 | gitfile.startswith("tools/"): |
230 | continue | 291 | continue |
292 | files.append(gitfile) | ||
293 | return files | ||
294 | |||
295 | |||
296 | def check_symbols(ignore): | ||
297 | """Find undefined Kconfig symbols and return a dict with the symbol as key | ||
298 | and a list of referencing files as value. Files matching %ignore are not | ||
299 | checked for undefined symbols.""" | ||
300 | pool = Pool(cpu_count(), init_worker) | ||
301 | try: | ||
302 | return check_symbols_helper(pool, ignore) | ||
303 | except KeyboardInterrupt: | ||
304 | pool.terminate() | ||
305 | pool.join() | ||
306 | sys.exit(1) | ||
307 | |||
308 | |||
309 | def check_symbols_helper(pool, ignore): | ||
310 | """Helper method for check_symbols(). Used to catch keyboard interrupts in | ||
311 | check_symbols() in order to properly terminate running worker processes.""" | ||
312 | source_files = [] | ||
313 | kconfig_files = [] | ||
314 | defined_features = [] | ||
315 | referenced_features = dict() # {file: [features]} | ||
316 | |||
317 | for gitfile in get_files(): | ||
231 | if REGEX_FILE_KCONFIG.match(gitfile): | 318 | if REGEX_FILE_KCONFIG.match(gitfile): |
232 | kconfig_files.append(gitfile) | 319 | kconfig_files.append(gitfile) |
233 | else: | 320 | else: |
234 | # all non-Kconfig files are checked for consistency | 321 | if ignore and not re.match(ignore, gitfile): |
322 | continue | ||
323 | # add source files that do not match the ignore pattern | ||
235 | source_files.append(gitfile) | 324 | source_files.append(gitfile) |
236 | 325 | ||
237 | for sfile in source_files: | 326 | # parse source files |
238 | if ignore and re.match(ignore, sfile): | 327 | arglist = partition(source_files, cpu_count()) |
239 | # do not check files matching %ignore | 328 | for res in pool.map(parse_source_files, arglist): |
240 | continue | 329 | referenced_features.update(res) |
241 | parse_source_file(sfile, referenced_features) | ||
242 | 330 | ||
243 | for kfile in kconfig_files: | 331 | |
244 | if ignore and re.match(ignore, kfile): | 332 | # parse kconfig files |
245 | # do not collect references for files matching %ignore | 333 | arglist = [] |
246 | parse_kconfig_file(kfile, defined_features, dict()) | 334 | for part in partition(kconfig_files, cpu_count()): |
247 | else: | 335 | arglist.append((part, ignore)) |
248 | parse_kconfig_file(kfile, defined_features, referenced_features) | 336 | for res in pool.map(parse_kconfig_files, arglist): |
337 | defined_features.extend(res[0]) | ||
338 | referenced_features.update(res[1]) | ||
339 | defined_features = set(defined_features) | ||
340 | |||
341 | # inverse mapping of referenced_features to dict(feature: [files]) | ||
342 | inv_map = dict() | ||
343 | for _file, features in referenced_features.iteritems(): | ||
344 | for feature in features: | ||
345 | inv_map[feature] = inv_map.get(feature, set()) | ||
346 | inv_map[feature].add(_file) | ||
347 | referenced_features = inv_map | ||
249 | 348 | ||
250 | undefined = {} # {feature: [files]} | 349 | undefined = {} # {feature: [files]} |
251 | for feature in sorted(referenced_features): | 350 | for feature in sorted(referenced_features): |
@@ -259,12 +358,26 @@ def check_symbols(ignore): | |||
259 | if feature[:-len("_MODULE")] in defined_features: | 358 | if feature[:-len("_MODULE")] in defined_features: |
260 | continue | 359 | continue |
261 | undefined[feature] = referenced_features.get(feature) | 360 | undefined[feature] = referenced_features.get(feature) |
262 | return undefined | 361 | return undefined, defined_features |
263 | 362 | ||
264 | 363 | ||
265 | def parse_source_file(sfile, referenced_features): | 364 | def parse_source_files(source_files): |
266 | """Parse @sfile for referenced Kconfig features.""" | 365 | """Parse each source file in @source_files and return dictionary with source |
366 | files as keys and lists of references Kconfig symbols as values.""" | ||
367 | referenced_features = dict() | ||
368 | for sfile in source_files: | ||
369 | referenced_features[sfile] = parse_source_file(sfile) | ||
370 | return referenced_features | ||
371 | |||
372 | |||
373 | def parse_source_file(sfile): | ||
374 | """Parse @sfile and return a list of referenced Kconfig features.""" | ||
267 | lines = [] | 375 | lines = [] |
376 | references = [] | ||
377 | |||
378 | if not os.path.exists(sfile): | ||
379 | return references | ||
380 | |||
268 | with open(sfile, "r") as stream: | 381 | with open(sfile, "r") as stream: |
269 | lines = stream.readlines() | 382 | lines = stream.readlines() |
270 | 383 | ||
@@ -275,9 +388,9 @@ def parse_source_file(sfile, referenced_features): | |||
275 | for feature in features: | 388 | for feature in features: |
276 | if not REGEX_FILTER_FEATURES.search(feature): | 389 | if not REGEX_FILTER_FEATURES.search(feature): |
277 | continue | 390 | continue |
278 | sfiles = referenced_features.get(feature, set()) | 391 | references.append(feature) |
279 | sfiles.add(sfile) | 392 | |
280 | referenced_features[feature] = sfiles | 393 | return references |
281 | 394 | ||
282 | 395 | ||
283 | def get_features_in_line(line): | 396 | def get_features_in_line(line): |
@@ -285,11 +398,35 @@ def get_features_in_line(line): | |||
285 | return REGEX_FEATURE.findall(line) | 398 | return REGEX_FEATURE.findall(line) |
286 | 399 | ||
287 | 400 | ||
288 | def parse_kconfig_file(kfile, defined_features, referenced_features): | 401 | def parse_kconfig_files(args): |
402 | """Parse kconfig files and return tuple of defined and references Kconfig | ||
403 | symbols. Note, @args is a tuple of a list of files and the @ignore | ||
404 | pattern.""" | ||
405 | kconfig_files = args[0] | ||
406 | ignore = args[1] | ||
407 | defined_features = [] | ||
408 | referenced_features = dict() | ||
409 | |||
410 | for kfile in kconfig_files: | ||
411 | defined, references = parse_kconfig_file(kfile) | ||
412 | defined_features.extend(defined) | ||
413 | if ignore and re.match(ignore, kfile): | ||
414 | # do not collect references for files that match the ignore pattern | ||
415 | continue | ||
416 | referenced_features[kfile] = references | ||
417 | return (defined_features, referenced_features) | ||
418 | |||
419 | |||
420 | def parse_kconfig_file(kfile): | ||
289 | """Parse @kfile and update feature definitions and references.""" | 421 | """Parse @kfile and update feature definitions and references.""" |
290 | lines = [] | 422 | lines = [] |
423 | defined = [] | ||
424 | references = [] | ||
291 | skip = False | 425 | skip = False |
292 | 426 | ||
427 | if not os.path.exists(kfile): | ||
428 | return defined, references | ||
429 | |||
293 | with open(kfile, "r") as stream: | 430 | with open(kfile, "r") as stream: |
294 | lines = stream.readlines() | 431 | lines = stream.readlines() |
295 | 432 | ||
@@ -300,7 +437,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): | |||
300 | 437 | ||
301 | if REGEX_KCONFIG_DEF.match(line): | 438 | if REGEX_KCONFIG_DEF.match(line): |
302 | feature_def = REGEX_KCONFIG_DEF.findall(line) | 439 | feature_def = REGEX_KCONFIG_DEF.findall(line) |
303 | defined_features.add(feature_def[0]) | 440 | defined.append(feature_def[0]) |
304 | skip = False | 441 | skip = False |
305 | elif REGEX_KCONFIG_HELP.match(line): | 442 | elif REGEX_KCONFIG_HELP.match(line): |
306 | skip = True | 443 | skip = True |
@@ -308,6 +445,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): | |||
308 | # ignore content of help messages | 445 | # ignore content of help messages |
309 | pass | 446 | pass |
310 | elif REGEX_KCONFIG_STMT.match(line): | 447 | elif REGEX_KCONFIG_STMT.match(line): |
448 | line = REGEX_QUOTES.sub("", line) | ||
311 | features = get_features_in_line(line) | 449 | features = get_features_in_line(line) |
312 | # multi-line statements | 450 | # multi-line statements |
313 | while line.endswith("\\"): | 451 | while line.endswith("\\"): |
@@ -319,9 +457,9 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): | |||
319 | if REGEX_NUMERIC.match(feature): | 457 | if REGEX_NUMERIC.match(feature): |
320 | # ignore numeric values | 458 | # ignore numeric values |
321 | continue | 459 | continue |
322 | paths = referenced_features.get(feature, set()) | 460 | references.append(feature) |
323 | paths.add(kfile) | 461 | |
324 | referenced_features[feature] = paths | 462 | return defined, references |
325 | 463 | ||
326 | 464 | ||
327 | if __name__ == "__main__": | 465 | if __name__ == "__main__": |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5b96206e9aab..8adca4406198 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -917,7 +917,7 @@ static int do_vmbus_entry(const char *filename, void *symval, | |||
917 | char guid_name[(sizeof(*guid) + 1) * 2]; | 917 | char guid_name[(sizeof(*guid) + 1) * 2]; |
918 | 918 | ||
919 | for (i = 0; i < (sizeof(*guid) * 2); i += 2) | 919 | for (i = 0; i < (sizeof(*guid) * 2); i += 2) |
920 | sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2])); | 920 | sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); |
921 | 921 | ||
922 | strcpy(alias, "vmbus:"); | 922 | strcpy(alias, "vmbus:"); |
923 | strcat(alias, guid_name); | 923 | strcat(alias, guid_name); |
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 5480e4e424eb..fdc9ca4c0356 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c | |||
@@ -37,12 +37,14 @@ | |||
37 | 37 | ||
38 | static int target_fd; | 38 | static int target_fd; |
39 | static char target_fname[W_MAX_PATH]; | 39 | static char target_fname[W_MAX_PATH]; |
40 | static unsigned long long filesize; | ||
40 | 41 | ||
41 | static int hv_start_fcopy(struct hv_start_fcopy *smsg) | 42 | static int hv_start_fcopy(struct hv_start_fcopy *smsg) |
42 | { | 43 | { |
43 | int error = HV_E_FAIL; | 44 | int error = HV_E_FAIL; |
44 | char *q, *p; | 45 | char *q, *p; |
45 | 46 | ||
47 | filesize = 0; | ||
46 | p = (char *)smsg->path_name; | 48 | p = (char *)smsg->path_name; |
47 | snprintf(target_fname, sizeof(target_fname), "%s/%s", | 49 | snprintf(target_fname, sizeof(target_fname), "%s/%s", |
48 | (char *)smsg->path_name, (char *)smsg->file_name); | 50 | (char *)smsg->path_name, (char *)smsg->file_name); |
@@ -98,14 +100,26 @@ done: | |||
98 | static int hv_copy_data(struct hv_do_fcopy *cpmsg) | 100 | static int hv_copy_data(struct hv_do_fcopy *cpmsg) |
99 | { | 101 | { |
100 | ssize_t bytes_written; | 102 | ssize_t bytes_written; |
103 | int ret = 0; | ||
101 | 104 | ||
102 | bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, | 105 | bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size, |
103 | cpmsg->offset); | 106 | cpmsg->offset); |
104 | 107 | ||
105 | if (bytes_written != cpmsg->size) | 108 | filesize += cpmsg->size; |
106 | return HV_E_FAIL; | 109 | if (bytes_written != cpmsg->size) { |
110 | switch (errno) { | ||
111 | case ENOSPC: | ||
112 | ret = HV_ERROR_DISK_FULL; | ||
113 | break; | ||
114 | default: | ||
115 | ret = HV_E_FAIL; | ||
116 | break; | ||
117 | } | ||
118 | syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)", | ||
119 | filesize, (long)bytes_written, strerror(errno)); | ||
120 | } | ||
107 | 121 | ||
108 | return 0; | 122 | return ret; |
109 | } | 123 | } |
110 | 124 | ||
111 | static int hv_copy_finished(void) | 125 | static int hv_copy_finished(void) |
@@ -165,7 +179,7 @@ int main(int argc, char *argv[]) | |||
165 | } | 179 | } |
166 | 180 | ||
167 | openlog("HV_FCOPY", 0, LOG_USER); | 181 | openlog("HV_FCOPY", 0, LOG_USER); |
168 | syslog(LOG_INFO, "HV_FCOPY starting; pid is:%d", getpid()); | 182 | syslog(LOG_INFO, "starting; pid is:%d", getpid()); |
169 | 183 | ||
170 | fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); | 184 | fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); |
171 | 185 | ||
@@ -201,7 +215,7 @@ int main(int argc, char *argv[]) | |||
201 | } | 215 | } |
202 | kernel_modver = *(__u32 *)buffer; | 216 | kernel_modver = *(__u32 *)buffer; |
203 | in_handshake = 0; | 217 | in_handshake = 0; |
204 | syslog(LOG_INFO, "HV_FCOPY: kernel module version: %d", | 218 | syslog(LOG_INFO, "kernel module version: %d", |
205 | kernel_modver); | 219 | kernel_modver); |
206 | continue; | 220 | continue; |
207 | } | 221 | } |
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 96234b638249..5d51d6ff08e6 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c | |||
@@ -254,7 +254,7 @@ int main(int argc, char *argv[]) | |||
254 | syslog(LOG_ERR, "Illegal op:%d\n", op); | 254 | syslog(LOG_ERR, "Illegal op:%d\n", op); |
255 | } | 255 | } |
256 | vss_msg->error = error; | 256 | vss_msg->error = error; |
257 | len = write(vss_fd, &error, sizeof(struct hv_vss_msg)); | 257 | len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
258 | if (len != sizeof(struct hv_vss_msg)) { | 258 | if (len != sizeof(struct hv_vss_msg)) { |
259 | syslog(LOG_ERR, "write failed; error: %d %s", errno, | 259 | syslog(LOG_ERR, "write failed; error: %d %s", errno, |
260 | strerror(errno)); | 260 | strerror(errno)); |