diff options
Diffstat (limited to 'drivers/misc')
41 files changed, 1648 insertions, 1633 deletions
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index 820826270b62..705b881e186d 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c | |||
@@ -51,7 +51,7 @@ static const struct ad_dpot_bus_ops bops = { | |||
51 | .write_r8d16 = write_r8d16, | 51 | .write_r8d16 = write_r8d16, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static int __devinit ad_dpot_i2c_probe(struct i2c_client *client, | 54 | static int ad_dpot_i2c_probe(struct i2c_client *client, |
55 | const struct i2c_device_id *id) | 55 | const struct i2c_device_id *id) |
56 | { | 56 | { |
57 | struct ad_dpot_bus_data bdata = { | 57 | struct ad_dpot_bus_data bdata = { |
@@ -68,7 +68,7 @@ static int __devinit ad_dpot_i2c_probe(struct i2c_client *client, | |||
68 | return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name); | 68 | return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name); |
69 | } | 69 | } |
70 | 70 | ||
71 | static int __devexit ad_dpot_i2c_remove(struct i2c_client *client) | 71 | static int ad_dpot_i2c_remove(struct i2c_client *client) |
72 | { | 72 | { |
73 | return ad_dpot_remove(&client->dev); | 73 | return ad_dpot_remove(&client->dev); |
74 | } | 74 | } |
@@ -109,7 +109,7 @@ static struct i2c_driver ad_dpot_i2c_driver = { | |||
109 | .owner = THIS_MODULE, | 109 | .owner = THIS_MODULE, |
110 | }, | 110 | }, |
111 | .probe = ad_dpot_i2c_probe, | 111 | .probe = ad_dpot_i2c_probe, |
112 | .remove = __devexit_p(ad_dpot_i2c_remove), | 112 | .remove = ad_dpot_i2c_remove, |
113 | .id_table = ad_dpot_id, | 113 | .id_table = ad_dpot_id, |
114 | }; | 114 | }; |
115 | 115 | ||
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index f62317540d00..9da04ede04f3 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c | |||
@@ -75,7 +75,7 @@ static const struct ad_dpot_bus_ops bops = { | |||
75 | .write_r8d8 = write16, | 75 | .write_r8d8 = write16, |
76 | .write_r8d16 = write24, | 76 | .write_r8d16 = write24, |
77 | }; | 77 | }; |
78 | static int __devinit ad_dpot_spi_probe(struct spi_device *spi) | 78 | static int ad_dpot_spi_probe(struct spi_device *spi) |
79 | { | 79 | { |
80 | struct ad_dpot_bus_data bdata = { | 80 | struct ad_dpot_bus_data bdata = { |
81 | .client = spi, | 81 | .client = spi, |
@@ -87,7 +87,7 @@ static int __devinit ad_dpot_spi_probe(struct spi_device *spi) | |||
87 | spi_get_device_id(spi)->name); | 87 | spi_get_device_id(spi)->name); |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devexit ad_dpot_spi_remove(struct spi_device *spi) | 90 | static int ad_dpot_spi_remove(struct spi_device *spi) |
91 | { | 91 | { |
92 | return ad_dpot_remove(&spi->dev); | 92 | return ad_dpot_remove(&spi->dev); |
93 | } | 93 | } |
@@ -131,7 +131,7 @@ static struct spi_driver ad_dpot_spi_driver = { | |||
131 | .owner = THIS_MODULE, | 131 | .owner = THIS_MODULE, |
132 | }, | 132 | }, |
133 | .probe = ad_dpot_spi_probe, | 133 | .probe = ad_dpot_spi_probe, |
134 | .remove = __devexit_p(ad_dpot_spi_remove), | 134 | .remove = ad_dpot_spi_remove, |
135 | .id_table = ad_dpot_spi_id, | 135 | .id_table = ad_dpot_spi_id, |
136 | }; | 136 | }; |
137 | 137 | ||
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c index 6938f1be664d..8f99e8e3f0ac 100644 --- a/drivers/misc/ad525x_dpot.c +++ b/drivers/misc/ad525x_dpot.c | |||
@@ -641,7 +641,7 @@ static const struct attribute_group ad525x_group_commands = { | |||
641 | .attrs = ad525x_attributes_commands, | 641 | .attrs = ad525x_attributes_commands, |
642 | }; | 642 | }; |
643 | 643 | ||
644 | __devinit int ad_dpot_add_files(struct device *dev, | 644 | int ad_dpot_add_files(struct device *dev, |
645 | unsigned features, unsigned rdac) | 645 | unsigned features, unsigned rdac) |
646 | { | 646 | { |
647 | int err = sysfs_create_file(&dev->kobj, | 647 | int err = sysfs_create_file(&dev->kobj, |
@@ -685,7 +685,7 @@ inline void ad_dpot_remove_files(struct device *dev, | |||
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
688 | int __devinit ad_dpot_probe(struct device *dev, | 688 | int ad_dpot_probe(struct device *dev, |
689 | struct ad_dpot_bus_data *bdata, unsigned long devid, | 689 | struct ad_dpot_bus_data *bdata, unsigned long devid, |
690 | const char *name) | 690 | const char *name) |
691 | { | 691 | { |
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c index 0314773f6db3..d648b0893027 100644 --- a/drivers/misc/apds9802als.c +++ b/drivers/misc/apds9802als.c | |||
@@ -68,7 +68,7 @@ static int als_wait_for_data_ready(struct device *dev) | |||
68 | ret = i2c_smbus_read_byte_data(client, 0x86); | 68 | ret = i2c_smbus_read_byte_data(client, 0x86); |
69 | } while (!(ret & 0x80) && retry--); | 69 | } while (!(ret & 0x80) && retry--); |
70 | 70 | ||
71 | if (!retry) { | 71 | if (retry < 0) { |
72 | dev_warn(dev, "timeout waiting for data ready\n"); | 72 | dev_warn(dev, "timeout waiting for data ready\n"); |
73 | return -ETIMEDOUT; | 73 | return -ETIMEDOUT; |
74 | } | 74 | } |
@@ -254,7 +254,7 @@ als_error1: | |||
254 | return res; | 254 | return res; |
255 | } | 255 | } |
256 | 256 | ||
257 | static int __devexit apds9802als_remove(struct i2c_client *client) | 257 | static int apds9802als_remove(struct i2c_client *client) |
258 | { | 258 | { |
259 | struct als_data *data = i2c_get_clientdata(client); | 259 | struct als_data *data = i2c_get_clientdata(client); |
260 | 260 | ||
@@ -326,7 +326,7 @@ static struct i2c_driver apds9802als_driver = { | |||
326 | .pm = APDS9802ALS_PM_OPS, | 326 | .pm = APDS9802ALS_PM_OPS, |
327 | }, | 327 | }, |
328 | .probe = apds9802als_probe, | 328 | .probe = apds9802als_probe, |
329 | .remove = __devexit_p(apds9802als_remove), | 329 | .remove = apds9802als_remove, |
330 | .suspend = apds9802als_suspend, | 330 | .suspend = apds9802als_suspend, |
331 | .resume = apds9802als_resume, | 331 | .resume = apds9802als_resume, |
332 | .id_table = apds9802als_id, | 332 | .id_table = apds9802als_id, |
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index ee74244aa03b..0e67f8263cd8 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c | |||
@@ -1047,7 +1047,7 @@ static struct attribute_group apds990x_attribute_group[] = { | |||
1047 | {.attrs = sysfs_attrs_ctrl }, | 1047 | {.attrs = sysfs_attrs_ctrl }, |
1048 | }; | 1048 | }; |
1049 | 1049 | ||
1050 | static int __devinit apds990x_probe(struct i2c_client *client, | 1050 | static int apds990x_probe(struct i2c_client *client, |
1051 | const struct i2c_device_id *id) | 1051 | const struct i2c_device_id *id) |
1052 | { | 1052 | { |
1053 | struct apds990x_chip *chip; | 1053 | struct apds990x_chip *chip; |
@@ -1181,7 +1181,7 @@ fail1: | |||
1181 | return err; | 1181 | return err; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | static int __devexit apds990x_remove(struct i2c_client *client) | 1184 | static int apds990x_remove(struct i2c_client *client) |
1185 | { | 1185 | { |
1186 | struct apds990x_chip *chip = i2c_get_clientdata(client); | 1186 | struct apds990x_chip *chip = i2c_get_clientdata(client); |
1187 | 1187 | ||
@@ -1275,7 +1275,7 @@ static struct i2c_driver apds990x_driver = { | |||
1275 | .pm = &apds990x_pm_ops, | 1275 | .pm = &apds990x_pm_ops, |
1276 | }, | 1276 | }, |
1277 | .probe = apds990x_probe, | 1277 | .probe = apds990x_probe, |
1278 | .remove = __devexit_p(apds990x_remove), | 1278 | .remove = apds990x_remove, |
1279 | .id_table = apds990x_id, | 1279 | .id_table = apds990x_id, |
1280 | }; | 1280 | }; |
1281 | 1281 | ||
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 5bb187781074..c58f9abcb356 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
@@ -137,7 +137,7 @@ out: | |||
137 | return retval; | 137 | return retval; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int __devexit ssc_remove(struct platform_device *pdev) | 140 | static int ssc_remove(struct platform_device *pdev) |
141 | { | 141 | { |
142 | struct ssc_device *ssc = platform_get_drvdata(pdev); | 142 | struct ssc_device *ssc = platform_get_drvdata(pdev); |
143 | 143 | ||
@@ -152,7 +152,7 @@ static int __devexit ssc_remove(struct platform_device *pdev) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | static struct platform_driver ssc_driver = { | 154 | static struct platform_driver ssc_driver = { |
155 | .remove = __devexit_p(ssc_remove), | 155 | .remove = ssc_remove, |
156 | .driver = { | 156 | .driver = { |
157 | .name = "ssc", | 157 | .name = "ssc", |
158 | .owner = THIS_MODULE, | 158 | .owner = THIS_MODULE, |
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index 3d56ae7ef8de..2ed8fc3be7e6 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c | |||
@@ -1162,7 +1162,7 @@ static struct attribute_group bh1770_attribute_group = { | |||
1162 | .attrs = sysfs_attrs | 1162 | .attrs = sysfs_attrs |
1163 | }; | 1163 | }; |
1164 | 1164 | ||
1165 | static int __devinit bh1770_probe(struct i2c_client *client, | 1165 | static int bh1770_probe(struct i2c_client *client, |
1166 | const struct i2c_device_id *id) | 1166 | const struct i2c_device_id *id) |
1167 | { | 1167 | { |
1168 | struct bh1770_chip *chip; | 1168 | struct bh1770_chip *chip; |
@@ -1285,7 +1285,7 @@ fail1: | |||
1285 | return err; | 1285 | return err; |
1286 | } | 1286 | } |
1287 | 1287 | ||
1288 | static int __devexit bh1770_remove(struct i2c_client *client) | 1288 | static int bh1770_remove(struct i2c_client *client) |
1289 | { | 1289 | { |
1290 | struct bh1770_chip *chip = i2c_get_clientdata(client); | 1290 | struct bh1770_chip *chip = i2c_get_clientdata(client); |
1291 | 1291 | ||
@@ -1395,7 +1395,7 @@ static struct i2c_driver bh1770_driver = { | |||
1395 | .pm = &bh1770_pm_ops, | 1395 | .pm = &bh1770_pm_ops, |
1396 | }, | 1396 | }, |
1397 | .probe = bh1770_probe, | 1397 | .probe = bh1770_probe, |
1398 | .remove = __devexit_p(bh1770_remove), | 1398 | .remove = bh1770_remove, |
1399 | .id_table = bh1770_id, | 1399 | .id_table = bh1770_id, |
1400 | }; | 1400 | }; |
1401 | 1401 | ||
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index f1f9877f3fdf..cf03d0abf33e 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c | |||
@@ -144,7 +144,7 @@ static const struct attribute_group bh1780_attr_group = { | |||
144 | .attrs = bh1780_attributes, | 144 | .attrs = bh1780_attributes, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static int __devinit bh1780_probe(struct i2c_client *client, | 147 | static int bh1780_probe(struct i2c_client *client, |
148 | const struct i2c_device_id *id) | 148 | const struct i2c_device_id *id) |
149 | { | 149 | { |
150 | int ret; | 150 | int ret; |
@@ -185,7 +185,7 @@ err_op_failed: | |||
185 | return ret; | 185 | return ret; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int __devexit bh1780_remove(struct i2c_client *client) | 188 | static int bh1780_remove(struct i2c_client *client) |
189 | { | 189 | { |
190 | struct bh1780_data *ddata; | 190 | struct bh1780_data *ddata; |
191 | 191 | ||
@@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = { | |||
248 | 248 | ||
249 | static struct i2c_driver bh1780_driver = { | 249 | static struct i2c_driver bh1780_driver = { |
250 | .probe = bh1780_probe, | 250 | .probe = bh1780_probe, |
251 | .remove = __devexit_p(bh1780_remove), | 251 | .remove = bh1780_remove, |
252 | .id_table = bh1780_id, | 252 | .id_table = bh1780_id, |
253 | .driver = { | 253 | .driver = { |
254 | .name = "bh1780", | 254 | .name = "bh1780", |
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c index a4f33c995ea1..3abfcecf8424 100644 --- a/drivers/misc/bmp085-i2c.c +++ b/drivers/misc/bmp085-i2c.c | |||
@@ -36,7 +36,7 @@ static int bmp085_i2c_detect(struct i2c_client *client, | |||
36 | return bmp085_detect(&client->dev); | 36 | return bmp085_detect(&client->dev); |
37 | } | 37 | } |
38 | 38 | ||
39 | static int __devinit bmp085_i2c_probe(struct i2c_client *client, | 39 | static int bmp085_i2c_probe(struct i2c_client *client, |
40 | const struct i2c_device_id *id) | 40 | const struct i2c_device_id *id) |
41 | { | 41 | { |
42 | int err; | 42 | int err; |
@@ -71,7 +71,7 @@ static struct i2c_driver bmp085_i2c_driver = { | |||
71 | }, | 71 | }, |
72 | .id_table = bmp085_id, | 72 | .id_table = bmp085_id, |
73 | .probe = bmp085_i2c_probe, | 73 | .probe = bmp085_i2c_probe, |
74 | .remove = __devexit_p(bmp085_i2c_remove), | 74 | .remove = bmp085_i2c_remove, |
75 | 75 | ||
76 | .detect = bmp085_i2c_detect, | 76 | .detect = bmp085_i2c_detect, |
77 | .address_list = normal_i2c | 77 | .address_list = normal_i2c |
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c index 5e982af99730..d6a52659cf24 100644 --- a/drivers/misc/bmp085-spi.c +++ b/drivers/misc/bmp085-spi.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include "bmp085.h" | 23 | #include "bmp085.h" |
24 | 24 | ||
25 | static int __devinit bmp085_spi_probe(struct spi_device *client) | 25 | static int bmp085_spi_probe(struct spi_device *client) |
26 | { | 26 | { |
27 | int err; | 27 | int err; |
28 | struct regmap *regmap; | 28 | struct regmap *regmap; |
@@ -70,7 +70,7 @@ static struct spi_driver bmp085_spi_driver = { | |||
70 | }, | 70 | }, |
71 | .id_table = bmp085_id, | 71 | .id_table = bmp085_id, |
72 | .probe = bmp085_spi_probe, | 72 | .probe = bmp085_spi_probe, |
73 | .remove = __devexit_p(bmp085_spi_remove) | 73 | .remove = bmp085_spi_remove |
74 | }; | 74 | }; |
75 | 75 | ||
76 | module_spi_driver(bmp085_spi_driver); | 76 | module_spi_driver(bmp085_spi_driver); |
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c index 62e418293b7e..849e2fed4da2 100644 --- a/drivers/misc/bmp085.c +++ b/drivers/misc/bmp085.c | |||
@@ -420,7 +420,7 @@ struct regmap_config bmp085_regmap_config = { | |||
420 | }; | 420 | }; |
421 | EXPORT_SYMBOL_GPL(bmp085_regmap_config); | 421 | EXPORT_SYMBOL_GPL(bmp085_regmap_config); |
422 | 422 | ||
423 | __devinit int bmp085_probe(struct device *dev, struct regmap *regmap) | 423 | int bmp085_probe(struct device *dev, struct regmap *regmap) |
424 | { | 424 | { |
425 | struct bmp085_data *data; | 425 | struct bmp085_data *data; |
426 | int err = 0; | 426 | int err = 0; |
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index 9d5eed754666..2e50f811ff59 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c | |||
@@ -30,7 +30,7 @@ void cb710_pci_update_config_reg(struct pci_dev *pdev, | |||
30 | EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg); | 30 | EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg); |
31 | 31 | ||
32 | /* Some magic writes based on Windows driver init code */ | 32 | /* Some magic writes based on Windows driver init code */ |
33 | static int __devinit cb710_pci_configure(struct pci_dev *pdev) | 33 | static int cb710_pci_configure(struct pci_dev *pdev) |
34 | { | 34 | { |
35 | unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); | 35 | unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); |
36 | struct pci_dev *pdev0; | 36 | struct pci_dev *pdev0; |
@@ -96,7 +96,7 @@ static void cb710_release_slot(struct device *dev) | |||
96 | #endif | 96 | #endif |
97 | } | 97 | } |
98 | 98 | ||
99 | static int __devinit cb710_register_slot(struct cb710_chip *chip, | 99 | static int cb710_register_slot(struct cb710_chip *chip, |
100 | unsigned slot_mask, unsigned io_offset, const char *name) | 100 | unsigned slot_mask, unsigned io_offset, const char *name) |
101 | { | 101 | { |
102 | int nr = chip->slots; | 102 | int nr = chip->slots; |
@@ -201,7 +201,7 @@ static int cb710_resume(struct pci_dev *pdev) | |||
201 | 201 | ||
202 | #endif /* CONFIG_PM */ | 202 | #endif /* CONFIG_PM */ |
203 | 203 | ||
204 | static int __devinit cb710_probe(struct pci_dev *pdev, | 204 | static int cb710_probe(struct pci_dev *pdev, |
205 | const struct pci_device_id *ent) | 205 | const struct pci_device_id *ent) |
206 | { | 206 | { |
207 | struct cb710_chip *chip; | 207 | struct cb710_chip *chip; |
@@ -305,7 +305,7 @@ unreg_mmc: | |||
305 | return err; | 305 | return err; |
306 | } | 306 | } |
307 | 307 | ||
308 | static void __devexit cb710_remove_one(struct pci_dev *pdev) | 308 | static void cb710_remove_one(struct pci_dev *pdev) |
309 | { | 309 | { |
310 | struct cb710_chip *chip = pci_get_drvdata(pdev); | 310 | struct cb710_chip *chip = pci_get_drvdata(pdev); |
311 | unsigned long flags; | 311 | unsigned long flags; |
@@ -332,7 +332,7 @@ static struct pci_driver cb710_driver = { | |||
332 | .name = KBUILD_MODNAME, | 332 | .name = KBUILD_MODNAME, |
333 | .id_table = cb710_pci_tbl, | 333 | .id_table = cb710_pci_tbl, |
334 | .probe = cb710_probe, | 334 | .probe = cb710_probe, |
335 | .remove = __devexit_p(cb710_remove_one), | 335 | .remove = cb710_remove_one, |
336 | #ifdef CONFIG_PM | 336 | #ifdef CONFIG_PM |
337 | .suspend = cb710_suspend, | 337 | .suspend = cb710_suspend, |
338 | .resume = cb710_resume, | 338 | .resume = cb710_resume, |
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index f505a40a8f49..9858f36dad8b 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c | |||
@@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_write); | |||
246 | * Jordan tells me that he and Mitch once played w/ it, but it's unclear | 246 | * Jordan tells me that he and Mitch once played w/ it, but it's unclear |
247 | * what the results of that were (and they experienced some instability). | 247 | * what the results of that were (and they experienced some instability). |
248 | */ | 248 | */ |
249 | static void __devinit reset_all_timers(void) | 249 | static void reset_all_timers(void) |
250 | { | 250 | { |
251 | uint32_t val, dummy; | 251 | uint32_t val, dummy; |
252 | 252 | ||
@@ -262,7 +262,7 @@ static void __devinit reset_all_timers(void) | |||
262 | * In other cases (such as with VSAless OpenFirmware), the system firmware | 262 | * In other cases (such as with VSAless OpenFirmware), the system firmware |
263 | * leaves timers available for us to use. | 263 | * leaves timers available for us to use. |
264 | */ | 264 | */ |
265 | static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt) | 265 | static int scan_timers(struct cs5535_mfgpt_chip *mfgpt) |
266 | { | 266 | { |
267 | struct cs5535_mfgpt_timer timer = { .chip = mfgpt }; | 267 | struct cs5535_mfgpt_timer timer = { .chip = mfgpt }; |
268 | unsigned long flags; | 268 | unsigned long flags; |
@@ -289,7 +289,7 @@ static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt) | |||
289 | return timers; | 289 | return timers; |
290 | } | 290 | } |
291 | 291 | ||
292 | static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev) | 292 | static int cs5535_mfgpt_probe(struct platform_device *pdev) |
293 | { | 293 | { |
294 | struct resource *res; | 294 | struct resource *res; |
295 | int err = -EIO, t; | 295 | int err = -EIO, t; |
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index ab1ad41786d1..2baeec56edfe 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
@@ -656,7 +656,7 @@ err_out: | |||
656 | return err; | 656 | return err; |
657 | } | 657 | } |
658 | 658 | ||
659 | static int __devexit at24_remove(struct i2c_client *client) | 659 | static int at24_remove(struct i2c_client *client) |
660 | { | 660 | { |
661 | struct at24_data *at24; | 661 | struct at24_data *at24; |
662 | int i; | 662 | int i; |
@@ -680,7 +680,7 @@ static struct i2c_driver at24_driver = { | |||
680 | .owner = THIS_MODULE, | 680 | .owner = THIS_MODULE, |
681 | }, | 681 | }, |
682 | .probe = at24_probe, | 682 | .probe = at24_probe, |
683 | .remove = __devexit_p(at24_remove), | 683 | .remove = at24_remove, |
684 | .id_table = at24_ids, | 684 | .id_table = at24_ids, |
685 | }; | 685 | }; |
686 | 686 | ||
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 4ed93dd54116..b08cf8a08789 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c | |||
@@ -459,7 +459,7 @@ fail: | |||
459 | return err; | 459 | return err; |
460 | } | 460 | } |
461 | 461 | ||
462 | static int __devexit at25_remove(struct spi_device *spi) | 462 | static int at25_remove(struct spi_device *spi) |
463 | { | 463 | { |
464 | struct at25_data *at25; | 464 | struct at25_data *at25; |
465 | 465 | ||
@@ -477,7 +477,7 @@ static struct spi_driver at25_driver = { | |||
477 | .owner = THIS_MODULE, | 477 | .owner = THIS_MODULE, |
478 | }, | 478 | }, |
479 | .probe = at25_probe, | 479 | .probe = at25_probe, |
480 | .remove = __devexit_p(at25_remove), | 480 | .remove = at25_remove, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | module_spi_driver(at25_driver); | 483 | module_spi_driver(at25_driver); |
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index ce3fe3633dd7..a6b5d5e73485 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c | |||
@@ -309,7 +309,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev, | |||
309 | } | 309 | } |
310 | static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); | 310 | static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); |
311 | 311 | ||
312 | static int __devinit eeprom_93xx46_probe(struct spi_device *spi) | 312 | static int eeprom_93xx46_probe(struct spi_device *spi) |
313 | { | 313 | { |
314 | struct eeprom_93xx46_platform_data *pd; | 314 | struct eeprom_93xx46_platform_data *pd; |
315 | struct eeprom_93xx46_dev *edev; | 315 | struct eeprom_93xx46_dev *edev; |
@@ -370,7 +370,7 @@ fail: | |||
370 | return err; | 370 | return err; |
371 | } | 371 | } |
372 | 372 | ||
373 | static int __devexit eeprom_93xx46_remove(struct spi_device *spi) | 373 | static int eeprom_93xx46_remove(struct spi_device *spi) |
374 | { | 374 | { |
375 | struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev); | 375 | struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev); |
376 | 376 | ||
@@ -389,7 +389,7 @@ static struct spi_driver eeprom_93xx46_driver = { | |||
389 | .owner = THIS_MODULE, | 389 | .owner = THIS_MODULE, |
390 | }, | 390 | }, |
391 | .probe = eeprom_93xx46_probe, | 391 | .probe = eeprom_93xx46_probe, |
392 | .remove = __devexit_p(eeprom_93xx46_remove), | 392 | .remove = eeprom_93xx46_remove, |
393 | }; | 393 | }; |
394 | 394 | ||
395 | module_spi_driver(eeprom_93xx46_driver); | 395 | module_spi_driver(eeprom_93xx46_driver); |
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c index ac96c3a4034a..e8cbb1c59f4c 100644 --- a/drivers/misc/fsa9480.c +++ b/drivers/misc/fsa9480.c | |||
@@ -407,7 +407,7 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw) | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static int __devinit fsa9480_probe(struct i2c_client *client, | 410 | static int fsa9480_probe(struct i2c_client *client, |
411 | const struct i2c_device_id *id) | 411 | const struct i2c_device_id *id) |
412 | { | 412 | { |
413 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 413 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
@@ -462,7 +462,7 @@ fail1: | |||
462 | return ret; | 462 | return ret; |
463 | } | 463 | } |
464 | 464 | ||
465 | static int __devexit fsa9480_remove(struct i2c_client *client) | 465 | static int fsa9480_remove(struct i2c_client *client) |
466 | { | 466 | { |
467 | struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); | 467 | struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); |
468 | if (client->irq) | 468 | if (client->irq) |
@@ -533,7 +533,7 @@ static struct i2c_driver fsa9480_i2c_driver = { | |||
533 | .name = "fsa9480", | 533 | .name = "fsa9480", |
534 | }, | 534 | }, |
535 | .probe = fsa9480_probe, | 535 | .probe = fsa9480_probe, |
536 | .remove = __devexit_p(fsa9480_remove), | 536 | .remove = fsa9480_remove, |
537 | .resume = fsa9480_resume, | 537 | .resume = fsa9480_resume, |
538 | .suspend = fsa9480_suspend, | 538 | .suspend = fsa9480_suspend, |
539 | .id_table = fsa9480_id, | 539 | .id_table = fsa9480_id, |
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 12ccdf94e4fa..621c7a373390 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | static struct class *ilo_class; | 31 | static struct class *ilo_class; |
32 | static unsigned int ilo_major; | 32 | static unsigned int ilo_major; |
33 | static unsigned int max_ccb = MIN_CCB; | 33 | static unsigned int max_ccb = 16; |
34 | static char ilo_hwdev[MAX_ILO_DEV]; | 34 | static char ilo_hwdev[MAX_ILO_DEV]; |
35 | 35 | ||
36 | static inline int get_entry_id(int entry) | 36 | static inline int get_entry_id(int entry) |
@@ -686,7 +686,7 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) | |||
686 | pci_iounmap(pdev, hw->mmio_vaddr); | 686 | pci_iounmap(pdev, hw->mmio_vaddr); |
687 | } | 687 | } |
688 | 688 | ||
689 | static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) | 689 | static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) |
690 | { | 690 | { |
691 | int error = -ENOMEM; | 691 | int error = -ENOMEM; |
692 | 692 | ||
@@ -725,6 +725,9 @@ static void ilo_remove(struct pci_dev *pdev) | |||
725 | int i, minor; | 725 | int i, minor; |
726 | struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev); | 726 | struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev); |
727 | 727 | ||
728 | if (!ilo_hw) | ||
729 | return; | ||
730 | |||
728 | clear_device(ilo_hw); | 731 | clear_device(ilo_hw); |
729 | 732 | ||
730 | minor = MINOR(ilo_hw->cdev.dev); | 733 | minor = MINOR(ilo_hw->cdev.dev); |
@@ -748,12 +751,16 @@ static void ilo_remove(struct pci_dev *pdev) | |||
748 | ilo_hwdev[(minor / max_ccb)] = 0; | 751 | ilo_hwdev[(minor / max_ccb)] = 0; |
749 | } | 752 | } |
750 | 753 | ||
751 | static int __devinit ilo_probe(struct pci_dev *pdev, | 754 | static int ilo_probe(struct pci_dev *pdev, |
752 | const struct pci_device_id *ent) | 755 | const struct pci_device_id *ent) |
753 | { | 756 | { |
754 | int devnum, minor, start, error; | 757 | int devnum, minor, start, error = 0; |
755 | struct ilo_hwinfo *ilo_hw; | 758 | struct ilo_hwinfo *ilo_hw; |
756 | 759 | ||
760 | /* Ignore subsystem_device = 0x1979 (set by BIOS) */ | ||
761 | if (pdev->subsystem_device == 0x1979) | ||
762 | goto out; | ||
763 | |||
757 | if (max_ccb > MAX_CCB) | 764 | if (max_ccb > MAX_CCB) |
758 | max_ccb = MAX_CCB; | 765 | max_ccb = MAX_CCB; |
759 | else if (max_ccb < MIN_CCB) | 766 | else if (max_ccb < MIN_CCB) |
@@ -852,7 +859,7 @@ static struct pci_driver ilo_driver = { | |||
852 | .name = ILO_NAME, | 859 | .name = ILO_NAME, |
853 | .id_table = ilo_devices, | 860 | .id_table = ilo_devices, |
854 | .probe = ilo_probe, | 861 | .probe = ilo_probe, |
855 | .remove = __devexit_p(ilo_remove), | 862 | .remove = ilo_remove, |
856 | }; | 863 | }; |
857 | 864 | ||
858 | static int __init ilo_init(void) | 865 | static int __init ilo_init(void) |
@@ -892,14 +899,14 @@ static void __exit ilo_exit(void) | |||
892 | class_destroy(ilo_class); | 899 | class_destroy(ilo_class); |
893 | } | 900 | } |
894 | 901 | ||
895 | MODULE_VERSION("1.3"); | 902 | MODULE_VERSION("1.4"); |
896 | MODULE_ALIAS(ILO_NAME); | 903 | MODULE_ALIAS(ILO_NAME); |
897 | MODULE_DESCRIPTION(ILO_NAME); | 904 | MODULE_DESCRIPTION(ILO_NAME); |
898 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); | 905 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); |
899 | MODULE_LICENSE("GPL v2"); | 906 | MODULE_LICENSE("GPL v2"); |
900 | 907 | ||
901 | module_param(max_ccb, uint, 0444); | 908 | module_param(max_ccb, uint, 0444); |
902 | MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)"); | 909 | MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (16)"); |
903 | 910 | ||
904 | module_init(ilo_init); | 911 | module_init(ilo_init); |
905 | module_exit(ilo_exit); | 912 | module_exit(ilo_exit); |
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index 168d8008f460..0346d87c5fed 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c | |||
@@ -62,7 +62,7 @@ module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR); | |||
62 | MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off"); | 62 | MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off"); |
63 | 63 | ||
64 | 64 | ||
65 | static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 65 | static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
66 | { | 66 | { |
67 | int result; | 67 | int result; |
68 | struct service_processor *sp; | 68 | struct service_processor *sp; |
@@ -163,7 +163,7 @@ error_resources: | |||
163 | return result; | 163 | return result; |
164 | } | 164 | } |
165 | 165 | ||
166 | static void __devexit ibmasm_remove_one(struct pci_dev *pdev) | 166 | static void ibmasm_remove_one(struct pci_dev *pdev) |
167 | { | 167 | { |
168 | struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev); | 168 | struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev); |
169 | 169 | ||
@@ -198,7 +198,7 @@ static struct pci_driver ibmasm_driver = { | |||
198 | .name = DRIVER_NAME, | 198 | .name = DRIVER_NAME, |
199 | .id_table = ibmasm_pci_table, | 199 | .id_table = ibmasm_pci_table, |
200 | .probe = ibmasm_init_one, | 200 | .probe = ibmasm_init_one, |
201 | .remove = __devexit_p(ibmasm_remove_one), | 201 | .remove = ibmasm_remove_one, |
202 | }; | 202 | }; |
203 | 203 | ||
204 | static void __exit ibmasm_exit (void) | 204 | static void __exit ibmasm_exit (void) |
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 6a7710603a90..06f6ad29ceff 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c | |||
@@ -139,7 +139,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) | |||
139 | * even though the following code utilizes external interrupt registers | 139 | * even though the following code utilizes external interrupt registers |
140 | * to perform the speed calculation. | 140 | * to perform the speed calculation. |
141 | */ | 141 | */ |
142 | static void __devinit | 142 | static void |
143 | ioc4_clock_calibrate(struct ioc4_driver_data *idd) | 143 | ioc4_clock_calibrate(struct ioc4_driver_data *idd) |
144 | { | 144 | { |
145 | union ioc4_int_out int_out; | 145 | union ioc4_int_out int_out; |
@@ -231,7 +231,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) | |||
231 | * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. | 231 | * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. |
232 | * If neither is present, it's a PCI-RT. | 232 | * If neither is present, it's a PCI-RT. |
233 | */ | 233 | */ |
234 | static unsigned int __devinit | 234 | static unsigned int |
235 | ioc4_variant(struct ioc4_driver_data *idd) | 235 | ioc4_variant(struct ioc4_driver_data *idd) |
236 | { | 236 | { |
237 | struct pci_dev *pdev = NULL; | 237 | struct pci_dev *pdev = NULL; |
@@ -279,7 +279,7 @@ ioc4_load_modules(struct work_struct *work) | |||
279 | static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules); | 279 | static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules); |
280 | 280 | ||
281 | /* Adds a new instance of an IOC4 card */ | 281 | /* Adds a new instance of an IOC4 card */ |
282 | static int __devinit | 282 | static int |
283 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 283 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) |
284 | { | 284 | { |
285 | struct ioc4_driver_data *idd; | 285 | struct ioc4_driver_data *idd; |
@@ -415,7 +415,7 @@ out: | |||
415 | } | 415 | } |
416 | 416 | ||
417 | /* Removes a particular instance of an IOC4 card. */ | 417 | /* Removes a particular instance of an IOC4 card. */ |
418 | static void __devexit | 418 | static void |
419 | ioc4_remove(struct pci_dev *pdev) | 419 | ioc4_remove(struct pci_dev *pdev) |
420 | { | 420 | { |
421 | struct ioc4_submodule *is; | 421 | struct ioc4_submodule *is; |
@@ -466,7 +466,7 @@ static struct pci_driver ioc4_driver = { | |||
466 | .name = "IOC4", | 466 | .name = "IOC4", |
467 | .id_table = ioc4_id_table, | 467 | .id_table = ioc4_id_table, |
468 | .probe = ioc4_probe, | 468 | .probe = ioc4_probe, |
469 | .remove = __devexit_p(ioc4_remove), | 469 | .remove = ioc4_remove, |
470 | }; | 470 | }; |
471 | 471 | ||
472 | MODULE_DEVICE_TABLE(pci, ioc4_id_table); | 472 | MODULE_DEVICE_TABLE(pci, ioc4_id_table); |
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c index eb5de2e210d7..29b306c6bdb3 100644 --- a/drivers/misc/isl29003.c +++ b/drivers/misc/isl29003.c | |||
@@ -365,7 +365,7 @@ static int isl29003_init_client(struct i2c_client *client) | |||
365 | * I2C layer | 365 | * I2C layer |
366 | */ | 366 | */ |
367 | 367 | ||
368 | static int __devinit isl29003_probe(struct i2c_client *client, | 368 | static int isl29003_probe(struct i2c_client *client, |
369 | const struct i2c_device_id *id) | 369 | const struct i2c_device_id *id) |
370 | { | 370 | { |
371 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 371 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
@@ -401,7 +401,7 @@ exit_kfree: | |||
401 | return err; | 401 | return err; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int __devexit isl29003_remove(struct i2c_client *client) | 404 | static int isl29003_remove(struct i2c_client *client) |
405 | { | 405 | { |
406 | sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group); | 406 | sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group); |
407 | isl29003_set_power_state(client, 0); | 407 | isl29003_set_power_state(client, 0); |
@@ -451,7 +451,7 @@ static struct i2c_driver isl29003_driver = { | |||
451 | .suspend = isl29003_suspend, | 451 | .suspend = isl29003_suspend, |
452 | .resume = isl29003_resume, | 452 | .resume = isl29003_resume, |
453 | .probe = isl29003_probe, | 453 | .probe = isl29003_probe, |
454 | .remove = __devexit_p(isl29003_remove), | 454 | .remove = isl29003_remove, |
455 | .id_table = isl29003_id, | 455 | .id_table = isl29003_id, |
456 | }; | 456 | }; |
457 | 457 | ||
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c index 60ec8689d6e3..7c97550240f1 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c | |||
@@ -114,7 +114,7 @@ static struct of_device_id lis3lv02d_i2c_dt_ids[] = { | |||
114 | MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids); | 114 | MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids); |
115 | #endif | 115 | #endif |
116 | 116 | ||
117 | static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, | 117 | static int lis3lv02d_i2c_probe(struct i2c_client *client, |
118 | const struct i2c_device_id *id) | 118 | const struct i2c_device_id *id) |
119 | { | 119 | { |
120 | int ret = 0; | 120 | int ret = 0; |
@@ -191,7 +191,7 @@ fail: | |||
191 | return ret; | 191 | return ret; |
192 | } | 192 | } |
193 | 193 | ||
194 | static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client) | 194 | static int lis3lv02d_i2c_remove(struct i2c_client *client) |
195 | { | 195 | { |
196 | struct lis3lv02d *lis3 = i2c_get_clientdata(client); | 196 | struct lis3lv02d *lis3 = i2c_get_clientdata(client); |
197 | struct lis3lv02d_platform_data *pdata = client->dev.platform_data; | 197 | struct lis3lv02d_platform_data *pdata = client->dev.platform_data; |
@@ -280,7 +280,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = { | |||
280 | .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), | 280 | .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids), |
281 | }, | 281 | }, |
282 | .probe = lis3lv02d_i2c_probe, | 282 | .probe = lis3lv02d_i2c_probe, |
283 | .remove = __devexit_p(lis3lv02d_i2c_remove), | 283 | .remove = lis3lv02d_i2c_remove, |
284 | .id_table = lis3lv02d_id, | 284 | .id_table = lis3lv02d_id, |
285 | }; | 285 | }; |
286 | 286 | ||
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c index ccb6475fa059..9aa2bd2a71ae 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c | |||
@@ -69,7 +69,7 @@ static struct of_device_id lis302dl_spi_dt_ids[] = { | |||
69 | MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids); | 69 | MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids); |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | static int __devinit lis302dl_spi_probe(struct spi_device *spi) | 72 | static int lis302dl_spi_probe(struct spi_device *spi) |
73 | { | 73 | { |
74 | int ret; | 74 | int ret; |
75 | 75 | ||
@@ -100,7 +100,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi) | |||
100 | return lis3lv02d_init_device(&lis3_dev); | 100 | return lis3lv02d_init_device(&lis3_dev); |
101 | } | 101 | } |
102 | 102 | ||
103 | static int __devexit lis302dl_spi_remove(struct spi_device *spi) | 103 | static int lis302dl_spi_remove(struct spi_device *spi) |
104 | { | 104 | { |
105 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); | 105 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); |
106 | lis3lv02d_joystick_disable(lis3); | 106 | lis3lv02d_joystick_disable(lis3); |
@@ -144,7 +144,7 @@ static struct spi_driver lis302dl_spi_driver = { | |||
144 | .of_match_table = of_match_ptr(lis302dl_spi_dt_ids), | 144 | .of_match_table = of_match_ptr(lis302dl_spi_dt_ids), |
145 | }, | 145 | }, |
146 | .probe = lis302dl_spi_probe, | 146 | .probe = lis302dl_spi_probe, |
147 | .remove = __devexit_p(lis302dl_spi_remove), | 147 | .remove = lis302dl_spi_remove, |
148 | }; | 148 | }; |
149 | 149 | ||
150 | module_spi_driver(lis302dl_spi_driver); | 150 | module_spi_driver(lis302dl_spi_driver); |
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index 57168db6c7e5..0017842e166c 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile | |||
@@ -8,4 +8,5 @@ mei-objs += interrupt.o | |||
8 | mei-objs += interface.o | 8 | mei-objs += interface.o |
9 | mei-objs += iorw.o | 9 | mei-objs += iorw.o |
10 | mei-objs += main.o | 10 | mei-objs += main.o |
11 | mei-objs += amthif.o | ||
11 | mei-objs += wd.o | 12 | mei-objs += wd.o |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c new file mode 100644 index 000000000000..18794aea6062 --- /dev/null +++ b/drivers/misc/mei/amthif.c | |||
@@ -0,0 +1,722 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Intel Management Engine Interface (Intel MEI) Linux driver | ||
4 | * Copyright (c) 2003-2012, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/fcntl.h> | ||
22 | #include <linux/aio.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioctl.h> | ||
26 | #include <linux/cdev.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/uuid.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | |||
34 | |||
35 | #include "mei_dev.h" | ||
36 | #include "hw.h" | ||
37 | #include <linux/mei.h> | ||
38 | #include "interface.h" | ||
39 | |||
40 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | ||
41 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | ||
42 | 0x81, 0x4c); | ||
43 | |||
44 | /** | ||
45 | * mei_amthif_reset_params - initializes mei device iamthif | ||
46 | * | ||
47 | * @dev: the device structure | ||
48 | */ | ||
49 | void mei_amthif_reset_params(struct mei_device *dev) | ||
50 | { | ||
51 | /* reset iamthif parameters. */ | ||
52 | dev->iamthif_current_cb = NULL; | ||
53 | dev->iamthif_msg_buf_size = 0; | ||
54 | dev->iamthif_msg_buf_index = 0; | ||
55 | dev->iamthif_canceled = false; | ||
56 | dev->iamthif_ioctl = false; | ||
57 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
58 | dev->iamthif_timer = 0; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * mei_amthif_host_init_ - mei initialization amthif client. | ||
63 | * | ||
64 | * @dev: the device structure | ||
65 | * | ||
66 | */ | ||
67 | void mei_amthif_host_init(struct mei_device *dev) | ||
68 | { | ||
69 | int i; | ||
70 | unsigned char *msg_buf; | ||
71 | |||
72 | mei_cl_init(&dev->iamthif_cl, dev); | ||
73 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
74 | |||
75 | /* find ME amthi client */ | ||
76 | i = mei_me_cl_link(dev, &dev->iamthif_cl, | ||
77 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
78 | if (i < 0) { | ||
79 | dev_info(&dev->pdev->dev, "failed to find iamthif client.\n"); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | /* Assign iamthif_mtu to the value received from ME */ | ||
84 | |||
85 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | ||
86 | dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", | ||
87 | dev->me_clients[i].props.max_msg_length); | ||
88 | |||
89 | kfree(dev->iamthif_msg_buf); | ||
90 | dev->iamthif_msg_buf = NULL; | ||
91 | |||
92 | /* allocate storage for ME message buffer */ | ||
93 | msg_buf = kcalloc(dev->iamthif_mtu, | ||
94 | sizeof(unsigned char), GFP_KERNEL); | ||
95 | if (!msg_buf) { | ||
96 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | dev->iamthif_msg_buf = msg_buf; | ||
101 | |||
102 | if (mei_connect(dev, &dev->iamthif_cl)) { | ||
103 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | ||
104 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
105 | dev->iamthif_cl.host_client_id = 0; | ||
106 | } else { | ||
107 | dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * mei_amthif_find_read_list_entry - finds a amthilist entry for current file | ||
113 | * | ||
114 | * @dev: the device structure | ||
115 | * @file: pointer to file object | ||
116 | * | ||
117 | * returns returned a list entry on success, NULL on failure. | ||
118 | */ | ||
119 | struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, | ||
120 | struct file *file) | ||
121 | { | ||
122 | struct mei_cl_cb *pos = NULL; | ||
123 | struct mei_cl_cb *next = NULL; | ||
124 | |||
125 | list_for_each_entry_safe(pos, next, | ||
126 | &dev->amthif_rd_complete_list.list, list) { | ||
127 | if (pos->cl && pos->cl == &dev->iamthif_cl && | ||
128 | pos->file_object == file) | ||
129 | return pos; | ||
130 | } | ||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * mei_amthif_read - read data from AMTHIF client | ||
137 | * | ||
138 | * @dev: the device structure | ||
139 | * @if_num: minor number | ||
140 | * @file: pointer to file object | ||
141 | * @*ubuf: pointer to user data in user space | ||
142 | * @length: data length to read | ||
143 | * @offset: data read offset | ||
144 | * | ||
145 | * Locking: called under "dev->device_lock" lock | ||
146 | * | ||
147 | * returns | ||
148 | * returned data length on success, | ||
149 | * zero if no data to read, | ||
150 | * negative on failure. | ||
151 | */ | ||
152 | int mei_amthif_read(struct mei_device *dev, struct file *file, | ||
153 | char __user *ubuf, size_t length, loff_t *offset) | ||
154 | { | ||
155 | int rets; | ||
156 | int wait_ret; | ||
157 | struct mei_cl_cb *cb = NULL; | ||
158 | struct mei_cl *cl = file->private_data; | ||
159 | unsigned long timeout; | ||
160 | int i; | ||
161 | |||
162 | /* Only Posible if we are in timeout */ | ||
163 | if (!cl || cl != &dev->iamthif_cl) { | ||
164 | dev_dbg(&dev->pdev->dev, "bad file ext.\n"); | ||
165 | return -ETIMEDOUT; | ||
166 | } | ||
167 | |||
168 | i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); | ||
169 | |||
170 | if (i < 0) { | ||
171 | dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); | ||
172 | return -ENODEV; | ||
173 | } | ||
174 | dev_dbg(&dev->pdev->dev, "checking amthi data\n"); | ||
175 | cb = mei_amthif_find_read_list_entry(dev, file); | ||
176 | |||
177 | /* Check for if we can block or not*/ | ||
178 | if (cb == NULL && file->f_flags & O_NONBLOCK) | ||
179 | return -EAGAIN; | ||
180 | |||
181 | |||
182 | dev_dbg(&dev->pdev->dev, "waiting for amthi data\n"); | ||
183 | while (cb == NULL) { | ||
184 | /* unlock the Mutex */ | ||
185 | mutex_unlock(&dev->device_lock); | ||
186 | |||
187 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | ||
188 | (cb = mei_amthif_find_read_list_entry(dev, file))); | ||
189 | |||
190 | if (wait_ret) | ||
191 | return -ERESTARTSYS; | ||
192 | |||
193 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | ||
194 | |||
195 | /* Locking again the Mutex */ | ||
196 | mutex_lock(&dev->device_lock); | ||
197 | } | ||
198 | |||
199 | |||
200 | dev_dbg(&dev->pdev->dev, "Got amthi data\n"); | ||
201 | dev->iamthif_timer = 0; | ||
202 | |||
203 | if (cb) { | ||
204 | timeout = cb->read_time + | ||
205 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); | ||
206 | dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", | ||
207 | timeout); | ||
208 | |||
209 | if (time_after(jiffies, timeout)) { | ||
210 | dev_dbg(&dev->pdev->dev, "amthi Time out\n"); | ||
211 | /* 15 sec for the message has expired */ | ||
212 | list_del(&cb->list); | ||
213 | rets = -ETIMEDOUT; | ||
214 | goto free; | ||
215 | } | ||
216 | } | ||
217 | /* if the whole message will fit remove it from the list */ | ||
218 | if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) | ||
219 | list_del(&cb->list); | ||
220 | else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { | ||
221 | /* end of the message has been reached */ | ||
222 | list_del(&cb->list); | ||
223 | rets = 0; | ||
224 | goto free; | ||
225 | } | ||
226 | /* else means that not full buffer will be read and do not | ||
227 | * remove message from deletion list | ||
228 | */ | ||
229 | |||
230 | dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n", | ||
231 | cb->response_buffer.size); | ||
232 | dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx); | ||
233 | |||
234 | /* length is being turncated to PAGE_SIZE, however, | ||
235 | * the buf_idx may point beyond */ | ||
236 | length = min_t(size_t, length, (cb->buf_idx - *offset)); | ||
237 | |||
238 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) | ||
239 | rets = -EFAULT; | ||
240 | else { | ||
241 | rets = length; | ||
242 | if ((*offset + length) < cb->buf_idx) { | ||
243 | *offset += length; | ||
244 | goto out; | ||
245 | } | ||
246 | } | ||
247 | free: | ||
248 | dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n"); | ||
249 | *offset = 0; | ||
250 | mei_io_cb_free(cb); | ||
251 | out: | ||
252 | return rets; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * mei_amthif_send_cmd - send amthif command to the ME | ||
257 | * | ||
258 | * @dev: the device structure | ||
259 | * @cb: mei call back struct | ||
260 | * | ||
261 | * returns 0 on success, <0 on failure. | ||
262 | * | ||
263 | */ | ||
264 | static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | ||
265 | { | ||
266 | struct mei_msg_hdr mei_hdr; | ||
267 | int ret; | ||
268 | |||
269 | if (!dev || !cb) | ||
270 | return -ENODEV; | ||
271 | |||
272 | dev_dbg(&dev->pdev->dev, "write data to amthi client.\n"); | ||
273 | |||
274 | dev->iamthif_state = MEI_IAMTHIF_WRITING; | ||
275 | dev->iamthif_current_cb = cb; | ||
276 | dev->iamthif_file_object = cb->file_object; | ||
277 | dev->iamthif_canceled = false; | ||
278 | dev->iamthif_ioctl = true; | ||
279 | dev->iamthif_msg_buf_size = cb->request_buffer.size; | ||
280 | memcpy(dev->iamthif_msg_buf, cb->request_buffer.data, | ||
281 | cb->request_buffer.size); | ||
282 | |||
283 | ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl); | ||
284 | if (ret < 0) | ||
285 | return ret; | ||
286 | |||
287 | if (ret && dev->mei_host_buffer_is_empty) { | ||
288 | ret = 0; | ||
289 | dev->mei_host_buffer_is_empty = false; | ||
290 | if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { | ||
291 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
292 | mei_hdr.msg_complete = 0; | ||
293 | } else { | ||
294 | mei_hdr.length = cb->request_buffer.size; | ||
295 | mei_hdr.msg_complete = 1; | ||
296 | } | ||
297 | |||
298 | mei_hdr.host_addr = dev->iamthif_cl.host_client_id; | ||
299 | mei_hdr.me_addr = dev->iamthif_cl.me_client_id; | ||
300 | mei_hdr.reserved = 0; | ||
301 | dev->iamthif_msg_buf_index += mei_hdr.length; | ||
302 | if (mei_write_message(dev, &mei_hdr, | ||
303 | (unsigned char *)(dev->iamthif_msg_buf), | ||
304 | mei_hdr.length)) | ||
305 | return -ENODEV; | ||
306 | |||
307 | if (mei_hdr.msg_complete) { | ||
308 | if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl)) | ||
309 | return -ENODEV; | ||
310 | dev->iamthif_flow_control_pending = true; | ||
311 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
312 | dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n"); | ||
313 | dev->iamthif_current_cb = cb; | ||
314 | dev->iamthif_file_object = cb->file_object; | ||
315 | list_add_tail(&cb->list, &dev->write_waiting_list.list); | ||
316 | } else { | ||
317 | dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n"); | ||
318 | list_add_tail(&cb->list, &dev->write_list.list); | ||
319 | } | ||
320 | } else { | ||
321 | if (!(dev->mei_host_buffer_is_empty)) | ||
322 | dev_dbg(&dev->pdev->dev, "host buffer is not empty"); | ||
323 | |||
324 | dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n"); | ||
325 | list_add_tail(&cb->list, &dev->write_list.list); | ||
326 | } | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /** | ||
331 | * mei_amthif_write - write amthif data to amthif client | ||
332 | * | ||
333 | * @dev: the device structure | ||
334 | * @cb: mei call back struct | ||
335 | * | ||
336 | * returns 0 on success, <0 on failure. | ||
337 | * | ||
338 | */ | ||
339 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) | ||
340 | { | ||
341 | int ret; | ||
342 | |||
343 | if (!dev || !cb) | ||
344 | return -ENODEV; | ||
345 | |||
346 | ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu); | ||
347 | if (ret) | ||
348 | return ret; | ||
349 | |||
350 | cb->fop_type = MEI_FOP_IOCTL; | ||
351 | |||
352 | if (!list_empty(&dev->amthif_cmd_list.list) || | ||
353 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { | ||
354 | dev_dbg(&dev->pdev->dev, | ||
355 | "amthif state = %d\n", dev->iamthif_state); | ||
356 | dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n"); | ||
357 | list_add_tail(&cb->list, &dev->amthif_cmd_list.list); | ||
358 | return 0; | ||
359 | } | ||
360 | return mei_amthif_send_cmd(dev, cb); | ||
361 | } | ||
362 | /** | ||
363 | * mei_amthif_run_next_cmd | ||
364 | * | ||
365 | * @dev: the device structure | ||
366 | * | ||
367 | * returns 0 on success, <0 on failure. | ||
368 | */ | ||
369 | void mei_amthif_run_next_cmd(struct mei_device *dev) | ||
370 | { | ||
371 | struct mei_cl_cb *pos = NULL; | ||
372 | struct mei_cl_cb *next = NULL; | ||
373 | int status; | ||
374 | |||
375 | if (!dev) | ||
376 | return; | ||
377 | |||
378 | dev->iamthif_msg_buf_size = 0; | ||
379 | dev->iamthif_msg_buf_index = 0; | ||
380 | dev->iamthif_canceled = false; | ||
381 | dev->iamthif_ioctl = true; | ||
382 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
383 | dev->iamthif_timer = 0; | ||
384 | dev->iamthif_file_object = NULL; | ||
385 | |||
386 | dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n"); | ||
387 | |||
388 | list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) { | ||
389 | list_del(&pos->list); | ||
390 | |||
391 | if (pos->cl && pos->cl == &dev->iamthif_cl) { | ||
392 | status = mei_amthif_send_cmd(dev, pos); | ||
393 | if (status) { | ||
394 | dev_dbg(&dev->pdev->dev, | ||
395 | "amthi write failed status = %d\n", | ||
396 | status); | ||
397 | return; | ||
398 | } | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | |||
405 | unsigned int mei_amthif_poll(struct mei_device *dev, | ||
406 | struct file *file, poll_table *wait) | ||
407 | { | ||
408 | unsigned int mask = 0; | ||
409 | mutex_unlock(&dev->device_lock); | ||
410 | poll_wait(file, &dev->iamthif_cl.wait, wait); | ||
411 | mutex_lock(&dev->device_lock); | ||
412 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && | ||
413 | dev->iamthif_file_object == file) { | ||
414 | mask |= (POLLIN | POLLRDNORM); | ||
415 | dev_dbg(&dev->pdev->dev, "run next amthi cb\n"); | ||
416 | mei_amthif_run_next_cmd(dev); | ||
417 | } | ||
418 | return mask; | ||
419 | } | ||
420 | |||
421 | |||
422 | |||
423 | /** | ||
424 | * mei_amthif_irq_process_completed - processes completed iamthif operation. | ||
425 | * | ||
426 | * @dev: the device structure. | ||
427 | * @slots: free slots. | ||
428 | * @cb_pos: callback block. | ||
429 | * @cl: private data of the file object. | ||
430 | * @cmpl_list: complete list. | ||
431 | * | ||
432 | * returns 0, OK; otherwise, error. | ||
433 | */ | ||
434 | int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots, | ||
435 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) | ||
436 | { | ||
437 | struct mei_msg_hdr *mei_hdr; | ||
438 | struct mei_cl *cl = cb->cl; | ||
439 | size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index; | ||
440 | size_t msg_slots = mei_data2slots(len); | ||
441 | |||
442 | mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; | ||
443 | mei_hdr->host_addr = cl->host_client_id; | ||
444 | mei_hdr->me_addr = cl->me_client_id; | ||
445 | mei_hdr->reserved = 0; | ||
446 | |||
447 | if (*slots >= msg_slots) { | ||
448 | mei_hdr->length = len; | ||
449 | mei_hdr->msg_complete = 1; | ||
450 | /* Split the message only if we can write the whole host buffer */ | ||
451 | } else if (*slots == dev->hbuf_depth) { | ||
452 | msg_slots = *slots; | ||
453 | len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
454 | mei_hdr->length = len; | ||
455 | mei_hdr->msg_complete = 0; | ||
456 | } else { | ||
457 | /* wait for next time the host buffer is empty */ | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n", | ||
462 | mei_hdr->length, mei_hdr->msg_complete); | ||
463 | |||
464 | *slots -= msg_slots; | ||
465 | if (mei_write_message(dev, mei_hdr, | ||
466 | dev->iamthif_msg_buf + dev->iamthif_msg_buf_index, | ||
467 | mei_hdr->length)) { | ||
468 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
469 | cl->status = -ENODEV; | ||
470 | list_del(&cb->list); | ||
471 | return -ENODEV; | ||
472 | } | ||
473 | |||
474 | if (mei_flow_ctrl_reduce(dev, cl)) | ||
475 | return -ENODEV; | ||
476 | |||
477 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
478 | cl->status = 0; | ||
479 | |||
480 | if (mei_hdr->msg_complete) { | ||
481 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
482 | dev->iamthif_flow_control_pending = true; | ||
483 | |||
484 | /* save iamthif cb sent to amthi client */ | ||
485 | cb->buf_idx = dev->iamthif_msg_buf_index; | ||
486 | dev->iamthif_current_cb = cb; | ||
487 | |||
488 | list_move_tail(&cb->list, &dev->write_waiting_list.list); | ||
489 | } | ||
490 | |||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * mei_amthif_irq_read_message - read routine after ISR to | ||
497 | * handle the read amthi message | ||
498 | * | ||
499 | * @complete_list: An instance of our list structure | ||
500 | * @dev: the device structure | ||
501 | * @mei_hdr: header of amthi message | ||
502 | * | ||
503 | * returns 0 on success, <0 on failure. | ||
504 | */ | ||
505 | int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list, | ||
506 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr) | ||
507 | { | ||
508 | struct mei_cl_cb *cb; | ||
509 | unsigned char *buffer; | ||
510 | |||
511 | BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); | ||
512 | BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); | ||
513 | |||
514 | buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; | ||
515 | BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); | ||
516 | |||
517 | mei_read_slots(dev, buffer, mei_hdr->length); | ||
518 | |||
519 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
520 | |||
521 | if (!mei_hdr->msg_complete) | ||
522 | return 0; | ||
523 | |||
524 | dev_dbg(&dev->pdev->dev, | ||
525 | "amthi_message_buffer_index =%d\n", | ||
526 | mei_hdr->length); | ||
527 | |||
528 | dev_dbg(&dev->pdev->dev, "completed amthi read.\n "); | ||
529 | if (!dev->iamthif_current_cb) | ||
530 | return -ENODEV; | ||
531 | |||
532 | cb = dev->iamthif_current_cb; | ||
533 | dev->iamthif_current_cb = NULL; | ||
534 | |||
535 | if (!cb->cl) | ||
536 | return -ENODEV; | ||
537 | |||
538 | dev->iamthif_stall_timer = 0; | ||
539 | cb->buf_idx = dev->iamthif_msg_buf_index; | ||
540 | cb->read_time = jiffies; | ||
541 | if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) { | ||
542 | /* found the iamthif cb */ | ||
543 | dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n "); | ||
544 | dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n "); | ||
545 | list_add_tail(&cb->list, &complete_list->list); | ||
546 | } | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * mei_amthif_irq_read - prepares to read amthif data. | ||
552 | * | ||
553 | * @dev: the device structure. | ||
554 | * @slots: free slots. | ||
555 | * | ||
556 | * returns 0, OK; otherwise, error. | ||
557 | */ | ||
558 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) | ||
559 | { | ||
560 | |||
561 | if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr) | ||
562 | + sizeof(struct hbm_flow_control))) { | ||
563 | return -EMSGSIZE; | ||
564 | } | ||
565 | *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); | ||
566 | if (mei_send_flow_control(dev, &dev->iamthif_cl)) { | ||
567 | dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); | ||
568 | return -EIO; | ||
569 | } | ||
570 | |||
571 | dev_dbg(&dev->pdev->dev, "iamthif flow control success\n"); | ||
572 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
573 | dev->iamthif_flow_control_pending = false; | ||
574 | dev->iamthif_msg_buf_index = 0; | ||
575 | dev->iamthif_msg_buf_size = 0; | ||
576 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | ||
577 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * mei_amthif_complete - complete amthif callback. | ||
583 | * | ||
584 | * @dev: the device structure. | ||
585 | * @cb_pos: callback block. | ||
586 | */ | ||
587 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) | ||
588 | { | ||
589 | if (dev->iamthif_canceled != 1) { | ||
590 | dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; | ||
591 | dev->iamthif_stall_timer = 0; | ||
592 | memcpy(cb->response_buffer.data, | ||
593 | dev->iamthif_msg_buf, | ||
594 | dev->iamthif_msg_buf_index); | ||
595 | list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); | ||
596 | dev_dbg(&dev->pdev->dev, "amthi read completed\n"); | ||
597 | dev->iamthif_timer = jiffies; | ||
598 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", | ||
599 | dev->iamthif_timer); | ||
600 | } else { | ||
601 | mei_amthif_run_next_cmd(dev); | ||
602 | } | ||
603 | |||
604 | dev_dbg(&dev->pdev->dev, "completing amthi call back.\n"); | ||
605 | wake_up_interruptible(&dev->iamthif_cl.wait); | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * mei_clear_list - removes all callbacks associated with file | ||
610 | * from mei_cb_list | ||
611 | * | ||
612 | * @dev: device structure. | ||
613 | * @file: file structure | ||
614 | * @mei_cb_list: callbacks list | ||
615 | * | ||
616 | * mei_clear_list is called to clear resources associated with file | ||
617 | * when application calls close function or Ctrl-C was pressed | ||
618 | * | ||
619 | * returns true if callback removed from the list, false otherwise | ||
620 | */ | ||
621 | static bool mei_clear_list(struct mei_device *dev, | ||
622 | const struct file *file, struct list_head *mei_cb_list) | ||
623 | { | ||
624 | struct mei_cl_cb *cb_pos = NULL; | ||
625 | struct mei_cl_cb *cb_next = NULL; | ||
626 | bool removed = false; | ||
627 | |||
628 | /* list all list member */ | ||
629 | list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) { | ||
630 | /* check if list member associated with a file */ | ||
631 | if (file == cb_pos->file_object) { | ||
632 | /* remove member from the list */ | ||
633 | list_del(&cb_pos->list); | ||
634 | /* check if cb equal to current iamthif cb */ | ||
635 | if (dev->iamthif_current_cb == cb_pos) { | ||
636 | dev->iamthif_current_cb = NULL; | ||
637 | /* send flow control to iamthif client */ | ||
638 | mei_send_flow_control(dev, &dev->iamthif_cl); | ||
639 | } | ||
640 | /* free all allocated buffers */ | ||
641 | mei_io_cb_free(cb_pos); | ||
642 | cb_pos = NULL; | ||
643 | removed = true; | ||
644 | } | ||
645 | } | ||
646 | return removed; | ||
647 | } | ||
648 | |||
649 | /** | ||
650 | * mei_clear_lists - removes all callbacks associated with file | ||
651 | * | ||
652 | * @dev: device structure | ||
653 | * @file: file structure | ||
654 | * | ||
655 | * mei_clear_lists is called to clear resources associated with file | ||
656 | * when application calls close function or Ctrl-C was pressed | ||
657 | * | ||
658 | * returns true if callback removed from the list, false otherwise | ||
659 | */ | ||
660 | static bool mei_clear_lists(struct mei_device *dev, struct file *file) | ||
661 | { | ||
662 | bool removed = false; | ||
663 | |||
664 | /* remove callbacks associated with a file */ | ||
665 | mei_clear_list(dev, file, &dev->amthif_cmd_list.list); | ||
666 | if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list)) | ||
667 | removed = true; | ||
668 | |||
669 | mei_clear_list(dev, file, &dev->ctrl_rd_list.list); | ||
670 | |||
671 | if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list)) | ||
672 | removed = true; | ||
673 | |||
674 | if (mei_clear_list(dev, file, &dev->write_waiting_list.list)) | ||
675 | removed = true; | ||
676 | |||
677 | if (mei_clear_list(dev, file, &dev->write_list.list)) | ||
678 | removed = true; | ||
679 | |||
680 | /* check if iamthif_current_cb not NULL */ | ||
681 | if (dev->iamthif_current_cb && !removed) { | ||
682 | /* check file and iamthif current cb association */ | ||
683 | if (dev->iamthif_current_cb->file_object == file) { | ||
684 | /* remove cb */ | ||
685 | mei_io_cb_free(dev->iamthif_current_cb); | ||
686 | dev->iamthif_current_cb = NULL; | ||
687 | removed = true; | ||
688 | } | ||
689 | } | ||
690 | return removed; | ||
691 | } | ||
692 | |||
693 | /** | ||
694 | * mei_amthif_release - the release function | ||
695 | * | ||
696 | * @inode: pointer to inode structure | ||
697 | * @file: pointer to file structure | ||
698 | * | ||
699 | * returns 0 on success, <0 on error | ||
700 | */ | ||
701 | int mei_amthif_release(struct mei_device *dev, struct file *file) | ||
702 | { | ||
703 | if (dev->open_handle_count > 0) | ||
704 | dev->open_handle_count--; | ||
705 | |||
706 | if (dev->iamthif_file_object == file && | ||
707 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { | ||
708 | |||
709 | dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n", | ||
710 | dev->iamthif_state); | ||
711 | dev->iamthif_canceled = true; | ||
712 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) { | ||
713 | dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n"); | ||
714 | mei_amthif_run_next_cmd(dev); | ||
715 | } | ||
716 | } | ||
717 | |||
718 | if (mei_clear_lists(dev, file)) | ||
719 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
720 | |||
721 | return 0; | ||
722 | } | ||
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 9700532f02f6..be8ca6b333ca 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h | |||
@@ -20,16 +20,16 @@ | |||
20 | #include <linux/uuid.h> | 20 | #include <linux/uuid.h> |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * Timeouts | 23 | * Timeouts in Seconds |
24 | */ | 24 | */ |
25 | #define MEI_INTEROP_TIMEOUT (HZ * 7) | 25 | #define MEI_INTEROP_TIMEOUT 7 /* Timeout on ready message */ |
26 | #define MEI_CONNECT_TIMEOUT 3 /* at least 2 seconds */ | 26 | #define MEI_CONNECT_TIMEOUT 3 /* HPS: at least 2 seconds */ |
27 | 27 | ||
28 | #define CONNECT_TIMEOUT 15 /* HPS definition */ | 28 | #define MEI_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */ |
29 | #define INIT_CLIENTS_TIMEOUT 15 /* HPS definition */ | 29 | #define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */ |
30 | 30 | ||
31 | #define IAMTHIF_STALL_TIMER 12 /* seconds */ | 31 | #define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */ |
32 | #define IAMTHIF_READ_TIMER 10000 /* ms */ | 32 | #define MEI_IAMTHIF_READ_TIMER 10 /* HPS */ |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Internal Clients Number | 35 | * Internal Clients Number |
@@ -293,6 +293,14 @@ struct hbm_props_response { | |||
293 | struct mei_client_properties client_properties; | 293 | struct mei_client_properties client_properties; |
294 | } __packed; | 294 | } __packed; |
295 | 295 | ||
296 | /** | ||
297 | * struct hbm_client_connect_request - connect/disconnect request | ||
298 | * | ||
299 | * @hbm_cmd - bus message command header | ||
300 | * @me_addr - address of the client in ME | ||
301 | * @host_addr - address of the client in the driver | ||
302 | * @reserved | ||
303 | */ | ||
296 | struct hbm_client_connect_request { | 304 | struct hbm_client_connect_request { |
297 | u8 hbm_cmd; | 305 | u8 hbm_cmd; |
298 | u8 me_addr; | 306 | u8 me_addr; |
@@ -300,6 +308,14 @@ struct hbm_client_connect_request { | |||
300 | u8 reserved; | 308 | u8 reserved; |
301 | } __packed; | 309 | } __packed; |
302 | 310 | ||
311 | /** | ||
312 | * struct hbm_client_connect_response - connect/disconnect response | ||
313 | * | ||
314 | * @hbm_cmd - bus message command header | ||
315 | * @me_addr - address of the client in ME | ||
316 | * @host_addr - address of the client in the driver | ||
317 | * @status - status of the request | ||
318 | */ | ||
303 | struct hbm_client_connect_response { | 319 | struct hbm_client_connect_response { |
304 | u8 hbm_cmd; | 320 | u8 hbm_cmd; |
305 | u8 me_addr; | 321 | u8 me_addr; |
@@ -307,12 +323,6 @@ struct hbm_client_connect_response { | |||
307 | u8 status; | 323 | u8 status; |
308 | } __packed; | 324 | } __packed; |
309 | 325 | ||
310 | struct hbm_client_disconnect_request { | ||
311 | u8 hbm_cmd; | ||
312 | u8 me_addr; | ||
313 | u8 host_addr; | ||
314 | u8 reserved[1]; | ||
315 | } __packed; | ||
316 | 326 | ||
317 | #define MEI_FC_MESSAGE_RESERVED_LENGTH 5 | 327 | #define MEI_FC_MESSAGE_RESERVED_LENGTH 5 |
318 | 328 | ||
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 98f1430e3e14..a54cd5567ca2 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -43,21 +43,6 @@ const char *mei_dev_state_str(int state) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | 45 | ||
46 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | ||
47 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | ||
48 | 0x81, 0x4c); | ||
49 | |||
50 | /** | ||
51 | * mei_io_list_init - Sets up a queue list. | ||
52 | * | ||
53 | * @list: An instance io list structure | ||
54 | * @dev: the device structure | ||
55 | */ | ||
56 | void mei_io_list_init(struct mei_io_list *list) | ||
57 | { | ||
58 | /* initialize our queue list */ | ||
59 | INIT_LIST_HEAD(&list->mei_cb.cb_list); | ||
60 | } | ||
61 | 46 | ||
62 | /** | 47 | /** |
63 | * mei_io_list_flush - removes list entry belonging to cl. | 48 | * mei_io_list_flush - removes list entry belonging to cl. |
@@ -65,17 +50,15 @@ void mei_io_list_init(struct mei_io_list *list) | |||
65 | * @list: An instance of our list structure | 50 | * @list: An instance of our list structure |
66 | * @cl: private data of the file object | 51 | * @cl: private data of the file object |
67 | */ | 52 | */ |
68 | void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl) | 53 | void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) |
69 | { | 54 | { |
70 | struct mei_cl_cb *pos; | 55 | struct mei_cl_cb *pos; |
71 | struct mei_cl_cb *next; | 56 | struct mei_cl_cb *next; |
72 | 57 | ||
73 | list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) { | 58 | list_for_each_entry_safe(pos, next, &list->list, list) { |
74 | if (pos->file_private) { | 59 | if (pos->cl) { |
75 | struct mei_cl *cl_tmp; | 60 | if (mei_cl_cmp_id(cl, pos->cl)) |
76 | cl_tmp = (struct mei_cl *)pos->file_private; | 61 | list_del(&pos->list); |
77 | if (mei_cl_cmp_id(cl, cl_tmp)) | ||
78 | list_del(&pos->cb_list); | ||
79 | } | 62 | } |
80 | } | 63 | } |
81 | } | 64 | } |
@@ -96,31 +79,14 @@ int mei_cl_flush_queues(struct mei_cl *cl) | |||
96 | mei_io_list_flush(&cl->dev->write_waiting_list, cl); | 79 | mei_io_list_flush(&cl->dev->write_waiting_list, cl); |
97 | mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); | 80 | mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); |
98 | mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); | 81 | mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); |
99 | mei_io_list_flush(&cl->dev->amthi_cmd_list, cl); | 82 | mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); |
100 | mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl); | 83 | mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); |
101 | return 0; | 84 | return 0; |
102 | } | 85 | } |
103 | 86 | ||
104 | 87 | ||
105 | 88 | ||
106 | /** | 89 | /** |
107 | * mei_reset_iamthif_params - initializes mei device iamthif | ||
108 | * | ||
109 | * @dev: the device structure | ||
110 | */ | ||
111 | static void mei_reset_iamthif_params(struct mei_device *dev) | ||
112 | { | ||
113 | /* reset iamthif parameters. */ | ||
114 | dev->iamthif_current_cb = NULL; | ||
115 | dev->iamthif_msg_buf_size = 0; | ||
116 | dev->iamthif_msg_buf_index = 0; | ||
117 | dev->iamthif_canceled = false; | ||
118 | dev->iamthif_ioctl = false; | ||
119 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
120 | dev->iamthif_timer = 0; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * init_mei_device - allocates and initializes the mei device structure | 90 | * init_mei_device - allocates and initializes the mei device structure |
125 | * | 91 | * |
126 | * @pdev: The pci device structure | 92 | * @pdev: The pci device structure |
@@ -144,16 +110,14 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) | |||
144 | init_waitqueue_head(&dev->wait_stop_wd); | 110 | init_waitqueue_head(&dev->wait_stop_wd); |
145 | dev->dev_state = MEI_DEV_INITIALIZING; | 111 | dev->dev_state = MEI_DEV_INITIALIZING; |
146 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | 112 | dev->iamthif_state = MEI_IAMTHIF_IDLE; |
147 | dev->wd_interface_reg = false; | ||
148 | |||
149 | 113 | ||
150 | mei_io_list_init(&dev->read_list); | 114 | mei_io_list_init(&dev->read_list); |
151 | mei_io_list_init(&dev->write_list); | 115 | mei_io_list_init(&dev->write_list); |
152 | mei_io_list_init(&dev->write_waiting_list); | 116 | mei_io_list_init(&dev->write_waiting_list); |
153 | mei_io_list_init(&dev->ctrl_wr_list); | 117 | mei_io_list_init(&dev->ctrl_wr_list); |
154 | mei_io_list_init(&dev->ctrl_rd_list); | 118 | mei_io_list_init(&dev->ctrl_rd_list); |
155 | mei_io_list_init(&dev->amthi_cmd_list); | 119 | mei_io_list_init(&dev->amthif_cmd_list); |
156 | mei_io_list_init(&dev->amthi_read_complete_list); | 120 | mei_io_list_init(&dev->amthif_rd_complete_list); |
157 | dev->pdev = pdev; | 121 | dev->pdev = pdev; |
158 | return dev; | 122 | return dev; |
159 | } | 123 | } |
@@ -196,7 +160,8 @@ int mei_hw_init(struct mei_device *dev) | |||
196 | if (!dev->recvd_msg) { | 160 | if (!dev->recvd_msg) { |
197 | mutex_unlock(&dev->device_lock); | 161 | mutex_unlock(&dev->device_lock); |
198 | err = wait_event_interruptible_timeout(dev->wait_recvd_msg, | 162 | err = wait_event_interruptible_timeout(dev->wait_recvd_msg, |
199 | dev->recvd_msg, MEI_INTEROP_TIMEOUT); | 163 | dev->recvd_msg, |
164 | mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); | ||
200 | mutex_lock(&dev->device_lock); | 165 | mutex_lock(&dev->device_lock); |
201 | } | 166 | } |
202 | 167 | ||
@@ -317,15 +282,13 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
317 | cl_pos->timer_count = 0; | 282 | cl_pos->timer_count = 0; |
318 | } | 283 | } |
319 | /* remove entry if already in list */ | 284 | /* remove entry if already in list */ |
320 | dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n"); | 285 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); |
321 | mei_remove_client_from_file_list(dev, | 286 | mei_me_cl_unlink(dev, &dev->wd_cl); |
322 | dev->wd_cl.host_client_id); | ||
323 | 287 | ||
324 | mei_remove_client_from_file_list(dev, | 288 | mei_me_cl_unlink(dev, &dev->iamthif_cl); |
325 | dev->iamthif_cl.host_client_id); | ||
326 | 289 | ||
327 | mei_reset_iamthif_params(dev); | 290 | mei_amthif_reset_params(dev); |
328 | dev->extra_write_index = 0; | 291 | memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); |
329 | } | 292 | } |
330 | 293 | ||
331 | dev->me_clients_num = 0; | 294 | dev->me_clients_num = 0; |
@@ -351,10 +314,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
351 | } | 314 | } |
352 | } | 315 | } |
353 | /* remove all waiting requests */ | 316 | /* remove all waiting requests */ |
354 | list_for_each_entry_safe(cb_pos, cb_next, | 317 | list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) { |
355 | &dev->write_list.mei_cb.cb_list, cb_list) { | 318 | list_del(&cb_pos->list); |
356 | list_del(&cb_pos->cb_list); | 319 | mei_io_cb_free(cb_pos); |
357 | mei_free_cb_private(cb_pos); | ||
358 | } | 320 | } |
359 | } | 321 | } |
360 | 322 | ||
@@ -370,31 +332,26 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
370 | void mei_host_start_message(struct mei_device *dev) | 332 | void mei_host_start_message(struct mei_device *dev) |
371 | { | 333 | { |
372 | struct mei_msg_hdr *mei_hdr; | 334 | struct mei_msg_hdr *mei_hdr; |
373 | struct hbm_host_version_request *host_start_req; | 335 | struct hbm_host_version_request *start_req; |
336 | const size_t len = sizeof(struct hbm_host_version_request); | ||
337 | |||
338 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
374 | 339 | ||
375 | /* host start message */ | 340 | /* host start message */ |
376 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 341 | start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1]; |
377 | mei_hdr->host_addr = 0; | 342 | memset(start_req, 0, len); |
378 | mei_hdr->me_addr = 0; | 343 | start_req->hbm_cmd = HOST_START_REQ_CMD; |
379 | mei_hdr->length = sizeof(struct hbm_host_version_request); | 344 | start_req->host_version.major_version = HBM_MAJOR_VERSION; |
380 | mei_hdr->msg_complete = 1; | 345 | start_req->host_version.minor_version = HBM_MINOR_VERSION; |
381 | mei_hdr->reserved = 0; | 346 | |
382 | |||
383 | host_start_req = | ||
384 | (struct hbm_host_version_request *) &dev->wr_msg_buf[1]; | ||
385 | memset(host_start_req, 0, sizeof(struct hbm_host_version_request)); | ||
386 | host_start_req->hbm_cmd = HOST_START_REQ_CMD; | ||
387 | host_start_req->host_version.major_version = HBM_MAJOR_VERSION; | ||
388 | host_start_req->host_version.minor_version = HBM_MINOR_VERSION; | ||
389 | dev->recvd_msg = false; | 347 | dev->recvd_msg = false; |
390 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, | 348 | if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) { |
391 | mei_hdr->length)) { | ||
392 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); | 349 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); |
393 | dev->dev_state = MEI_DEV_RESETING; | 350 | dev->dev_state = MEI_DEV_RESETING; |
394 | mei_reset(dev, 1); | 351 | mei_reset(dev, 1); |
395 | } | 352 | } |
396 | dev->init_clients_state = MEI_START_MESSAGE; | 353 | dev->init_clients_state = MEI_START_MESSAGE; |
397 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 354 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
398 | return ; | 355 | return ; |
399 | } | 356 | } |
400 | 357 | ||
@@ -408,26 +365,22 @@ void mei_host_start_message(struct mei_device *dev) | |||
408 | void mei_host_enum_clients_message(struct mei_device *dev) | 365 | void mei_host_enum_clients_message(struct mei_device *dev) |
409 | { | 366 | { |
410 | struct mei_msg_hdr *mei_hdr; | 367 | struct mei_msg_hdr *mei_hdr; |
411 | struct hbm_host_enum_request *host_enum_req; | 368 | struct hbm_host_enum_request *enum_req; |
412 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 369 | const size_t len = sizeof(struct hbm_host_enum_request); |
413 | /* enumerate clients */ | 370 | /* enumerate clients */ |
414 | mei_hdr->host_addr = 0; | 371 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); |
415 | mei_hdr->me_addr = 0; | 372 | |
416 | mei_hdr->length = sizeof(struct hbm_host_enum_request); | 373 | enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; |
417 | mei_hdr->msg_complete = 1; | 374 | memset(enum_req, 0, sizeof(struct hbm_host_enum_request)); |
418 | mei_hdr->reserved = 0; | 375 | enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; |
419 | 376 | ||
420 | host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; | 377 | if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) { |
421 | memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); | ||
422 | host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; | ||
423 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, | ||
424 | mei_hdr->length)) { | ||
425 | dev->dev_state = MEI_DEV_RESETING; | 378 | dev->dev_state = MEI_DEV_RESETING; |
426 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | 379 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); |
427 | mei_reset(dev, 1); | 380 | mei_reset(dev, 1); |
428 | } | 381 | } |
429 | dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; | 382 | dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; |
430 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 383 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
431 | return; | 384 | return; |
432 | } | 385 | } |
433 | 386 | ||
@@ -470,56 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) | |||
470 | dev->me_clients = clients; | 423 | dev->me_clients = clients; |
471 | return ; | 424 | return ; |
472 | } | 425 | } |
473 | /** | 426 | |
474 | * host_client_properties - reads properties for client | 427 | void mei_host_client_init(struct work_struct *work) |
475 | * | ||
476 | * @dev: the device structure | ||
477 | * | ||
478 | * returns: | ||
479 | * < 0 - Error. | ||
480 | * = 0 - no more clients. | ||
481 | * = 1 - still have clients to send properties request. | ||
482 | */ | ||
483 | int mei_host_client_properties(struct mei_device *dev) | ||
484 | { | 428 | { |
485 | struct mei_msg_hdr *mei_header; | 429 | struct mei_device *dev = container_of(work, |
486 | struct hbm_props_request *host_cli_req; | 430 | struct mei_device, init_work); |
487 | int b; | 431 | struct mei_client_properties *client_props; |
488 | u8 client_num = dev->me_client_presentation_num; | 432 | int i; |
489 | 433 | ||
490 | b = dev->me_client_index; | 434 | mutex_lock(&dev->device_lock); |
491 | b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b); | 435 | |
492 | if (b < MEI_CLIENTS_MAX) { | 436 | bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); |
493 | dev->me_clients[client_num].client_id = b; | 437 | dev->open_handle_count = 0; |
494 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; | 438 | |
495 | mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; | 439 | /* |
496 | mei_header->host_addr = 0; | 440 | * Reserving the first three client IDs |
497 | mei_header->me_addr = 0; | 441 | * 0: Reserved for MEI Bus Message communications |
498 | mei_header->length = sizeof(struct hbm_props_request); | 442 | * 1: Reserved for Watchdog |
499 | mei_header->msg_complete = 1; | 443 | * 2: Reserved for AMTHI |
500 | mei_header->reserved = 0; | 444 | */ |
501 | 445 | bitmap_set(dev->host_clients_map, 0, 3); | |
502 | host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | 446 | |
503 | 447 | for (i = 0; i < dev->me_clients_num; i++) { | |
504 | memset(host_cli_req, 0, sizeof(struct hbm_props_request)); | 448 | client_props = &dev->me_clients[i].props; |
505 | 449 | ||
506 | host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | 450 | if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) |
507 | host_cli_req->address = b; | 451 | mei_amthif_host_init(dev); |
508 | 452 | else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) | |
509 | if (mei_write_message(dev, mei_header, | 453 | mei_wd_host_init(dev); |
510 | (unsigned char *)host_cli_req, | 454 | } |
511 | mei_header->length)) { | 455 | |
512 | dev->dev_state = MEI_DEV_RESETING; | 456 | dev->dev_state = MEI_DEV_ENABLED; |
513 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | ||
514 | mei_reset(dev, 1); | ||
515 | return -EIO; | ||
516 | } | ||
517 | 457 | ||
518 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 458 | mutex_unlock(&dev->device_lock); |
519 | dev->me_client_index = b; | 459 | } |
520 | return 1; | 460 | |
461 | int mei_host_client_enumerate(struct mei_device *dev) | ||
462 | { | ||
463 | |||
464 | struct mei_msg_hdr *mei_hdr; | ||
465 | struct hbm_props_request *prop_req; | ||
466 | const size_t len = sizeof(struct hbm_props_request); | ||
467 | unsigned long next_client_index; | ||
468 | u8 client_num; | ||
469 | |||
470 | |||
471 | client_num = dev->me_client_presentation_num; | ||
472 | |||
473 | next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, | ||
474 | dev->me_client_index); | ||
475 | |||
476 | /* We got all client properties */ | ||
477 | if (next_client_index == MEI_CLIENTS_MAX) { | ||
478 | schedule_work(&dev->init_work); | ||
479 | |||
480 | return 0; | ||
521 | } | 481 | } |
522 | 482 | ||
483 | dev->me_clients[client_num].client_id = next_client_index; | ||
484 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; | ||
485 | |||
486 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
487 | prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | ||
488 | |||
489 | memset(prop_req, 0, sizeof(struct hbm_props_request)); | ||
490 | |||
491 | |||
492 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | ||
493 | prop_req->address = next_client_index; | ||
494 | |||
495 | if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req, | ||
496 | mei_hdr->length)) { | ||
497 | dev->dev_state = MEI_DEV_RESETING; | ||
498 | dev_err(&dev->pdev->dev, "Properties request command failed\n"); | ||
499 | mei_reset(dev, 1); | ||
500 | |||
501 | return -EIO; | ||
502 | } | ||
503 | |||
504 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | ||
505 | dev->me_client_index = next_client_index; | ||
506 | |||
523 | return 0; | 507 | return 0; |
524 | } | 508 | } |
525 | 509 | ||
@@ -557,17 +541,20 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) | |||
557 | 541 | ||
558 | 542 | ||
559 | /** | 543 | /** |
560 | * mei_me_cl_update_filext - searches for ME client guid | 544 | * mei_me_cl_link - create link between host and me clinet and add |
561 | * sets client_id in mei_file_private if found | 545 | * me_cl to the list |
546 | * | ||
562 | * @dev: the device structure | 547 | * @dev: the device structure |
563 | * @cl: private file structure to set client_id in | 548 | * @cl: link between me and host client assocated with opened file descriptor |
564 | * @cuuid: searched uuid of ME client | 549 | * @cuuid: uuid of ME client |
565 | * @client_id: id of host client to be set in file private structure | 550 | * @client_id: id of the host client |
566 | * | 551 | * |
567 | * returns ME client index | 552 | * returns ME client index if ME client |
553 | * -EINVAL on incorrect values | ||
554 | * -ENONET if client not found | ||
568 | */ | 555 | */ |
569 | int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | 556 | int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl, |
570 | const uuid_le *cuuid, u8 host_cl_id) | 557 | const uuid_le *cuuid, u8 host_cl_id) |
571 | { | 558 | { |
572 | int i; | 559 | int i; |
573 | 560 | ||
@@ -587,54 +574,22 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | |||
587 | 574 | ||
588 | return -ENOENT; | 575 | return -ENOENT; |
589 | } | 576 | } |
590 | |||
591 | /** | 577 | /** |
592 | * host_init_iamthif - mei initialization iamthif client. | 578 | * mei_me_cl_unlink - remove me_cl from the list |
593 | * | 579 | * |
594 | * @dev: the device structure | 580 | * @dev: the device structure |
595 | * | 581 | * @host_client_id: host client id to be removed |
596 | */ | 582 | */ |
597 | void mei_host_init_iamthif(struct mei_device *dev) | 583 | void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl) |
598 | { | 584 | { |
599 | int i; | 585 | struct mei_cl *pos, *next; |
600 | unsigned char *msg_buf; | 586 | list_for_each_entry_safe(pos, next, &dev->file_list, link) { |
601 | 587 | if (cl->host_client_id == pos->host_client_id) { | |
602 | mei_cl_init(&dev->iamthif_cl, dev); | 588 | dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", |
603 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | 589 | pos->host_client_id, pos->me_client_id); |
604 | 590 | list_del_init(&pos->link); | |
605 | /* find ME amthi client */ | 591 | break; |
606 | i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, | 592 | } |
607 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
608 | if (i < 0) { | ||
609 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | /* Assign iamthif_mtu to the value received from ME */ | ||
614 | |||
615 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | ||
616 | dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", | ||
617 | dev->me_clients[i].props.max_msg_length); | ||
618 | |||
619 | kfree(dev->iamthif_msg_buf); | ||
620 | dev->iamthif_msg_buf = NULL; | ||
621 | |||
622 | /* allocate storage for ME message buffer */ | ||
623 | msg_buf = kcalloc(dev->iamthif_mtu, | ||
624 | sizeof(unsigned char), GFP_KERNEL); | ||
625 | if (!msg_buf) { | ||
626 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | dev->iamthif_msg_buf = msg_buf; | ||
631 | |||
632 | if (mei_connect(dev, &dev->iamthif_cl)) { | ||
633 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | ||
634 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
635 | dev->iamthif_cl.host_client_id = 0; | ||
636 | } else { | ||
637 | dev->iamthif_cl.timer_count = CONNECT_TIMEOUT; | ||
638 | } | 593 | } |
639 | } | 594 | } |
640 | 595 | ||
@@ -671,9 +626,8 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev) | |||
671 | */ | 626 | */ |
672 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | 627 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) |
673 | { | 628 | { |
674 | int rets, err; | ||
675 | long timeout = 15; /* 15 seconds */ | ||
676 | struct mei_cl_cb *cb; | 629 | struct mei_cl_cb *cb; |
630 | int rets, err; | ||
677 | 631 | ||
678 | if (!dev || !cl) | 632 | if (!dev || !cl) |
679 | return -ENODEV; | 633 | return -ENODEV; |
@@ -681,13 +635,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
681 | if (cl->state != MEI_FILE_DISCONNECTING) | 635 | if (cl->state != MEI_FILE_DISCONNECTING) |
682 | return 0; | 636 | return 0; |
683 | 637 | ||
684 | cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | 638 | cb = mei_io_cb_init(cl, NULL); |
685 | if (!cb) | 639 | if (!cb) |
686 | return -ENOMEM; | 640 | return -ENOMEM; |
687 | 641 | ||
688 | INIT_LIST_HEAD(&cb->cb_list); | 642 | cb->fop_type = MEI_FOP_CLOSE; |
689 | cb->file_private = cl; | ||
690 | cb->major_file_operations = MEI_CLOSE; | ||
691 | if (dev->mei_host_buffer_is_empty) { | 643 | if (dev->mei_host_buffer_is_empty) { |
692 | dev->mei_host_buffer_is_empty = false; | 644 | dev->mei_host_buffer_is_empty = false; |
693 | if (mei_disconnect(dev, cl)) { | 645 | if (mei_disconnect(dev, cl)) { |
@@ -696,17 +648,17 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
696 | goto free; | 648 | goto free; |
697 | } | 649 | } |
698 | mdelay(10); /* Wait for hardware disconnection ready */ | 650 | mdelay(10); /* Wait for hardware disconnection ready */ |
699 | list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list); | 651 | list_add_tail(&cb->list, &dev->ctrl_rd_list.list); |
700 | } else { | 652 | } else { |
701 | dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); | 653 | dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); |
702 | list_add_tail(&cb->cb_list, | 654 | list_add_tail(&cb->list, &dev->ctrl_wr_list.list); |
703 | &dev->ctrl_wr_list.mei_cb.cb_list); | 655 | |
704 | } | 656 | } |
705 | mutex_unlock(&dev->device_lock); | 657 | mutex_unlock(&dev->device_lock); |
706 | 658 | ||
707 | err = wait_event_timeout(dev->wait_recvd_msg, | 659 | err = wait_event_timeout(dev->wait_recvd_msg, |
708 | (MEI_FILE_DISCONNECTED == cl->state), | 660 | MEI_FILE_DISCONNECTED == cl->state, |
709 | timeout * HZ); | 661 | mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); |
710 | 662 | ||
711 | mutex_lock(&dev->device_lock); | 663 | mutex_lock(&dev->device_lock); |
712 | if (MEI_FILE_DISCONNECTED == cl->state) { | 664 | if (MEI_FILE_DISCONNECTED == cl->state) { |
@@ -728,29 +680,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
728 | mei_io_list_flush(&dev->ctrl_rd_list, cl); | 680 | mei_io_list_flush(&dev->ctrl_rd_list, cl); |
729 | mei_io_list_flush(&dev->ctrl_wr_list, cl); | 681 | mei_io_list_flush(&dev->ctrl_wr_list, cl); |
730 | free: | 682 | free: |
731 | mei_free_cb_private(cb); | 683 | mei_io_cb_free(cb); |
732 | return rets; | 684 | return rets; |
733 | } | 685 | } |
734 | 686 | ||
735 | /** | ||
736 | * mei_remove_client_from_file_list - | ||
737 | * removes file private data from device file list | ||
738 | * | ||
739 | * @dev: the device structure | ||
740 | * @host_client_id: host client id to be removed | ||
741 | */ | ||
742 | void mei_remove_client_from_file_list(struct mei_device *dev, | ||
743 | u8 host_client_id) | ||
744 | { | ||
745 | struct mei_cl *cl_pos = NULL; | ||
746 | struct mei_cl *cl_next = NULL; | ||
747 | list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { | ||
748 | if (host_client_id == cl_pos->host_client_id) { | ||
749 | dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", | ||
750 | cl_pos->host_client_id, | ||
751 | cl_pos->me_client_id); | ||
752 | list_del_init(&cl_pos->link); | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | } | ||
diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 509c3957ff45..8de854785960 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c | |||
@@ -292,28 +292,23 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl) | |||
292 | int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl) | 292 | int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl) |
293 | { | 293 | { |
294 | struct mei_msg_hdr *mei_hdr; | 294 | struct mei_msg_hdr *mei_hdr; |
295 | struct hbm_flow_control *mei_flow_control; | 295 | struct hbm_flow_control *flow_ctrl; |
296 | 296 | const size_t len = sizeof(struct hbm_flow_control); | |
297 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 297 | |
298 | mei_hdr->host_addr = 0; | 298 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); |
299 | mei_hdr->me_addr = 0; | 299 | |
300 | mei_hdr->length = sizeof(struct hbm_flow_control); | 300 | flow_ctrl = (struct hbm_flow_control *)&dev->wr_msg_buf[1]; |
301 | mei_hdr->msg_complete = 1; | 301 | memset(flow_ctrl, 0, len); |
302 | mei_hdr->reserved = 0; | 302 | flow_ctrl->hbm_cmd = MEI_FLOW_CONTROL_CMD; |
303 | 303 | flow_ctrl->host_addr = cl->host_client_id; | |
304 | mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1]; | 304 | flow_ctrl->me_addr = cl->me_client_id; |
305 | memset(mei_flow_control, 0, sizeof(*mei_flow_control)); | 305 | /* FIXME: reserved !? */ |
306 | mei_flow_control->host_addr = cl->host_client_id; | 306 | memset(flow_ctrl->reserved, 0, sizeof(flow_ctrl->reserved)); |
307 | mei_flow_control->me_addr = cl->me_client_id; | ||
308 | mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD; | ||
309 | memset(mei_flow_control->reserved, 0, | ||
310 | sizeof(mei_flow_control->reserved)); | ||
311 | dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n", | 307 | dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n", |
312 | cl->host_client_id, cl->me_client_id); | 308 | cl->host_client_id, cl->me_client_id); |
313 | 309 | ||
314 | return mei_write_message(dev, mei_hdr, | 310 | return mei_write_message(dev, mei_hdr, |
315 | (unsigned char *) mei_flow_control, | 311 | (unsigned char *) flow_ctrl, len); |
316 | sizeof(struct hbm_flow_control)); | ||
317 | } | 312 | } |
318 | 313 | ||
319 | /** | 314 | /** |
@@ -352,26 +347,19 @@ int mei_other_client_is_connecting(struct mei_device *dev, | |||
352 | int mei_disconnect(struct mei_device *dev, struct mei_cl *cl) | 347 | int mei_disconnect(struct mei_device *dev, struct mei_cl *cl) |
353 | { | 348 | { |
354 | struct mei_msg_hdr *mei_hdr; | 349 | struct mei_msg_hdr *mei_hdr; |
355 | struct hbm_client_disconnect_request *mei_cli_disconnect; | 350 | struct hbm_client_connect_request *req; |
356 | 351 | const size_t len = sizeof(struct hbm_client_connect_request); | |
357 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
358 | mei_hdr->host_addr = 0; | ||
359 | mei_hdr->me_addr = 0; | ||
360 | mei_hdr->length = sizeof(struct hbm_client_disconnect_request); | ||
361 | mei_hdr->msg_complete = 1; | ||
362 | mei_hdr->reserved = 0; | ||
363 | |||
364 | mei_cli_disconnect = | ||
365 | (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1]; | ||
366 | memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect)); | ||
367 | mei_cli_disconnect->host_addr = cl->host_client_id; | ||
368 | mei_cli_disconnect->me_addr = cl->me_client_id; | ||
369 | mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD; | ||
370 | mei_cli_disconnect->reserved[0] = 0; | ||
371 | 352 | ||
372 | return mei_write_message(dev, mei_hdr, | 353 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); |
373 | (unsigned char *) mei_cli_disconnect, | 354 | |
374 | sizeof(struct hbm_client_disconnect_request)); | 355 | req = (struct hbm_client_connect_request *)&dev->wr_msg_buf[1]; |
356 | memset(req, 0, len); | ||
357 | req->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD; | ||
358 | req->host_addr = cl->host_client_id; | ||
359 | req->me_addr = cl->me_client_id; | ||
360 | req->reserved = 0; | ||
361 | |||
362 | return mei_write_message(dev, mei_hdr, (unsigned char *)req, len); | ||
375 | } | 363 | } |
376 | 364 | ||
377 | /** | 365 | /** |
@@ -385,23 +373,16 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl) | |||
385 | int mei_connect(struct mei_device *dev, struct mei_cl *cl) | 373 | int mei_connect(struct mei_device *dev, struct mei_cl *cl) |
386 | { | 374 | { |
387 | struct mei_msg_hdr *mei_hdr; | 375 | struct mei_msg_hdr *mei_hdr; |
388 | struct hbm_client_connect_request *mei_cli_connect; | 376 | struct hbm_client_connect_request *req; |
389 | 377 | const size_t len = sizeof(struct hbm_client_connect_request); | |
390 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
391 | mei_hdr->host_addr = 0; | ||
392 | mei_hdr->me_addr = 0; | ||
393 | mei_hdr->length = sizeof(struct hbm_client_connect_request); | ||
394 | mei_hdr->msg_complete = 1; | ||
395 | mei_hdr->reserved = 0; | ||
396 | |||
397 | mei_cli_connect = | ||
398 | (struct hbm_client_connect_request *) &dev->wr_msg_buf[1]; | ||
399 | mei_cli_connect->host_addr = cl->host_client_id; | ||
400 | mei_cli_connect->me_addr = cl->me_client_id; | ||
401 | mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD; | ||
402 | mei_cli_connect->reserved = 0; | ||
403 | 378 | ||
404 | return mei_write_message(dev, mei_hdr, | 379 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); |
405 | (unsigned char *) mei_cli_connect, | 380 | |
406 | sizeof(struct hbm_client_connect_request)); | 381 | req = (struct hbm_client_connect_request *) &dev->wr_msg_buf[1]; |
382 | req->hbm_cmd = CLIENT_CONNECT_REQ_CMD; | ||
383 | req->host_addr = cl->host_client_id; | ||
384 | req->me_addr = cl->me_client_id; | ||
385 | req->reserved = 0; | ||
386 | |||
387 | return mei_write_message(dev, mei_hdr, (unsigned char *) req, len); | ||
407 | } | 388 | } |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 3533edde04a5..04fa2134615e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -57,14 +57,14 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) | |||
57 | */ | 57 | */ |
58 | static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) | 58 | static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) |
59 | { | 59 | { |
60 | if (cb_pos->major_file_operations == MEI_WRITE) { | 60 | if (cb_pos->fop_type == MEI_FOP_WRITE) { |
61 | mei_free_cb_private(cb_pos); | 61 | mei_io_cb_free(cb_pos); |
62 | cb_pos = NULL; | 62 | cb_pos = NULL; |
63 | cl->writing_state = MEI_WRITE_COMPLETE; | 63 | cl->writing_state = MEI_WRITE_COMPLETE; |
64 | if (waitqueue_active(&cl->tx_wait)) | 64 | if (waitqueue_active(&cl->tx_wait)) |
65 | wake_up_interruptible(&cl->tx_wait); | 65 | wake_up_interruptible(&cl->tx_wait); |
66 | 66 | ||
67 | } else if (cb_pos->major_file_operations == MEI_READ && | 67 | } else if (cb_pos->fop_type == MEI_FOP_READ && |
68 | MEI_READING == cl->reading_state) { | 68 | MEI_READING == cl->reading_state) { |
69 | cl->reading_state = MEI_READ_COMPLETE; | 69 | cl->reading_state = MEI_READ_COMPLETE; |
70 | if (waitqueue_active(&cl->rx_wait)) | 70 | if (waitqueue_active(&cl->rx_wait)) |
@@ -74,94 +74,6 @@ static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * _mei_cmpl_iamthif - processes completed iamthif operation. | ||
78 | * | ||
79 | * @dev: the device structure. | ||
80 | * @cb_pos: callback block. | ||
81 | */ | ||
82 | static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos) | ||
83 | { | ||
84 | if (dev->iamthif_canceled != 1) { | ||
85 | dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; | ||
86 | dev->iamthif_stall_timer = 0; | ||
87 | memcpy(cb_pos->response_buffer.data, | ||
88 | dev->iamthif_msg_buf, | ||
89 | dev->iamthif_msg_buf_index); | ||
90 | list_add_tail(&cb_pos->cb_list, | ||
91 | &dev->amthi_read_complete_list.mei_cb.cb_list); | ||
92 | dev_dbg(&dev->pdev->dev, "amthi read completed.\n"); | ||
93 | dev->iamthif_timer = jiffies; | ||
94 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", | ||
95 | dev->iamthif_timer); | ||
96 | } else { | ||
97 | mei_run_next_iamthif_cmd(dev); | ||
98 | } | ||
99 | |||
100 | dev_dbg(&dev->pdev->dev, "completing amthi call back.\n"); | ||
101 | wake_up_interruptible(&dev->iamthif_cl.wait); | ||
102 | } | ||
103 | |||
104 | |||
105 | /** | ||
106 | * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to | ||
107 | * handle the read amthi message data processing. | ||
108 | * | ||
109 | * @complete_list: An instance of our list structure | ||
110 | * @dev: the device structure | ||
111 | * @mei_hdr: header of amthi message | ||
112 | * | ||
113 | * returns 0 on success, <0 on failure. | ||
114 | */ | ||
115 | static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list, | ||
116 | struct mei_device *dev, | ||
117 | struct mei_msg_hdr *mei_hdr) | ||
118 | { | ||
119 | struct mei_cl *cl; | ||
120 | struct mei_cl_cb *cb; | ||
121 | unsigned char *buffer; | ||
122 | |||
123 | BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); | ||
124 | BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); | ||
125 | |||
126 | buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; | ||
127 | BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); | ||
128 | |||
129 | mei_read_slots(dev, buffer, mei_hdr->length); | ||
130 | |||
131 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
132 | |||
133 | if (!mei_hdr->msg_complete) | ||
134 | return 0; | ||
135 | |||
136 | dev_dbg(&dev->pdev->dev, | ||
137 | "amthi_message_buffer_index =%d\n", | ||
138 | mei_hdr->length); | ||
139 | |||
140 | dev_dbg(&dev->pdev->dev, "completed amthi read.\n "); | ||
141 | if (!dev->iamthif_current_cb) | ||
142 | return -ENODEV; | ||
143 | |||
144 | cb = dev->iamthif_current_cb; | ||
145 | dev->iamthif_current_cb = NULL; | ||
146 | |||
147 | cl = (struct mei_cl *)cb->file_private; | ||
148 | if (!cl) | ||
149 | return -ENODEV; | ||
150 | |||
151 | dev->iamthif_stall_timer = 0; | ||
152 | cb->information = dev->iamthif_msg_buf_index; | ||
153 | cb->read_time = jiffies; | ||
154 | if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) { | ||
155 | /* found the iamthif cb */ | ||
156 | dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n "); | ||
157 | dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n "); | ||
158 | list_add_tail(&cb->cb_list, | ||
159 | &complete_list->mei_cb.cb_list); | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * _mei_irq_thread_state_ok - checks if mei header matches file private data | 77 | * _mei_irq_thread_state_ok - checks if mei header matches file private data |
166 | * | 78 | * |
167 | * @cl: private data of the file object | 79 | * @cl: private data of the file object |
@@ -188,7 +100,7 @@ static int _mei_irq_thread_state_ok(struct mei_cl *cl, | |||
188 | * | 100 | * |
189 | * returns 0 on success, <0 on failure. | 101 | * returns 0 on success, <0 on failure. |
190 | */ | 102 | */ |
191 | static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, | 103 | static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list, |
192 | struct mei_device *dev, | 104 | struct mei_device *dev, |
193 | struct mei_msg_hdr *mei_hdr) | 105 | struct mei_msg_hdr *mei_hdr) |
194 | { | 106 | { |
@@ -197,36 +109,36 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, | |||
197 | unsigned char *buffer = NULL; | 109 | unsigned char *buffer = NULL; |
198 | 110 | ||
199 | dev_dbg(&dev->pdev->dev, "start client msg\n"); | 111 | dev_dbg(&dev->pdev->dev, "start client msg\n"); |
200 | if (list_empty(&dev->read_list.mei_cb.cb_list)) | 112 | if (list_empty(&dev->read_list.list)) |
201 | goto quit; | 113 | goto quit; |
202 | 114 | ||
203 | list_for_each_entry_safe(cb_pos, cb_next, | 115 | list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) { |
204 | &dev->read_list.mei_cb.cb_list, cb_list) { | 116 | cl = cb_pos->cl; |
205 | cl = (struct mei_cl *)cb_pos->file_private; | ||
206 | if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) { | 117 | if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) { |
207 | cl->reading_state = MEI_READING; | 118 | cl->reading_state = MEI_READING; |
208 | buffer = cb_pos->response_buffer.data + cb_pos->information; | 119 | buffer = cb_pos->response_buffer.data + cb_pos->buf_idx; |
209 | 120 | ||
210 | if (cb_pos->response_buffer.size < | 121 | if (cb_pos->response_buffer.size < |
211 | mei_hdr->length + cb_pos->information) { | 122 | mei_hdr->length + cb_pos->buf_idx) { |
212 | dev_dbg(&dev->pdev->dev, "message overflow.\n"); | 123 | dev_dbg(&dev->pdev->dev, "message overflow.\n"); |
213 | list_del(&cb_pos->cb_list); | 124 | list_del(&cb_pos->list); |
214 | return -ENOMEM; | 125 | return -ENOMEM; |
215 | } | 126 | } |
216 | if (buffer) | 127 | if (buffer) |
217 | mei_read_slots(dev, buffer, mei_hdr->length); | 128 | mei_read_slots(dev, buffer, mei_hdr->length); |
218 | 129 | ||
219 | cb_pos->information += mei_hdr->length; | 130 | cb_pos->buf_idx += mei_hdr->length; |
220 | if (mei_hdr->msg_complete) { | 131 | if (mei_hdr->msg_complete) { |
221 | cl->status = 0; | 132 | cl->status = 0; |
222 | list_del(&cb_pos->cb_list); | 133 | list_del(&cb_pos->list); |
223 | dev_dbg(&dev->pdev->dev, | 134 | dev_dbg(&dev->pdev->dev, |
224 | "completed read H cl = %d, ME cl = %d, length = %lu\n", | 135 | "completed read H cl = %d, ME cl = %d, length = %lu\n", |
225 | cl->host_client_id, | 136 | cl->host_client_id, |
226 | cl->me_client_id, | 137 | cl->me_client_id, |
227 | cb_pos->information); | 138 | cb_pos->buf_idx); |
228 | list_add_tail(&cb_pos->cb_list, | 139 | |
229 | &complete_list->mei_cb.cb_list); | 140 | list_add_tail(&cb_pos->list, |
141 | &complete_list->list); | ||
230 | } | 142 | } |
231 | 143 | ||
232 | break; | 144 | break; |
@@ -246,37 +158,6 @@ quit: | |||
246 | } | 158 | } |
247 | 159 | ||
248 | /** | 160 | /** |
249 | * _mei_irq_thread_iamthif_read - prepares to read iamthif data. | ||
250 | * | ||
251 | * @dev: the device structure. | ||
252 | * @slots: free slots. | ||
253 | * | ||
254 | * returns 0, OK; otherwise, error. | ||
255 | */ | ||
256 | static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) | ||
257 | { | ||
258 | |||
259 | if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr) | ||
260 | + sizeof(struct hbm_flow_control))) { | ||
261 | return -EMSGSIZE; | ||
262 | } | ||
263 | *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); | ||
264 | if (mei_send_flow_control(dev, &dev->iamthif_cl)) { | ||
265 | dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); | ||
266 | return -EIO; | ||
267 | } | ||
268 | |||
269 | dev_dbg(&dev->pdev->dev, "iamthif flow control success\n"); | ||
270 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
271 | dev->iamthif_flow_control_pending = false; | ||
272 | dev->iamthif_msg_buf_index = 0; | ||
273 | dev->iamthif_msg_buf_size = 0; | ||
274 | dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER; | ||
275 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * _mei_irq_thread_close - processes close related operation. | 161 | * _mei_irq_thread_close - processes close related operation. |
281 | * | 162 | * |
282 | * @dev: the device structure. | 163 | * @dev: the device structure. |
@@ -290,26 +171,24 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) | |||
290 | static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, | 171 | static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, |
291 | struct mei_cl_cb *cb_pos, | 172 | struct mei_cl_cb *cb_pos, |
292 | struct mei_cl *cl, | 173 | struct mei_cl *cl, |
293 | struct mei_io_list *cmpl_list) | 174 | struct mei_cl_cb *cmpl_list) |
294 | { | 175 | { |
295 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + | 176 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + |
296 | sizeof(struct hbm_client_disconnect_request))) | 177 | sizeof(struct hbm_client_connect_request))) |
297 | return -EBADMSG; | 178 | return -EBADMSG; |
298 | 179 | ||
299 | *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request)); | 180 | *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); |
300 | 181 | ||
301 | if (mei_disconnect(dev, cl)) { | 182 | if (mei_disconnect(dev, cl)) { |
302 | cl->status = 0; | 183 | cl->status = 0; |
303 | cb_pos->information = 0; | 184 | cb_pos->buf_idx = 0; |
304 | list_move_tail(&cb_pos->cb_list, | 185 | list_move_tail(&cb_pos->list, &cmpl_list->list); |
305 | &cmpl_list->mei_cb.cb_list); | ||
306 | return -EMSGSIZE; | 186 | return -EMSGSIZE; |
307 | } else { | 187 | } else { |
308 | cl->state = MEI_FILE_DISCONNECTING; | 188 | cl->state = MEI_FILE_DISCONNECTING; |
309 | cl->status = 0; | 189 | cl->status = 0; |
310 | cb_pos->information = 0; | 190 | cb_pos->buf_idx = 0; |
311 | list_move_tail(&cb_pos->cb_list, | 191 | list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); |
312 | &dev->ctrl_rd_list.mei_cb.cb_list); | ||
313 | cl->timer_count = MEI_CONNECT_TIMEOUT; | 192 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
314 | } | 193 | } |
315 | 194 | ||
@@ -356,7 +235,7 @@ static void mei_client_connect_response(struct mei_device *dev, | |||
356 | { | 235 | { |
357 | 236 | ||
358 | struct mei_cl *cl; | 237 | struct mei_cl *cl; |
359 | struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; | 238 | struct mei_cl_cb *pos = NULL, *next = NULL; |
360 | 239 | ||
361 | dev_dbg(&dev->pdev->dev, | 240 | dev_dbg(&dev->pdev->dev, |
362 | "connect_response:\n" | 241 | "connect_response:\n" |
@@ -373,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev, | |||
373 | dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); | 252 | dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); |
374 | mei_watchdog_register(dev); | 253 | mei_watchdog_register(dev); |
375 | 254 | ||
376 | /* next step in the state maching */ | ||
377 | mei_host_init_iamthif(dev); | ||
378 | return; | 255 | return; |
379 | } | 256 | } |
380 | 257 | ||
@@ -382,17 +259,16 @@ static void mei_client_connect_response(struct mei_device *dev, | |||
382 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | 259 | dev->iamthif_state = MEI_IAMTHIF_IDLE; |
383 | return; | 260 | return; |
384 | } | 261 | } |
385 | list_for_each_entry_safe(cb_pos, cb_next, | 262 | list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { |
386 | &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { | ||
387 | 263 | ||
388 | cl = (struct mei_cl *)cb_pos->file_private; | 264 | cl = pos->cl; |
389 | if (!cl) { | 265 | if (!cl) { |
390 | list_del(&cb_pos->cb_list); | 266 | list_del(&pos->list); |
391 | return; | 267 | return; |
392 | } | 268 | } |
393 | if (MEI_IOCTL == cb_pos->major_file_operations) { | 269 | if (pos->fop_type == MEI_FOP_IOCTL) { |
394 | if (is_treat_specially_client(cl, rs)) { | 270 | if (is_treat_specially_client(cl, rs)) { |
395 | list_del(&cb_pos->cb_list); | 271 | list_del(&pos->list); |
396 | cl->status = 0; | 272 | cl->status = 0; |
397 | cl->timer_count = 0; | 273 | cl->timer_count = 0; |
398 | break; | 274 | break; |
@@ -411,7 +287,7 @@ static void mei_client_disconnect_response(struct mei_device *dev, | |||
411 | struct hbm_client_connect_response *rs) | 287 | struct hbm_client_connect_response *rs) |
412 | { | 288 | { |
413 | struct mei_cl *cl; | 289 | struct mei_cl *cl; |
414 | struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; | 290 | struct mei_cl_cb *pos = NULL, *next = NULL; |
415 | 291 | ||
416 | dev_dbg(&dev->pdev->dev, | 292 | dev_dbg(&dev->pdev->dev, |
417 | "disconnect_response:\n" | 293 | "disconnect_response:\n" |
@@ -422,12 +298,11 @@ static void mei_client_disconnect_response(struct mei_device *dev, | |||
422 | rs->host_addr, | 298 | rs->host_addr, |
423 | rs->status); | 299 | rs->status); |
424 | 300 | ||
425 | list_for_each_entry_safe(cb_pos, cb_next, | 301 | list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { |
426 | &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { | 302 | cl = pos->cl; |
427 | cl = (struct mei_cl *)cb_pos->file_private; | ||
428 | 303 | ||
429 | if (!cl) { | 304 | if (!cl) { |
430 | list_del(&cb_pos->cb_list); | 305 | list_del(&pos->list); |
431 | return; | 306 | return; |
432 | } | 307 | } |
433 | 308 | ||
@@ -435,7 +310,7 @@ static void mei_client_disconnect_response(struct mei_device *dev, | |||
435 | if (cl->host_client_id == rs->host_addr && | 310 | if (cl->host_client_id == rs->host_addr && |
436 | cl->me_client_id == rs->me_addr) { | 311 | cl->me_client_id == rs->me_addr) { |
437 | 312 | ||
438 | list_del(&cb_pos->cb_list); | 313 | list_del(&pos->list); |
439 | if (!rs->status) | 314 | if (!rs->status) |
440 | cl->state = MEI_FILE_DISCONNECTED; | 315 | cl->state = MEI_FILE_DISCONNECTED; |
441 | 316 | ||
@@ -537,10 +412,10 @@ static void mei_client_flow_control_response(struct mei_device *dev, | |||
537 | * returns !=0, same; 0,not. | 412 | * returns !=0, same; 0,not. |
538 | */ | 413 | */ |
539 | static int same_disconn_addr(struct mei_cl *cl, | 414 | static int same_disconn_addr(struct mei_cl *cl, |
540 | struct hbm_client_disconnect_request *disconn) | 415 | struct hbm_client_connect_request *req) |
541 | { | 416 | { |
542 | return (cl->host_client_id == disconn->host_addr && | 417 | return (cl->host_client_id == req->host_addr && |
543 | cl->me_client_id == disconn->me_addr); | 418 | cl->me_client_id == req->me_addr); |
544 | } | 419 | } |
545 | 420 | ||
546 | /** | 421 | /** |
@@ -550,49 +425,38 @@ static int same_disconn_addr(struct mei_cl *cl, | |||
550 | * @disconnect_req: disconnect request bus message. | 425 | * @disconnect_req: disconnect request bus message. |
551 | */ | 426 | */ |
552 | static void mei_client_disconnect_request(struct mei_device *dev, | 427 | static void mei_client_disconnect_request(struct mei_device *dev, |
553 | struct hbm_client_disconnect_request *disconnect_req) | 428 | struct hbm_client_connect_request *disconnect_req) |
554 | { | 429 | { |
555 | struct mei_msg_hdr *mei_hdr; | ||
556 | struct hbm_client_connect_response *disconnect_res; | 430 | struct hbm_client_connect_response *disconnect_res; |
557 | struct mei_cl *cl_pos = NULL; | 431 | struct mei_cl *pos, *next; |
558 | struct mei_cl *cl_next = NULL; | 432 | const size_t len = sizeof(struct hbm_client_connect_response); |
559 | 433 | ||
560 | list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { | 434 | list_for_each_entry_safe(pos, next, &dev->file_list, link) { |
561 | if (same_disconn_addr(cl_pos, disconnect_req)) { | 435 | if (same_disconn_addr(pos, disconnect_req)) { |
562 | dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n", | 436 | dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n", |
563 | disconnect_req->host_addr, | 437 | disconnect_req->host_addr, |
564 | disconnect_req->me_addr); | 438 | disconnect_req->me_addr); |
565 | cl_pos->state = MEI_FILE_DISCONNECTED; | 439 | pos->state = MEI_FILE_DISCONNECTED; |
566 | cl_pos->timer_count = 0; | 440 | pos->timer_count = 0; |
567 | if (cl_pos == &dev->wd_cl) | 441 | if (pos == &dev->wd_cl) |
568 | dev->wd_pending = false; | 442 | dev->wd_pending = false; |
569 | else if (cl_pos == &dev->iamthif_cl) | 443 | else if (pos == &dev->iamthif_cl) |
570 | dev->iamthif_timer = 0; | 444 | dev->iamthif_timer = 0; |
571 | 445 | ||
572 | /* prepare disconnect response */ | 446 | /* prepare disconnect response */ |
573 | mei_hdr = | 447 | (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len); |
574 | (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; | ||
575 | mei_hdr->host_addr = 0; | ||
576 | mei_hdr->me_addr = 0; | ||
577 | mei_hdr->length = | ||
578 | sizeof(struct hbm_client_connect_response); | ||
579 | mei_hdr->msg_complete = 1; | ||
580 | mei_hdr->reserved = 0; | ||
581 | |||
582 | disconnect_res = | 448 | disconnect_res = |
583 | (struct hbm_client_connect_response *) | 449 | (struct hbm_client_connect_response *) |
584 | &dev->ext_msg_buf[1]; | 450 | &dev->wr_ext_msg.data; |
585 | disconnect_res->host_addr = cl_pos->host_client_id; | ||
586 | disconnect_res->me_addr = cl_pos->me_client_id; | ||
587 | disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD; | 451 | disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD; |
452 | disconnect_res->host_addr = pos->host_client_id; | ||
453 | disconnect_res->me_addr = pos->me_client_id; | ||
588 | disconnect_res->status = 0; | 454 | disconnect_res->status = 0; |
589 | dev->extra_write_index = 2; | ||
590 | break; | 455 | break; |
591 | } | 456 | } |
592 | } | 457 | } |
593 | } | 458 | } |
594 | 459 | ||
595 | |||
596 | /** | 460 | /** |
597 | * mei_irq_thread_read_bus_message - bottom half read routine after ISR to | 461 | * mei_irq_thread_read_bus_message - bottom half read routine after ISR to |
598 | * handle the read bus message cmd processing. | 462 | * handle the read bus message cmd processing. |
@@ -604,16 +468,15 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
604 | struct mei_msg_hdr *mei_hdr) | 468 | struct mei_msg_hdr *mei_hdr) |
605 | { | 469 | { |
606 | struct mei_bus_message *mei_msg; | 470 | struct mei_bus_message *mei_msg; |
471 | struct mei_me_client *me_client; | ||
607 | struct hbm_host_version_response *version_res; | 472 | struct hbm_host_version_response *version_res; |
608 | struct hbm_client_connect_response *connect_res; | 473 | struct hbm_client_connect_response *connect_res; |
609 | struct hbm_client_connect_response *disconnect_res; | 474 | struct hbm_client_connect_response *disconnect_res; |
475 | struct hbm_client_connect_request *disconnect_req; | ||
610 | struct hbm_flow_control *flow_control; | 476 | struct hbm_flow_control *flow_control; |
611 | struct hbm_props_response *props_res; | 477 | struct hbm_props_response *props_res; |
612 | struct hbm_host_enum_response *enum_res; | 478 | struct hbm_host_enum_response *enum_res; |
613 | struct hbm_client_disconnect_request *disconnect_req; | 479 | struct hbm_host_stop_request *stop_req; |
614 | struct hbm_host_stop_request *host_stop_req; | ||
615 | int res; | ||
616 | |||
617 | 480 | ||
618 | /* read the message to our buffer */ | 481 | /* read the message to our buffer */ |
619 | BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); | 482 | BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); |
@@ -637,26 +500,20 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
637 | return; | 500 | return; |
638 | } | 501 | } |
639 | } else { | 502 | } else { |
503 | u32 *buf = dev->wr_msg_buf; | ||
504 | const size_t len = sizeof(struct hbm_host_stop_request); | ||
505 | |||
640 | dev->version = version_res->me_max_version; | 506 | dev->version = version_res->me_max_version; |
507 | |||
641 | /* send stop message */ | 508 | /* send stop message */ |
642 | mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; | 509 | mei_hdr = mei_hbm_hdr(&buf[0], len); |
643 | mei_hdr->host_addr = 0; | 510 | stop_req = (struct hbm_host_stop_request *)&buf[1]; |
644 | mei_hdr->me_addr = 0; | 511 | memset(stop_req, 0, len); |
645 | mei_hdr->length = sizeof(struct hbm_host_stop_request); | 512 | stop_req->hbm_cmd = HOST_STOP_REQ_CMD; |
646 | mei_hdr->msg_complete = 1; | 513 | stop_req->reason = DRIVER_STOP_REQUEST; |
647 | mei_hdr->reserved = 0; | 514 | |
648 | |||
649 | host_stop_req = (struct hbm_host_stop_request *) | ||
650 | &dev->wr_msg_buf[1]; | ||
651 | |||
652 | memset(host_stop_req, | ||
653 | 0, | ||
654 | sizeof(struct hbm_host_stop_request)); | ||
655 | host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD; | ||
656 | host_stop_req->reason = DRIVER_STOP_REQUEST; | ||
657 | mei_write_message(dev, mei_hdr, | 515 | mei_write_message(dev, mei_hdr, |
658 | (unsigned char *) (host_stop_req), | 516 | (unsigned char *)stop_req, len); |
659 | mei_hdr->length); | ||
660 | dev_dbg(&dev->pdev->dev, "version mismatch.\n"); | 517 | dev_dbg(&dev->pdev->dev, "version mismatch.\n"); |
661 | return; | 518 | return; |
662 | } | 519 | } |
@@ -666,16 +523,14 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
666 | break; | 523 | break; |
667 | 524 | ||
668 | case CLIENT_CONNECT_RES_CMD: | 525 | case CLIENT_CONNECT_RES_CMD: |
669 | connect_res = | 526 | connect_res = (struct hbm_client_connect_response *) mei_msg; |
670 | (struct hbm_client_connect_response *) mei_msg; | ||
671 | mei_client_connect_response(dev, connect_res); | 527 | mei_client_connect_response(dev, connect_res); |
672 | dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); | 528 | dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); |
673 | wake_up(&dev->wait_recvd_msg); | 529 | wake_up(&dev->wait_recvd_msg); |
674 | break; | 530 | break; |
675 | 531 | ||
676 | case CLIENT_DISCONNECT_RES_CMD: | 532 | case CLIENT_DISCONNECT_RES_CMD: |
677 | disconnect_res = | 533 | disconnect_res = (struct hbm_client_connect_response *) mei_msg; |
678 | (struct hbm_client_connect_response *) mei_msg; | ||
679 | mei_client_disconnect_response(dev, disconnect_res); | 534 | mei_client_disconnect_response(dev, disconnect_res); |
680 | dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); | 535 | dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); |
681 | wake_up(&dev->wait_recvd_msg); | 536 | wake_up(&dev->wait_recvd_msg); |
@@ -689,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
689 | 544 | ||
690 | case HOST_CLIENT_PROPERTIES_RES_CMD: | 545 | case HOST_CLIENT_PROPERTIES_RES_CMD: |
691 | props_res = (struct hbm_props_response *)mei_msg; | 546 | props_res = (struct hbm_props_response *)mei_msg; |
547 | me_client = &dev->me_clients[dev->me_client_presentation_num]; | ||
548 | |||
692 | if (props_res->status || !dev->me_clients) { | 549 | if (props_res->status || !dev->me_clients) { |
693 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); | 550 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); |
694 | mei_reset(dev, 1); | 551 | mei_reset(dev, 1); |
695 | return; | 552 | return; |
696 | } | 553 | } |
697 | if (dev->me_clients[dev->me_client_presentation_num] | ||
698 | .client_id == props_res->address) { | ||
699 | 554 | ||
700 | dev->me_clients[dev->me_client_presentation_num].props | 555 | if (me_client->client_id != props_res->address) { |
701 | = props_res->client_properties; | 556 | dev_err(&dev->pdev->dev, |
557 | "Host client properties reply mismatch\n"); | ||
558 | mei_reset(dev, 1); | ||
702 | 559 | ||
703 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && | 560 | return; |
704 | dev->init_clients_state == | 561 | } |
705 | MEI_CLIENT_PROPERTIES_MESSAGE) { | ||
706 | dev->me_client_index++; | ||
707 | dev->me_client_presentation_num++; | ||
708 | |||
709 | /** Send Client Properties request **/ | ||
710 | res = mei_host_client_properties(dev); | ||
711 | if (res < 0) { | ||
712 | dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed"); | ||
713 | return; | ||
714 | } else if (!res) { | ||
715 | /* | ||
716 | * No more clients to send to. | ||
717 | * Clear Map for indicating now ME clients | ||
718 | * with associated host client | ||
719 | */ | ||
720 | bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); | ||
721 | dev->open_handle_count = 0; | ||
722 | |||
723 | /* | ||
724 | * Reserving the first three client IDs | ||
725 | * Client Id 0 - Reserved for MEI Bus Message communications | ||
726 | * Client Id 1 - Reserved for Watchdog | ||
727 | * Client ID 2 - Reserved for AMTHI | ||
728 | */ | ||
729 | bitmap_set(dev->host_clients_map, 0, 3); | ||
730 | dev->dev_state = MEI_DEV_ENABLED; | ||
731 | |||
732 | /* if wd initialization fails, initialization the AMTHI client, | ||
733 | * otherwise the AMTHI client will be initialized after the WD client connect response | ||
734 | * will be received | ||
735 | */ | ||
736 | if (mei_wd_host_init(dev)) | ||
737 | mei_host_init_iamthif(dev); | ||
738 | } | ||
739 | 562 | ||
740 | } else { | 563 | if (dev->dev_state != MEI_DEV_INIT_CLIENTS || |
741 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message"); | 564 | dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { |
742 | mei_reset(dev, 1); | 565 | dev_err(&dev->pdev->dev, |
743 | return; | 566 | "Unexpected client properties reply\n"); |
744 | } | ||
745 | } else { | ||
746 | dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n"); | ||
747 | mei_reset(dev, 1); | 567 | mei_reset(dev, 1); |
568 | |||
748 | return; | 569 | return; |
749 | } | 570 | } |
571 | |||
572 | me_client->props = props_res->client_properties; | ||
573 | dev->me_client_index++; | ||
574 | dev->me_client_presentation_num++; | ||
575 | |||
576 | mei_host_client_enumerate(dev); | ||
577 | |||
750 | break; | 578 | break; |
751 | 579 | ||
752 | case HOST_ENUM_RES_CMD: | 580 | case HOST_ENUM_RES_CMD: |
@@ -760,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
760 | mei_allocate_me_clients_storage(dev); | 588 | mei_allocate_me_clients_storage(dev); |
761 | dev->init_clients_state = | 589 | dev->init_clients_state = |
762 | MEI_CLIENT_PROPERTIES_MESSAGE; | 590 | MEI_CLIENT_PROPERTIES_MESSAGE; |
763 | mei_host_client_properties(dev); | 591 | |
592 | mei_host_client_enumerate(dev); | ||
764 | } else { | 593 | } else { |
765 | dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); | 594 | dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); |
766 | mei_reset(dev, 1); | 595 | mei_reset(dev, 1); |
@@ -776,29 +605,23 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
776 | 605 | ||
777 | case CLIENT_DISCONNECT_REQ_CMD: | 606 | case CLIENT_DISCONNECT_REQ_CMD: |
778 | /* search for client */ | 607 | /* search for client */ |
779 | disconnect_req = | 608 | disconnect_req = (struct hbm_client_connect_request *)mei_msg; |
780 | (struct hbm_client_disconnect_request *) mei_msg; | ||
781 | mei_client_disconnect_request(dev, disconnect_req); | 609 | mei_client_disconnect_request(dev, disconnect_req); |
782 | break; | 610 | break; |
783 | 611 | ||
784 | case ME_STOP_REQ_CMD: | 612 | case ME_STOP_REQ_CMD: |
785 | /* prepare stop request */ | 613 | { |
786 | mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; | 614 | /* prepare stop request: sent in next interrupt event */ |
787 | mei_hdr->host_addr = 0; | 615 | |
788 | mei_hdr->me_addr = 0; | 616 | const size_t len = sizeof(struct hbm_host_stop_request); |
789 | mei_hdr->length = sizeof(struct hbm_host_stop_request); | ||
790 | mei_hdr->msg_complete = 1; | ||
791 | mei_hdr->reserved = 0; | ||
792 | host_stop_req = | ||
793 | (struct hbm_host_stop_request *) &dev->ext_msg_buf[1]; | ||
794 | memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request)); | ||
795 | host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD; | ||
796 | host_stop_req->reason = DRIVER_STOP_REQUEST; | ||
797 | host_stop_req->reserved[0] = 0; | ||
798 | host_stop_req->reserved[1] = 0; | ||
799 | dev->extra_write_index = 2; | ||
800 | break; | ||
801 | 617 | ||
618 | mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len); | ||
619 | stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data; | ||
620 | memset(stop_req, 0, len); | ||
621 | stop_req->hbm_cmd = HOST_STOP_REQ_CMD; | ||
622 | stop_req->reason = DRIVER_STOP_REQUEST; | ||
623 | break; | ||
624 | } | ||
802 | default: | 625 | default: |
803 | BUG(); | 626 | BUG(); |
804 | break; | 627 | break; |
@@ -821,12 +644,12 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
821 | static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, | 644 | static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, |
822 | struct mei_cl_cb *cb_pos, | 645 | struct mei_cl_cb *cb_pos, |
823 | struct mei_cl *cl, | 646 | struct mei_cl *cl, |
824 | struct mei_io_list *cmpl_list) | 647 | struct mei_cl_cb *cmpl_list) |
825 | { | 648 | { |
826 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + | 649 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + |
827 | sizeof(struct hbm_flow_control))) { | 650 | sizeof(struct hbm_flow_control))) { |
828 | /* return the cancel routine */ | 651 | /* return the cancel routine */ |
829 | list_del(&cb_pos->cb_list); | 652 | list_del(&cb_pos->list); |
830 | return -EBADMSG; | 653 | return -EBADMSG; |
831 | } | 654 | } |
832 | 655 | ||
@@ -834,11 +657,11 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, | |||
834 | 657 | ||
835 | if (mei_send_flow_control(dev, cl)) { | 658 | if (mei_send_flow_control(dev, cl)) { |
836 | cl->status = -ENODEV; | 659 | cl->status = -ENODEV; |
837 | cb_pos->information = 0; | 660 | cb_pos->buf_idx = 0; |
838 | list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list); | 661 | list_move_tail(&cb_pos->list, &cmpl_list->list); |
839 | return -ENODEV; | 662 | return -ENODEV; |
840 | } | 663 | } |
841 | list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list); | 664 | list_move_tail(&cb_pos->list, &dev->read_list.list); |
842 | 665 | ||
843 | return 0; | 666 | return 0; |
844 | } | 667 | } |
@@ -858,12 +681,12 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, | |||
858 | static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, | 681 | static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, |
859 | struct mei_cl_cb *cb_pos, | 682 | struct mei_cl_cb *cb_pos, |
860 | struct mei_cl *cl, | 683 | struct mei_cl *cl, |
861 | struct mei_io_list *cmpl_list) | 684 | struct mei_cl_cb *cmpl_list) |
862 | { | 685 | { |
863 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + | 686 | if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + |
864 | sizeof(struct hbm_client_connect_request))) { | 687 | sizeof(struct hbm_client_connect_request))) { |
865 | /* return the cancel routine */ | 688 | /* return the cancel routine */ |
866 | list_del(&cb_pos->cb_list); | 689 | list_del(&cb_pos->list); |
867 | return -EBADMSG; | 690 | return -EBADMSG; |
868 | } | 691 | } |
869 | 692 | ||
@@ -871,188 +694,73 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, | |||
871 | *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); | 694 | *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); |
872 | if (mei_connect(dev, cl)) { | 695 | if (mei_connect(dev, cl)) { |
873 | cl->status = -ENODEV; | 696 | cl->status = -ENODEV; |
874 | cb_pos->information = 0; | 697 | cb_pos->buf_idx = 0; |
875 | list_del(&cb_pos->cb_list); | 698 | list_del(&cb_pos->list); |
876 | return -ENODEV; | 699 | return -ENODEV; |
877 | } else { | 700 | } else { |
878 | list_move_tail(&cb_pos->cb_list, | 701 | list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); |
879 | &dev->ctrl_rd_list.mei_cb.cb_list); | ||
880 | cl->timer_count = MEI_CONNECT_TIMEOUT; | 702 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
881 | } | 703 | } |
882 | return 0; | 704 | return 0; |
883 | } | 705 | } |
884 | 706 | ||
885 | /** | 707 | /** |
886 | * _mei_irq_thread_cmpl - processes completed and no-iamthif operation. | 708 | * mei_irq_thread_write_complete - write messages to device. |
887 | * | 709 | * |
888 | * @dev: the device structure. | 710 | * @dev: the device structure. |
889 | * @slots: free slots. | 711 | * @slots: free slots. |
890 | * @cb_pos: callback block. | 712 | * @cb: callback block. |
891 | * @cl: private data of the file object. | ||
892 | * @cmpl_list: complete list. | 713 | * @cmpl_list: complete list. |
893 | * | 714 | * |
894 | * returns 0, OK; otherwise, error. | 715 | * returns 0, OK; otherwise, error. |
895 | */ | 716 | */ |
896 | static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, | 717 | static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, |
897 | struct mei_cl_cb *cb_pos, | 718 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) |
898 | struct mei_cl *cl, | ||
899 | struct mei_io_list *cmpl_list) | ||
900 | { | 719 | { |
901 | struct mei_msg_hdr *mei_hdr; | 720 | struct mei_msg_hdr *mei_hdr; |
721 | struct mei_cl *cl = cb->cl; | ||
722 | size_t len = cb->request_buffer.size - cb->buf_idx; | ||
723 | size_t msg_slots = mei_data2slots(len); | ||
724 | |||
725 | mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; | ||
726 | mei_hdr->host_addr = cl->host_client_id; | ||
727 | mei_hdr->me_addr = cl->me_client_id; | ||
728 | mei_hdr->reserved = 0; | ||
902 | 729 | ||
903 | if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + | 730 | if (*slots >= msg_slots) { |
904 | (cb_pos->request_buffer.size - | 731 | mei_hdr->length = len; |
905 | cb_pos->information))) { | ||
906 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
907 | mei_hdr->host_addr = cl->host_client_id; | ||
908 | mei_hdr->me_addr = cl->me_client_id; | ||
909 | mei_hdr->length = cb_pos->request_buffer.size - | ||
910 | cb_pos->information; | ||
911 | mei_hdr->msg_complete = 1; | 732 | mei_hdr->msg_complete = 1; |
912 | mei_hdr->reserved = 0; | 733 | /* Split the message only if we can write the whole host buffer */ |
913 | dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d" | ||
914 | "mei_hdr->msg_complete = %d\n", | ||
915 | cb_pos->request_buffer.size, | ||
916 | mei_hdr->msg_complete); | ||
917 | dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", | ||
918 | cb_pos->information); | ||
919 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", | ||
920 | mei_hdr->length); | ||
921 | *slots -= mei_data2slots(mei_hdr->length); | ||
922 | if (mei_write_message(dev, mei_hdr, | ||
923 | (unsigned char *) | ||
924 | (cb_pos->request_buffer.data + | ||
925 | cb_pos->information), | ||
926 | mei_hdr->length)) { | ||
927 | cl->status = -ENODEV; | ||
928 | list_move_tail(&cb_pos->cb_list, | ||
929 | &cmpl_list->mei_cb.cb_list); | ||
930 | return -ENODEV; | ||
931 | } else { | ||
932 | if (mei_flow_ctrl_reduce(dev, cl)) | ||
933 | return -ENODEV; | ||
934 | cl->status = 0; | ||
935 | cb_pos->information += mei_hdr->length; | ||
936 | list_move_tail(&cb_pos->cb_list, | ||
937 | &dev->write_waiting_list.mei_cb.cb_list); | ||
938 | } | ||
939 | } else if (*slots == dev->hbuf_depth) { | 734 | } else if (*slots == dev->hbuf_depth) { |
940 | /* buffer is still empty */ | 735 | msg_slots = *slots; |
941 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 736 | len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); |
942 | mei_hdr->host_addr = cl->host_client_id; | 737 | mei_hdr->length = len; |
943 | mei_hdr->me_addr = cl->me_client_id; | ||
944 | mei_hdr->length = | ||
945 | (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
946 | mei_hdr->msg_complete = 0; | 738 | mei_hdr->msg_complete = 0; |
947 | mei_hdr->reserved = 0; | ||
948 | *slots -= mei_data2slots(mei_hdr->length); | ||
949 | if (mei_write_message(dev, mei_hdr, | ||
950 | (unsigned char *) | ||
951 | (cb_pos->request_buffer.data + | ||
952 | cb_pos->information), | ||
953 | mei_hdr->length)) { | ||
954 | cl->status = -ENODEV; | ||
955 | list_move_tail(&cb_pos->cb_list, | ||
956 | &cmpl_list->mei_cb.cb_list); | ||
957 | return -ENODEV; | ||
958 | } else { | ||
959 | cb_pos->information += mei_hdr->length; | ||
960 | dev_dbg(&dev->pdev->dev, | ||
961 | "cb_pos->request_buffer.size =%d" | ||
962 | " mei_hdr->msg_complete = %d\n", | ||
963 | cb_pos->request_buffer.size, | ||
964 | mei_hdr->msg_complete); | ||
965 | dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", | ||
966 | cb_pos->information); | ||
967 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", | ||
968 | mei_hdr->length); | ||
969 | } | ||
970 | return -EMSGSIZE; | ||
971 | } else { | 739 | } else { |
972 | return -EBADMSG; | 740 | /* wait for next time the host buffer is empty */ |
741 | return 0; | ||
973 | } | 742 | } |
974 | 743 | ||
975 | return 0; | 744 | dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", |
976 | } | 745 | cb->request_buffer.size, cb->buf_idx); |
977 | 746 | dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n", | |
978 | /** | 747 | mei_hdr->length, mei_hdr->msg_complete); |
979 | * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation. | ||
980 | * | ||
981 | * @dev: the device structure. | ||
982 | * @slots: free slots. | ||
983 | * @cb_pos: callback block. | ||
984 | * @cl: private data of the file object. | ||
985 | * @cmpl_list: complete list. | ||
986 | * | ||
987 | * returns 0, OK; otherwise, error. | ||
988 | */ | ||
989 | static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, | ||
990 | struct mei_cl_cb *cb_pos, | ||
991 | struct mei_cl *cl, | ||
992 | struct mei_io_list *cmpl_list) | ||
993 | { | ||
994 | struct mei_msg_hdr *mei_hdr; | ||
995 | |||
996 | if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + | ||
997 | dev->iamthif_msg_buf_size - | ||
998 | dev->iamthif_msg_buf_index)) { | ||
999 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
1000 | mei_hdr->host_addr = cl->host_client_id; | ||
1001 | mei_hdr->me_addr = cl->me_client_id; | ||
1002 | mei_hdr->length = dev->iamthif_msg_buf_size - | ||
1003 | dev->iamthif_msg_buf_index; | ||
1004 | mei_hdr->msg_complete = 1; | ||
1005 | mei_hdr->reserved = 0; | ||
1006 | |||
1007 | *slots -= mei_data2slots(mei_hdr->length); | ||
1008 | |||
1009 | if (mei_write_message(dev, mei_hdr, | ||
1010 | (dev->iamthif_msg_buf + | ||
1011 | dev->iamthif_msg_buf_index), | ||
1012 | mei_hdr->length)) { | ||
1013 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
1014 | cl->status = -ENODEV; | ||
1015 | list_del(&cb_pos->cb_list); | ||
1016 | return -ENODEV; | ||
1017 | } else { | ||
1018 | if (mei_flow_ctrl_reduce(dev, cl)) | ||
1019 | return -ENODEV; | ||
1020 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
1021 | cb_pos->information = dev->iamthif_msg_buf_index; | ||
1022 | cl->status = 0; | ||
1023 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
1024 | dev->iamthif_flow_control_pending = true; | ||
1025 | /* save iamthif cb sent to amthi client */ | ||
1026 | dev->iamthif_current_cb = cb_pos; | ||
1027 | list_move_tail(&cb_pos->cb_list, | ||
1028 | &dev->write_waiting_list.mei_cb.cb_list); | ||
1029 | 748 | ||
1030 | } | 749 | *slots -= msg_slots; |
1031 | } else if (*slots == dev->hbuf_depth) { | 750 | if (mei_write_message(dev, mei_hdr, |
1032 | /* buffer is still empty */ | 751 | cb->request_buffer.data + cb->buf_idx, len)) { |
1033 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 752 | cl->status = -ENODEV; |
1034 | mei_hdr->host_addr = cl->host_client_id; | 753 | list_move_tail(&cb->list, &cmpl_list->list); |
1035 | mei_hdr->me_addr = cl->me_client_id; | 754 | return -ENODEV; |
1036 | mei_hdr->length = | 755 | } |
1037 | (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
1038 | mei_hdr->msg_complete = 0; | ||
1039 | mei_hdr->reserved = 0; | ||
1040 | 756 | ||
1041 | *slots -= mei_data2slots(mei_hdr->length); | 757 | if (mei_flow_ctrl_reduce(dev, cl)) |
758 | return -ENODEV; | ||
1042 | 759 | ||
1043 | if (mei_write_message(dev, mei_hdr, | 760 | cl->status = 0; |
1044 | (dev->iamthif_msg_buf + | 761 | cb->buf_idx += mei_hdr->length; |
1045 | dev->iamthif_msg_buf_index), | 762 | if (mei_hdr->msg_complete) |
1046 | mei_hdr->length)) { | 763 | list_move_tail(&cb->list, &dev->write_waiting_list.list); |
1047 | cl->status = -ENODEV; | ||
1048 | list_del(&cb_pos->cb_list); | ||
1049 | } else { | ||
1050 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
1051 | } | ||
1052 | return -EMSGSIZE; | ||
1053 | } else { | ||
1054 | return -EBADMSG; | ||
1055 | } | ||
1056 | 764 | ||
1057 | return 0; | 765 | return 0; |
1058 | } | 766 | } |
@@ -1067,7 +775,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, | |||
1067 | * | 775 | * |
1068 | * returns 0 on success, <0 on failure. | 776 | * returns 0 on success, <0 on failure. |
1069 | */ | 777 | */ |
1070 | static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list, | 778 | static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, |
1071 | struct mei_device *dev, | 779 | struct mei_device *dev, |
1072 | s32 *slots) | 780 | s32 *slots) |
1073 | { | 781 | { |
@@ -1130,8 +838,8 @@ static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list, | |||
1130 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); | 838 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); |
1131 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", | 839 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", |
1132 | mei_hdr->length); | 840 | mei_hdr->length); |
1133 | ret = mei_irq_thread_read_amthi_message(cmpl_list, | 841 | |
1134 | dev, mei_hdr); | 842 | ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr); |
1135 | if (ret) | 843 | if (ret) |
1136 | goto end; | 844 | goto end; |
1137 | 845 | ||
@@ -1164,53 +872,51 @@ end: | |||
1164 | * mei_irq_thread_write_handler - bottom half write routine after | 872 | * mei_irq_thread_write_handler - bottom half write routine after |
1165 | * ISR to handle the write processing. | 873 | * ISR to handle the write processing. |
1166 | * | 874 | * |
1167 | * @cmpl_list: An instance of our list structure | ||
1168 | * @dev: the device structure | 875 | * @dev: the device structure |
1169 | * @slots: slots to write. | 876 | * @cmpl_list: An instance of our list structure |
1170 | * | 877 | * |
1171 | * returns 0 on success, <0 on failure. | 878 | * returns 0 on success, <0 on failure. |
1172 | */ | 879 | */ |
1173 | static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, | 880 | static int mei_irq_thread_write_handler(struct mei_device *dev, |
1174 | struct mei_device *dev, | 881 | struct mei_cl_cb *cmpl_list) |
1175 | s32 *slots) | ||
1176 | { | 882 | { |
1177 | 883 | ||
1178 | struct mei_cl *cl; | 884 | struct mei_cl *cl; |
1179 | struct mei_cl_cb *pos = NULL, *next = NULL; | 885 | struct mei_cl_cb *pos = NULL, *next = NULL; |
1180 | struct mei_io_list *list; | 886 | struct mei_cl_cb *list; |
887 | s32 slots; | ||
1181 | int ret; | 888 | int ret; |
1182 | 889 | ||
1183 | if (!mei_hbuf_is_empty(dev)) { | 890 | if (!mei_hbuf_is_empty(dev)) { |
1184 | dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); | 891 | dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); |
1185 | return 0; | 892 | return 0; |
1186 | } | 893 | } |
1187 | *slots = mei_hbuf_empty_slots(dev); | 894 | slots = mei_hbuf_empty_slots(dev); |
1188 | if (*slots <= 0) | 895 | if (slots <= 0) |
1189 | return -EMSGSIZE; | 896 | return -EMSGSIZE; |
1190 | 897 | ||
1191 | /* complete all waiting for write CB */ | 898 | /* complete all waiting for write CB */ |
1192 | dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); | 899 | dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); |
1193 | 900 | ||
1194 | list = &dev->write_waiting_list; | 901 | list = &dev->write_waiting_list; |
1195 | list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) { | 902 | list_for_each_entry_safe(pos, next, &list->list, list) { |
1196 | cl = (struct mei_cl *)pos->file_private; | 903 | cl = pos->cl; |
1197 | if (cl == NULL) | 904 | if (cl == NULL) |
1198 | continue; | 905 | continue; |
1199 | 906 | ||
1200 | cl->status = 0; | 907 | cl->status = 0; |
1201 | list_del(&pos->cb_list); | 908 | list_del(&pos->list); |
1202 | if (MEI_WRITING == cl->writing_state && | 909 | if (MEI_WRITING == cl->writing_state && |
1203 | (pos->major_file_operations == MEI_WRITE) && | 910 | pos->fop_type == MEI_FOP_WRITE && |
1204 | (cl != &dev->iamthif_cl)) { | 911 | cl != &dev->iamthif_cl) { |
1205 | dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); | 912 | dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); |
1206 | cl->writing_state = MEI_WRITE_COMPLETE; | 913 | cl->writing_state = MEI_WRITE_COMPLETE; |
1207 | list_add_tail(&pos->cb_list, | 914 | list_add_tail(&pos->list, &cmpl_list->list); |
1208 | &cmpl_list->mei_cb.cb_list); | ||
1209 | } | 915 | } |
1210 | if (cl == &dev->iamthif_cl) { | 916 | if (cl == &dev->iamthif_cl) { |
1211 | dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); | 917 | dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); |
1212 | if (dev->iamthif_flow_control_pending) { | 918 | if (dev->iamthif_flow_control_pending) { |
1213 | ret = _mei_irq_thread_iamthif_read(dev, slots); | 919 | ret = mei_amthif_irq_read(dev, &slots); |
1214 | if (ret) | 920 | if (ret) |
1215 | return ret; | 921 | return ret; |
1216 | } | 922 | } |
@@ -1222,15 +928,11 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, | |||
1222 | wake_up_interruptible(&dev->wait_stop_wd); | 928 | wake_up_interruptible(&dev->wait_stop_wd); |
1223 | } | 929 | } |
1224 | 930 | ||
1225 | if (dev->extra_write_index) { | 931 | if (dev->wr_ext_msg.hdr.length) { |
1226 | dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n", | 932 | mei_write_message(dev, &dev->wr_ext_msg.hdr, |
1227 | dev->extra_write_index); | 933 | dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length); |
1228 | mei_write_message(dev, | 934 | slots -= mei_data2slots(dev->wr_ext_msg.hdr.length); |
1229 | (struct mei_msg_hdr *) &dev->ext_msg_buf[0], | 935 | dev->wr_ext_msg.hdr.length = 0; |
1230 | (unsigned char *) &dev->ext_msg_buf[1], | ||
1231 | (dev->extra_write_index - 1) * sizeof(u32)); | ||
1232 | *slots -= dev->extra_write_index; | ||
1233 | dev->extra_write_index = 0; | ||
1234 | } | 936 | } |
1235 | if (dev->dev_state == MEI_DEV_ENABLED) { | 937 | if (dev->dev_state == MEI_DEV_ENABLED) { |
1236 | if (dev->wd_pending && | 938 | if (dev->wd_pending && |
@@ -1243,41 +945,43 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, | |||
1243 | dev->wd_pending = false; | 945 | dev->wd_pending = false; |
1244 | 946 | ||
1245 | if (dev->wd_state == MEI_WD_RUNNING) | 947 | if (dev->wd_state == MEI_WD_RUNNING) |
1246 | *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); | 948 | slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); |
1247 | else | 949 | else |
1248 | *slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); | 950 | slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); |
1249 | } | 951 | } |
1250 | } | 952 | } |
1251 | 953 | ||
1252 | /* complete control write list CB */ | 954 | /* complete control write list CB */ |
1253 | dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); | 955 | dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); |
1254 | list_for_each_entry_safe(pos, next, | 956 | list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) { |
1255 | &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) { | 957 | cl = pos->cl; |
1256 | cl = (struct mei_cl *) pos->file_private; | ||
1257 | if (!cl) { | 958 | if (!cl) { |
1258 | list_del(&pos->cb_list); | 959 | list_del(&pos->list); |
1259 | return -ENODEV; | 960 | return -ENODEV; |
1260 | } | 961 | } |
1261 | switch (pos->major_file_operations) { | 962 | switch (pos->fop_type) { |
1262 | case MEI_CLOSE: | 963 | case MEI_FOP_CLOSE: |
1263 | /* send disconnect message */ | 964 | /* send disconnect message */ |
1264 | ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list); | 965 | ret = _mei_irq_thread_close(dev, &slots, pos, |
966 | cl, cmpl_list); | ||
1265 | if (ret) | 967 | if (ret) |
1266 | return ret; | 968 | return ret; |
1267 | 969 | ||
1268 | break; | 970 | break; |
1269 | case MEI_READ: | 971 | case MEI_FOP_READ: |
1270 | /* send flow control message */ | 972 | /* send flow control message */ |
1271 | ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list); | 973 | ret = _mei_irq_thread_read(dev, &slots, pos, |
974 | cl, cmpl_list); | ||
1272 | if (ret) | 975 | if (ret) |
1273 | return ret; | 976 | return ret; |
1274 | 977 | ||
1275 | break; | 978 | break; |
1276 | case MEI_IOCTL: | 979 | case MEI_FOP_IOCTL: |
1277 | /* connect message */ | 980 | /* connect message */ |
1278 | if (mei_other_client_is_connecting(dev, cl)) | 981 | if (mei_other_client_is_connecting(dev, cl)) |
1279 | continue; | 982 | continue; |
1280 | ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list); | 983 | ret = _mei_irq_thread_ioctl(dev, &slots, pos, |
984 | cl, cmpl_list); | ||
1281 | if (ret) | 985 | if (ret) |
1282 | return ret; | 986 | return ret; |
1283 | 987 | ||
@@ -1290,40 +994,26 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, | |||
1290 | } | 994 | } |
1291 | /* complete write list CB */ | 995 | /* complete write list CB */ |
1292 | dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); | 996 | dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); |
1293 | list_for_each_entry_safe(pos, next, | 997 | list_for_each_entry_safe(pos, next, &dev->write_list.list, list) { |
1294 | &dev->write_list.mei_cb.cb_list, cb_list) { | 998 | cl = pos->cl; |
1295 | cl = (struct mei_cl *)pos->file_private; | ||
1296 | if (cl == NULL) | 999 | if (cl == NULL) |
1297 | continue; | 1000 | continue; |
1298 | 1001 | if (mei_flow_ctrl_creds(dev, cl) <= 0) { | |
1299 | if (cl != &dev->iamthif_cl) { | 1002 | dev_dbg(&dev->pdev->dev, |
1300 | if (mei_flow_ctrl_creds(dev, cl) <= 0) { | 1003 | "No flow control credentials for client %d, not sending.\n", |
1301 | dev_dbg(&dev->pdev->dev, | 1004 | cl->host_client_id); |
1302 | "No flow control credentials for client %d, not sending.\n", | 1005 | continue; |
1303 | cl->host_client_id); | ||
1304 | continue; | ||
1305 | } | ||
1306 | ret = _mei_irq_thread_cmpl(dev, slots, pos, | ||
1307 | cl, cmpl_list); | ||
1308 | if (ret) | ||
1309 | return ret; | ||
1310 | |||
1311 | } else if (cl == &dev->iamthif_cl) { | ||
1312 | /* IAMTHIF IOCTL */ | ||
1313 | dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n"); | ||
1314 | if (mei_flow_ctrl_creds(dev, cl) <= 0) { | ||
1315 | dev_dbg(&dev->pdev->dev, | ||
1316 | "No flow control credentials for amthi client %d.\n", | ||
1317 | cl->host_client_id); | ||
1318 | continue; | ||
1319 | } | ||
1320 | ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos, | ||
1321 | cl, cmpl_list); | ||
1322 | if (ret) | ||
1323 | return ret; | ||
1324 | |||
1325 | } | 1006 | } |
1326 | 1007 | ||
1008 | if (cl == &dev->iamthif_cl) | ||
1009 | ret = mei_amthif_irq_write_complete(dev, &slots, | ||
1010 | pos, cmpl_list); | ||
1011 | else | ||
1012 | ret = mei_irq_thread_write_complete(dev, &slots, pos, | ||
1013 | cmpl_list); | ||
1014 | if (ret) | ||
1015 | return ret; | ||
1016 | |||
1327 | } | 1017 | } |
1328 | return 0; | 1018 | return 0; |
1329 | } | 1019 | } |
@@ -1342,7 +1032,6 @@ void mei_timer(struct work_struct *work) | |||
1342 | unsigned long timeout; | 1032 | unsigned long timeout; |
1343 | struct mei_cl *cl_pos = NULL; | 1033 | struct mei_cl *cl_pos = NULL; |
1344 | struct mei_cl *cl_next = NULL; | 1034 | struct mei_cl *cl_next = NULL; |
1345 | struct list_head *amthi_complete_list = NULL; | ||
1346 | struct mei_cl_cb *cb_pos = NULL; | 1035 | struct mei_cl_cb *cb_pos = NULL; |
1347 | struct mei_cl_cb *cb_next = NULL; | 1036 | struct mei_cl_cb *cb_next = NULL; |
1348 | 1037 | ||
@@ -1385,19 +1074,18 @@ void mei_timer(struct work_struct *work) | |||
1385 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | 1074 | dev->iamthif_state = MEI_IAMTHIF_IDLE; |
1386 | dev->iamthif_timer = 0; | 1075 | dev->iamthif_timer = 0; |
1387 | 1076 | ||
1388 | if (dev->iamthif_current_cb) | 1077 | mei_io_cb_free(dev->iamthif_current_cb); |
1389 | mei_free_cb_private(dev->iamthif_current_cb); | 1078 | dev->iamthif_current_cb = NULL; |
1390 | 1079 | ||
1391 | dev->iamthif_file_object = NULL; | 1080 | dev->iamthif_file_object = NULL; |
1392 | dev->iamthif_current_cb = NULL; | 1081 | mei_amthif_run_next_cmd(dev); |
1393 | mei_run_next_iamthif_cmd(dev); | ||
1394 | } | 1082 | } |
1395 | } | 1083 | } |
1396 | 1084 | ||
1397 | if (dev->iamthif_timer) { | 1085 | if (dev->iamthif_timer) { |
1398 | 1086 | ||
1399 | timeout = dev->iamthif_timer + | 1087 | timeout = dev->iamthif_timer + |
1400 | msecs_to_jiffies(IAMTHIF_READ_TIMER); | 1088 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); |
1401 | 1089 | ||
1402 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", | 1090 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", |
1403 | dev->iamthif_timer); | 1091 | dev->iamthif_timer); |
@@ -1411,25 +1099,22 @@ void mei_timer(struct work_struct *work) | |||
1411 | 1099 | ||
1412 | dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n"); | 1100 | dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n"); |
1413 | 1101 | ||
1414 | amthi_complete_list = &dev->amthi_read_complete_list. | 1102 | list_for_each_entry_safe(cb_pos, cb_next, |
1415 | mei_cb.cb_list; | 1103 | &dev->amthif_rd_complete_list.list, list) { |
1416 | |||
1417 | list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) { | ||
1418 | 1104 | ||
1419 | cl_pos = cb_pos->file_object->private_data; | 1105 | cl_pos = cb_pos->file_object->private_data; |
1420 | 1106 | ||
1421 | /* Finding the AMTHI entry. */ | 1107 | /* Finding the AMTHI entry. */ |
1422 | if (cl_pos == &dev->iamthif_cl) | 1108 | if (cl_pos == &dev->iamthif_cl) |
1423 | list_del(&cb_pos->cb_list); | 1109 | list_del(&cb_pos->list); |
1424 | } | 1110 | } |
1425 | if (dev->iamthif_current_cb) | 1111 | mei_io_cb_free(dev->iamthif_current_cb); |
1426 | mei_free_cb_private(dev->iamthif_current_cb); | 1112 | dev->iamthif_current_cb = NULL; |
1427 | 1113 | ||
1428 | dev->iamthif_file_object->private_data = NULL; | 1114 | dev->iamthif_file_object->private_data = NULL; |
1429 | dev->iamthif_file_object = NULL; | 1115 | dev->iamthif_file_object = NULL; |
1430 | dev->iamthif_current_cb = NULL; | ||
1431 | dev->iamthif_timer = 0; | 1116 | dev->iamthif_timer = 0; |
1432 | mei_run_next_iamthif_cmd(dev); | 1117 | mei_amthif_run_next_cmd(dev); |
1433 | 1118 | ||
1434 | } | 1119 | } |
1435 | } | 1120 | } |
@@ -1451,7 +1136,7 @@ out: | |||
1451 | irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) | 1136 | irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) |
1452 | { | 1137 | { |
1453 | struct mei_device *dev = (struct mei_device *) dev_id; | 1138 | struct mei_device *dev = (struct mei_device *) dev_id; |
1454 | struct mei_io_list complete_list; | 1139 | struct mei_cl_cb complete_list; |
1455 | struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; | 1140 | struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; |
1456 | struct mei_cl *cl; | 1141 | struct mei_cl *cl; |
1457 | s32 slots; | 1142 | s32 slots; |
@@ -1504,17 +1189,17 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) | |||
1504 | } | 1189 | } |
1505 | /* check slots available for reading */ | 1190 | /* check slots available for reading */ |
1506 | slots = mei_count_full_read_slots(dev); | 1191 | slots = mei_count_full_read_slots(dev); |
1507 | dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", | 1192 | while (slots > 0) { |
1508 | slots, dev->extra_write_index); | 1193 | /* we have urgent data to send so break the read */ |
1509 | while (slots > 0 && !dev->extra_write_index) { | 1194 | if (dev->wr_ext_msg.hdr.length) |
1510 | dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", | 1195 | break; |
1511 | slots, dev->extra_write_index); | 1196 | dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots); |
1512 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); | 1197 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); |
1513 | rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); | 1198 | rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); |
1514 | if (rets) | 1199 | if (rets) |
1515 | goto end; | 1200 | goto end; |
1516 | } | 1201 | } |
1517 | rets = mei_irq_thread_write_handler(&complete_list, dev, &slots); | 1202 | rets = mei_irq_thread_write_handler(dev, &complete_list); |
1518 | end: | 1203 | end: |
1519 | dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); | 1204 | dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); |
1520 | dev->host_hw_state = mei_hcsr_read(dev); | 1205 | dev->host_hw_state = mei_hcsr_read(dev); |
@@ -1531,21 +1216,20 @@ end: | |||
1531 | wake_up_interruptible(&dev->wait_recvd_msg); | 1216 | wake_up_interruptible(&dev->wait_recvd_msg); |
1532 | bus_message_received = false; | 1217 | bus_message_received = false; |
1533 | } | 1218 | } |
1534 | if (list_empty(&complete_list.mei_cb.cb_list)) | 1219 | if (list_empty(&complete_list.list)) |
1535 | return IRQ_HANDLED; | 1220 | return IRQ_HANDLED; |
1536 | 1221 | ||
1537 | 1222 | ||
1538 | list_for_each_entry_safe(cb_pos, cb_next, | 1223 | list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) { |
1539 | &complete_list.mei_cb.cb_list, cb_list) { | 1224 | cl = cb_pos->cl; |
1540 | cl = (struct mei_cl *)cb_pos->file_private; | 1225 | list_del(&cb_pos->list); |
1541 | list_del(&cb_pos->cb_list); | ||
1542 | if (cl) { | 1226 | if (cl) { |
1543 | if (cl != &dev->iamthif_cl) { | 1227 | if (cl != &dev->iamthif_cl) { |
1544 | dev_dbg(&dev->pdev->dev, "completing call back.\n"); | 1228 | dev_dbg(&dev->pdev->dev, "completing call back.\n"); |
1545 | _mei_cmpl(cl, cb_pos); | 1229 | _mei_cmpl(cl, cb_pos); |
1546 | cb_pos = NULL; | 1230 | cb_pos = NULL; |
1547 | } else if (cl == &dev->iamthif_cl) { | 1231 | } else if (cl == &dev->iamthif_cl) { |
1548 | _mei_cmpl_iamthif(dev, cb_pos); | 1232 | mei_amthif_complete(dev, cb_pos); |
1549 | } | 1233 | } |
1550 | } | 1234 | } |
1551 | } | 1235 | } |
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c index fcba98eb892e..eb93a1b53b9b 100644 --- a/drivers/misc/mei/iorw.c +++ b/drivers/misc/mei/iorw.c | |||
@@ -39,6 +39,95 @@ | |||
39 | #include "interface.h" | 39 | #include "interface.h" |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * mei_io_cb_free - free mei_cb_private related memory | ||
43 | * | ||
44 | * @cb: mei callback struct | ||
45 | */ | ||
46 | void mei_io_cb_free(struct mei_cl_cb *cb) | ||
47 | { | ||
48 | if (cb == NULL) | ||
49 | return; | ||
50 | |||
51 | kfree(cb->request_buffer.data); | ||
52 | kfree(cb->response_buffer.data); | ||
53 | kfree(cb); | ||
54 | } | ||
55 | /** | ||
56 | * mei_io_cb_init - allocate and initialize io callback | ||
57 | * | ||
58 | * @cl - mei client | ||
59 | * @file: pointer to file structure | ||
60 | * | ||
61 | * returns mei_cl_cb pointer or NULL; | ||
62 | */ | ||
63 | struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp) | ||
64 | { | ||
65 | struct mei_cl_cb *cb; | ||
66 | |||
67 | cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | ||
68 | if (!cb) | ||
69 | return NULL; | ||
70 | |||
71 | mei_io_list_init(cb); | ||
72 | |||
73 | cb->file_object = fp; | ||
74 | cb->cl = cl; | ||
75 | cb->buf_idx = 0; | ||
76 | return cb; | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * mei_io_cb_alloc_req_buf - allocate request buffer | ||
82 | * | ||
83 | * @cb - io callback structure | ||
84 | * @size: size of the buffer | ||
85 | * | ||
86 | * returns 0 on success | ||
87 | * -EINVAL if cb is NULL | ||
88 | * -ENOMEM if allocation failed | ||
89 | */ | ||
90 | int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length) | ||
91 | { | ||
92 | if (!cb) | ||
93 | return -EINVAL; | ||
94 | |||
95 | if (length == 0) | ||
96 | return 0; | ||
97 | |||
98 | cb->request_buffer.data = kmalloc(length, GFP_KERNEL); | ||
99 | if (!cb->request_buffer.data) | ||
100 | return -ENOMEM; | ||
101 | cb->request_buffer.size = length; | ||
102 | return 0; | ||
103 | } | ||
104 | /** | ||
105 | * mei_io_cb_alloc_req_buf - allocate respose buffer | ||
106 | * | ||
107 | * @cb - io callback structure | ||
108 | * @size: size of the buffer | ||
109 | * | ||
110 | * returns 0 on success | ||
111 | * -EINVAL if cb is NULL | ||
112 | * -ENOMEM if allocation failed | ||
113 | */ | ||
114 | int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length) | ||
115 | { | ||
116 | if (!cb) | ||
117 | return -EINVAL; | ||
118 | |||
119 | if (length == 0) | ||
120 | return 0; | ||
121 | |||
122 | cb->response_buffer.data = kmalloc(length, GFP_KERNEL); | ||
123 | if (!cb->response_buffer.data) | ||
124 | return -ENOMEM; | ||
125 | cb->response_buffer.size = length; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | |||
130 | /** | ||
42 | * mei_me_cl_by_id return index to me_clients for client_id | 131 | * mei_me_cl_by_id return index to me_clients for client_id |
43 | * | 132 | * |
44 | * @dev: the device structure | 133 | * @dev: the device structure |
@@ -82,9 +171,7 @@ int mei_ioctl_connect_client(struct file *file, | |||
82 | struct mei_cl_cb *cb; | 171 | struct mei_cl_cb *cb; |
83 | struct mei_client *client; | 172 | struct mei_client *client; |
84 | struct mei_cl *cl; | 173 | struct mei_cl *cl; |
85 | struct mei_cl *cl_pos = NULL; | 174 | long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT); |
86 | struct mei_cl *cl_next = NULL; | ||
87 | long timeout = CONNECT_TIMEOUT; | ||
88 | int i; | 175 | int i; |
89 | int err; | 176 | int err; |
90 | int rets; | 177 | int rets; |
@@ -97,16 +184,14 @@ int mei_ioctl_connect_client(struct file *file, | |||
97 | 184 | ||
98 | dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n"); | 185 | dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n"); |
99 | 186 | ||
100 | |||
101 | /* buffered ioctl cb */ | 187 | /* buffered ioctl cb */ |
102 | cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | 188 | cb = mei_io_cb_init(cl, file); |
103 | if (!cb) { | 189 | if (!cb) { |
104 | rets = -ENOMEM; | 190 | rets = -ENOMEM; |
105 | goto end; | 191 | goto end; |
106 | } | 192 | } |
107 | INIT_LIST_HEAD(&cb->cb_list); | ||
108 | 193 | ||
109 | cb->major_file_operations = MEI_IOCTL; | 194 | cb->fop_type = MEI_FOP_IOCTL; |
110 | 195 | ||
111 | if (dev->dev_state != MEI_DEV_ENABLED) { | 196 | if (dev->dev_state != MEI_DEV_ENABLED) { |
112 | rets = -ENODEV; | 197 | rets = -ENODEV; |
@@ -142,21 +227,9 @@ int mei_ioctl_connect_client(struct file *file, | |||
142 | goto end; | 227 | goto end; |
143 | } | 228 | } |
144 | clear_bit(cl->host_client_id, dev->host_clients_map); | 229 | clear_bit(cl->host_client_id, dev->host_clients_map); |
145 | list_for_each_entry_safe(cl_pos, cl_next, | 230 | mei_me_cl_unlink(dev, cl); |
146 | &dev->file_list, link) { | ||
147 | if (mei_cl_cmp_id(cl, cl_pos)) { | ||
148 | dev_dbg(&dev->pdev->dev, | ||
149 | "remove file private data node host" | ||
150 | " client = %d, ME client = %d.\n", | ||
151 | cl_pos->host_client_id, | ||
152 | cl_pos->me_client_id); | ||
153 | list_del(&cl_pos->link); | ||
154 | } | ||
155 | 231 | ||
156 | } | ||
157 | dev_dbg(&dev->pdev->dev, "free file private data memory.\n"); | ||
158 | kfree(cl); | 232 | kfree(cl); |
159 | |||
160 | cl = NULL; | 233 | cl = NULL; |
161 | file->private_data = &dev->iamthif_cl; | 234 | file->private_data = &dev->iamthif_cl; |
162 | 235 | ||
@@ -192,25 +265,19 @@ int mei_ioctl_connect_client(struct file *file, | |||
192 | } else { | 265 | } else { |
193 | dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n"); | 266 | dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n"); |
194 | cl->timer_count = MEI_CONNECT_TIMEOUT; | 267 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
195 | cb->file_private = cl; | 268 | list_add_tail(&cb->list, &dev->ctrl_rd_list.list); |
196 | list_add_tail(&cb->cb_list, | ||
197 | &dev->ctrl_rd_list.mei_cb. | ||
198 | cb_list); | ||
199 | } | 269 | } |
200 | 270 | ||
201 | 271 | ||
202 | } else { | 272 | } else { |
203 | dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n"); | 273 | dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n"); |
204 | cb->file_private = cl; | ||
205 | dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n"); | 274 | dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n"); |
206 | list_add_tail(&cb->cb_list, | 275 | list_add_tail(&cb->list, &dev->ctrl_wr_list.list); |
207 | &dev->ctrl_wr_list.mei_cb.cb_list); | ||
208 | } | 276 | } |
209 | mutex_unlock(&dev->device_lock); | 277 | mutex_unlock(&dev->device_lock); |
210 | err = wait_event_timeout(dev->wait_recvd_msg, | 278 | err = wait_event_timeout(dev->wait_recvd_msg, |
211 | (MEI_FILE_CONNECTED == cl->state || | 279 | (MEI_FILE_CONNECTED == cl->state || |
212 | MEI_FILE_DISCONNECTED == cl->state), | 280 | MEI_FILE_DISCONNECTED == cl->state), timeout); |
213 | timeout * HZ); | ||
214 | 281 | ||
215 | mutex_lock(&dev->device_lock); | 282 | mutex_lock(&dev->device_lock); |
216 | if (MEI_FILE_CONNECTED == cl->state) { | 283 | if (MEI_FILE_CONNECTED == cl->state) { |
@@ -234,153 +301,7 @@ int mei_ioctl_connect_client(struct file *file, | |||
234 | rets = 0; | 301 | rets = 0; |
235 | end: | 302 | end: |
236 | dev_dbg(&dev->pdev->dev, "free connect cb memory."); | 303 | dev_dbg(&dev->pdev->dev, "free connect cb memory."); |
237 | kfree(cb); | 304 | mei_io_cb_free(cb); |
238 | return rets; | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * find_amthi_read_list_entry - finds a amthilist entry for current file | ||
243 | * | ||
244 | * @dev: the device structure | ||
245 | * @file: pointer to file object | ||
246 | * | ||
247 | * returns returned a list entry on success, NULL on failure. | ||
248 | */ | ||
249 | struct mei_cl_cb *find_amthi_read_list_entry( | ||
250 | struct mei_device *dev, | ||
251 | struct file *file) | ||
252 | { | ||
253 | struct mei_cl *cl_temp; | ||
254 | struct mei_cl_cb *pos = NULL; | ||
255 | struct mei_cl_cb *next = NULL; | ||
256 | |||
257 | list_for_each_entry_safe(pos, next, | ||
258 | &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) { | ||
259 | cl_temp = (struct mei_cl *)pos->file_private; | ||
260 | if (cl_temp && cl_temp == &dev->iamthif_cl && | ||
261 | pos->file_object == file) | ||
262 | return pos; | ||
263 | } | ||
264 | return NULL; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * amthi_read - read data from AMTHI client | ||
269 | * | ||
270 | * @dev: the device structure | ||
271 | * @if_num: minor number | ||
272 | * @file: pointer to file object | ||
273 | * @*ubuf: pointer to user data in user space | ||
274 | * @length: data length to read | ||
275 | * @offset: data read offset | ||
276 | * | ||
277 | * Locking: called under "dev->device_lock" lock | ||
278 | * | ||
279 | * returns | ||
280 | * returned data length on success, | ||
281 | * zero if no data to read, | ||
282 | * negative on failure. | ||
283 | */ | ||
284 | int amthi_read(struct mei_device *dev, struct file *file, | ||
285 | char __user *ubuf, size_t length, loff_t *offset) | ||
286 | { | ||
287 | int rets; | ||
288 | int wait_ret; | ||
289 | struct mei_cl_cb *cb = NULL; | ||
290 | struct mei_cl *cl = file->private_data; | ||
291 | unsigned long timeout; | ||
292 | int i; | ||
293 | |||
294 | /* Only Posible if we are in timeout */ | ||
295 | if (!cl || cl != &dev->iamthif_cl) { | ||
296 | dev_dbg(&dev->pdev->dev, "bad file ext.\n"); | ||
297 | return -ETIMEDOUT; | ||
298 | } | ||
299 | |||
300 | i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); | ||
301 | |||
302 | if (i < 0) { | ||
303 | dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); | ||
304 | return -ENODEV; | ||
305 | } | ||
306 | dev_dbg(&dev->pdev->dev, "checking amthi data\n"); | ||
307 | cb = find_amthi_read_list_entry(dev, file); | ||
308 | |||
309 | /* Check for if we can block or not*/ | ||
310 | if (cb == NULL && file->f_flags & O_NONBLOCK) | ||
311 | return -EAGAIN; | ||
312 | |||
313 | |||
314 | dev_dbg(&dev->pdev->dev, "waiting for amthi data\n"); | ||
315 | while (cb == NULL) { | ||
316 | /* unlock the Mutex */ | ||
317 | mutex_unlock(&dev->device_lock); | ||
318 | |||
319 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | ||
320 | (cb = find_amthi_read_list_entry(dev, file))); | ||
321 | |||
322 | if (wait_ret) | ||
323 | return -ERESTARTSYS; | ||
324 | |||
325 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | ||
326 | |||
327 | /* Locking again the Mutex */ | ||
328 | mutex_lock(&dev->device_lock); | ||
329 | } | ||
330 | |||
331 | |||
332 | dev_dbg(&dev->pdev->dev, "Got amthi data\n"); | ||
333 | dev->iamthif_timer = 0; | ||
334 | |||
335 | if (cb) { | ||
336 | timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER); | ||
337 | dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", | ||
338 | timeout); | ||
339 | |||
340 | if (time_after(jiffies, timeout)) { | ||
341 | dev_dbg(&dev->pdev->dev, "amthi Time out\n"); | ||
342 | /* 15 sec for the message has expired */ | ||
343 | list_del(&cb->cb_list); | ||
344 | rets = -ETIMEDOUT; | ||
345 | goto free; | ||
346 | } | ||
347 | } | ||
348 | /* if the whole message will fit remove it from the list */ | ||
349 | if (cb->information >= *offset && length >= (cb->information - *offset)) | ||
350 | list_del(&cb->cb_list); | ||
351 | else if (cb->information > 0 && cb->information <= *offset) { | ||
352 | /* end of the message has been reached */ | ||
353 | list_del(&cb->cb_list); | ||
354 | rets = 0; | ||
355 | goto free; | ||
356 | } | ||
357 | /* else means that not full buffer will be read and do not | ||
358 | * remove message from deletion list | ||
359 | */ | ||
360 | |||
361 | dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n", | ||
362 | cb->response_buffer.size); | ||
363 | dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n", | ||
364 | cb->information); | ||
365 | |||
366 | /* length is being turncated to PAGE_SIZE, however, | ||
367 | * the information may be longer */ | ||
368 | length = min_t(size_t, length, (cb->information - *offset)); | ||
369 | |||
370 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) | ||
371 | rets = -EFAULT; | ||
372 | else { | ||
373 | rets = length; | ||
374 | if ((*offset + length) < cb->information) { | ||
375 | *offset += length; | ||
376 | goto out; | ||
377 | } | ||
378 | } | ||
379 | free: | ||
380 | dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n"); | ||
381 | *offset = 0; | ||
382 | mei_free_cb_private(cb); | ||
383 | out: | ||
384 | return rets; | 305 | return rets; |
385 | } | 306 | } |
386 | 307 | ||
@@ -396,7 +317,7 @@ out: | |||
396 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl) | 317 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl) |
397 | { | 318 | { |
398 | struct mei_cl_cb *cb; | 319 | struct mei_cl_cb *cb; |
399 | int rets = 0; | 320 | int rets; |
400 | int i; | 321 | int i; |
401 | 322 | ||
402 | if (cl->state != MEI_FILE_CONNECTED) | 323 | if (cl->state != MEI_FILE_CONNECTED) |
@@ -405,187 +326,41 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) | |||
405 | if (dev->dev_state != MEI_DEV_ENABLED) | 326 | if (dev->dev_state != MEI_DEV_ENABLED) |
406 | return -ENODEV; | 327 | return -ENODEV; |
407 | 328 | ||
408 | dev_dbg(&dev->pdev->dev, "check if read is pending.\n"); | ||
409 | if (cl->read_pending || cl->read_cb) { | 329 | if (cl->read_pending || cl->read_cb) { |
410 | dev_dbg(&dev->pdev->dev, "read is pending.\n"); | 330 | dev_dbg(&dev->pdev->dev, "read is pending.\n"); |
411 | return -EBUSY; | 331 | return -EBUSY; |
412 | } | 332 | } |
333 | i = mei_me_cl_by_id(dev, cl->me_client_id); | ||
334 | if (i < 0) { | ||
335 | dev_err(&dev->pdev->dev, "no such me client %d\n", | ||
336 | cl->me_client_id); | ||
337 | return -ENODEV; | ||
338 | } | ||
413 | 339 | ||
414 | cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | 340 | cb = mei_io_cb_init(cl, NULL); |
415 | if (!cb) | 341 | if (!cb) |
416 | return -ENOMEM; | 342 | return -ENOMEM; |
417 | 343 | ||
418 | dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n", | 344 | rets = mei_io_cb_alloc_resp_buf(cb, |
419 | cl->host_client_id, cl->me_client_id); | 345 | dev->me_clients[i].props.max_msg_length); |
420 | i = mei_me_cl_by_id(dev, cl->me_client_id); | 346 | if (rets) |
421 | if (i < 0) { | 347 | goto err; |
422 | rets = -ENODEV; | ||
423 | goto unlock; | ||
424 | } | ||
425 | 348 | ||
426 | cb->response_buffer.size = dev->me_clients[i].props.max_msg_length; | 349 | cb->fop_type = MEI_FOP_READ; |
427 | cb->response_buffer.data = | ||
428 | kmalloc(cb->response_buffer.size, GFP_KERNEL); | ||
429 | if (!cb->response_buffer.data) { | ||
430 | rets = -ENOMEM; | ||
431 | goto unlock; | ||
432 | } | ||
433 | dev_dbg(&dev->pdev->dev, "allocation call back data success.\n"); | ||
434 | cb->major_file_operations = MEI_READ; | ||
435 | /* make sure information is zero before we start */ | ||
436 | cb->information = 0; | ||
437 | cb->file_private = (void *) cl; | ||
438 | cl->read_cb = cb; | 350 | cl->read_cb = cb; |
439 | if (dev->mei_host_buffer_is_empty) { | 351 | if (dev->mei_host_buffer_is_empty) { |
440 | dev->mei_host_buffer_is_empty = false; | 352 | dev->mei_host_buffer_is_empty = false; |
441 | if (mei_send_flow_control(dev, cl)) { | 353 | if (mei_send_flow_control(dev, cl)) { |
442 | rets = -ENODEV; | 354 | rets = -ENODEV; |
443 | goto unlock; | 355 | goto err; |
444 | } | 356 | } |
445 | list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list); | 357 | list_add_tail(&cb->list, &dev->read_list.list); |
446 | } else { | 358 | } else { |
447 | list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list); | 359 | list_add_tail(&cb->list, &dev->ctrl_wr_list.list); |
448 | } | 360 | } |
449 | return rets; | 361 | return rets; |
450 | unlock: | 362 | err: |
451 | mei_free_cb_private(cb); | 363 | mei_io_cb_free(cb); |
452 | return rets; | 364 | return rets; |
453 | } | 365 | } |
454 | 366 | ||
455 | /** | ||
456 | * amthi_write - write iamthif data to amthi client | ||
457 | * | ||
458 | * @dev: the device structure | ||
459 | * @cb: mei call back struct | ||
460 | * | ||
461 | * returns 0 on success, <0 on failure. | ||
462 | */ | ||
463 | int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb) | ||
464 | { | ||
465 | struct mei_msg_hdr mei_hdr; | ||
466 | int ret; | ||
467 | |||
468 | if (!dev || !cb) | ||
469 | return -ENODEV; | ||
470 | |||
471 | dev_dbg(&dev->pdev->dev, "write data to amthi client.\n"); | ||
472 | |||
473 | dev->iamthif_state = MEI_IAMTHIF_WRITING; | ||
474 | dev->iamthif_current_cb = cb; | ||
475 | dev->iamthif_file_object = cb->file_object; | ||
476 | dev->iamthif_canceled = false; | ||
477 | dev->iamthif_ioctl = true; | ||
478 | dev->iamthif_msg_buf_size = cb->request_buffer.size; | ||
479 | memcpy(dev->iamthif_msg_buf, cb->request_buffer.data, | ||
480 | cb->request_buffer.size); | ||
481 | |||
482 | ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl); | ||
483 | if (ret < 0) | ||
484 | return ret; | ||
485 | |||
486 | if (ret && dev->mei_host_buffer_is_empty) { | ||
487 | ret = 0; | ||
488 | dev->mei_host_buffer_is_empty = false; | ||
489 | if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { | ||
490 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
491 | mei_hdr.msg_complete = 0; | ||
492 | } else { | ||
493 | mei_hdr.length = cb->request_buffer.size; | ||
494 | mei_hdr.msg_complete = 1; | ||
495 | } | ||
496 | |||
497 | mei_hdr.host_addr = dev->iamthif_cl.host_client_id; | ||
498 | mei_hdr.me_addr = dev->iamthif_cl.me_client_id; | ||
499 | mei_hdr.reserved = 0; | ||
500 | dev->iamthif_msg_buf_index += mei_hdr.length; | ||
501 | if (mei_write_message(dev, &mei_hdr, | ||
502 | (unsigned char *)(dev->iamthif_msg_buf), | ||
503 | mei_hdr.length)) | ||
504 | return -ENODEV; | ||
505 | |||
506 | if (mei_hdr.msg_complete) { | ||
507 | if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl)) | ||
508 | return -ENODEV; | ||
509 | dev->iamthif_flow_control_pending = true; | ||
510 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
511 | dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n"); | ||
512 | dev->iamthif_current_cb = cb; | ||
513 | dev->iamthif_file_object = cb->file_object; | ||
514 | list_add_tail(&cb->cb_list, | ||
515 | &dev->write_waiting_list.mei_cb.cb_list); | ||
516 | } else { | ||
517 | dev_dbg(&dev->pdev->dev, "message does not complete, " | ||
518 | "so add amthi cb to write list.\n"); | ||
519 | list_add_tail(&cb->cb_list, | ||
520 | &dev->write_list.mei_cb.cb_list); | ||
521 | } | ||
522 | } else { | ||
523 | if (!(dev->mei_host_buffer_is_empty)) | ||
524 | dev_dbg(&dev->pdev->dev, "host buffer is not empty"); | ||
525 | |||
526 | dev_dbg(&dev->pdev->dev, "No flow control credentials, " | ||
527 | "so add iamthif cb to write list.\n"); | ||
528 | list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list); | ||
529 | } | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | /** | ||
534 | * iamthif_ioctl_send_msg - send cmd data to amthi client | ||
535 | * | ||
536 | * @dev: the device structure | ||
537 | * | ||
538 | * returns 0 on success, <0 on failure. | ||
539 | */ | ||
540 | void mei_run_next_iamthif_cmd(struct mei_device *dev) | ||
541 | { | ||
542 | struct mei_cl *cl_tmp; | ||
543 | struct mei_cl_cb *pos = NULL; | ||
544 | struct mei_cl_cb *next = NULL; | ||
545 | int status; | ||
546 | |||
547 | if (!dev) | ||
548 | return; | ||
549 | |||
550 | dev->iamthif_msg_buf_size = 0; | ||
551 | dev->iamthif_msg_buf_index = 0; | ||
552 | dev->iamthif_canceled = false; | ||
553 | dev->iamthif_ioctl = true; | ||
554 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
555 | dev->iamthif_timer = 0; | ||
556 | dev->iamthif_file_object = NULL; | ||
557 | |||
558 | dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n"); | ||
559 | |||
560 | list_for_each_entry_safe(pos, next, | ||
561 | &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) { | ||
562 | list_del(&pos->cb_list); | ||
563 | cl_tmp = (struct mei_cl *)pos->file_private; | ||
564 | |||
565 | if (cl_tmp && cl_tmp == &dev->iamthif_cl) { | ||
566 | status = amthi_write(dev, pos); | ||
567 | if (status) { | ||
568 | dev_dbg(&dev->pdev->dev, | ||
569 | "amthi write failed status = %d\n", | ||
570 | status); | ||
571 | return; | ||
572 | } | ||
573 | break; | ||
574 | } | ||
575 | } | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * mei_free_cb_private - free mei_cb_private related memory | ||
580 | * | ||
581 | * @cb: mei callback struct | ||
582 | */ | ||
583 | void mei_free_cb_private(struct mei_cl_cb *cb) | ||
584 | { | ||
585 | if (cb == NULL) | ||
586 | return; | ||
587 | |||
588 | kfree(cb->request_buffer.data); | ||
589 | kfree(cb->response_buffer.data); | ||
590 | kfree(cb); | ||
591 | } | ||
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index e8b0858132c1..43fb52ff98ad 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -90,93 +90,6 @@ static DEFINE_MUTEX(mei_mutex); | |||
90 | 90 | ||
91 | 91 | ||
92 | /** | 92 | /** |
93 | * mei_clear_list - removes all callbacks associated with file | ||
94 | * from mei_cb_list | ||
95 | * | ||
96 | * @dev: device structure. | ||
97 | * @file: file structure | ||
98 | * @mei_cb_list: callbacks list | ||
99 | * | ||
100 | * mei_clear_list is called to clear resources associated with file | ||
101 | * when application calls close function or Ctrl-C was pressed | ||
102 | * | ||
103 | * returns true if callback removed from the list, false otherwise | ||
104 | */ | ||
105 | static bool mei_clear_list(struct mei_device *dev, | ||
106 | struct file *file, struct list_head *mei_cb_list) | ||
107 | { | ||
108 | struct mei_cl_cb *cb_pos = NULL; | ||
109 | struct mei_cl_cb *cb_next = NULL; | ||
110 | struct file *file_temp; | ||
111 | bool removed = false; | ||
112 | |||
113 | /* list all list member */ | ||
114 | list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) { | ||
115 | file_temp = (struct file *)cb_pos->file_object; | ||
116 | /* check if list member associated with a file */ | ||
117 | if (file_temp == file) { | ||
118 | /* remove member from the list */ | ||
119 | list_del(&cb_pos->cb_list); | ||
120 | /* check if cb equal to current iamthif cb */ | ||
121 | if (dev->iamthif_current_cb == cb_pos) { | ||
122 | dev->iamthif_current_cb = NULL; | ||
123 | /* send flow control to iamthif client */ | ||
124 | mei_send_flow_control(dev, &dev->iamthif_cl); | ||
125 | } | ||
126 | /* free all allocated buffers */ | ||
127 | mei_free_cb_private(cb_pos); | ||
128 | cb_pos = NULL; | ||
129 | removed = true; | ||
130 | } | ||
131 | } | ||
132 | return removed; | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * mei_clear_lists - removes all callbacks associated with file | ||
137 | * | ||
138 | * @dev: device structure | ||
139 | * @file: file structure | ||
140 | * | ||
141 | * mei_clear_lists is called to clear resources associated with file | ||
142 | * when application calls close function or Ctrl-C was pressed | ||
143 | * | ||
144 | * returns true if callback removed from the list, false otherwise | ||
145 | */ | ||
146 | static bool mei_clear_lists(struct mei_device *dev, struct file *file) | ||
147 | { | ||
148 | bool removed = false; | ||
149 | |||
150 | /* remove callbacks associated with a file */ | ||
151 | mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list); | ||
152 | if (mei_clear_list(dev, file, | ||
153 | &dev->amthi_read_complete_list.mei_cb.cb_list)) | ||
154 | removed = true; | ||
155 | |||
156 | mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list); | ||
157 | |||
158 | if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list)) | ||
159 | removed = true; | ||
160 | |||
161 | if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list)) | ||
162 | removed = true; | ||
163 | |||
164 | if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list)) | ||
165 | removed = true; | ||
166 | |||
167 | /* check if iamthif_current_cb not NULL */ | ||
168 | if (dev->iamthif_current_cb && !removed) { | ||
169 | /* check file and iamthif current cb association */ | ||
170 | if (dev->iamthif_current_cb->file_object == file) { | ||
171 | /* remove cb */ | ||
172 | mei_free_cb_private(dev->iamthif_current_cb); | ||
173 | dev->iamthif_current_cb = NULL; | ||
174 | removed = true; | ||
175 | } | ||
176 | } | ||
177 | return removed; | ||
178 | } | ||
179 | /** | ||
180 | * find_read_list_entry - find read list entry | 93 | * find_read_list_entry - find read list entry |
181 | * | 94 | * |
182 | * @dev: device structure | 95 | * @dev: device structure |
@@ -192,14 +105,9 @@ static struct mei_cl_cb *find_read_list_entry( | |||
192 | struct mei_cl_cb *next = NULL; | 105 | struct mei_cl_cb *next = NULL; |
193 | 106 | ||
194 | dev_dbg(&dev->pdev->dev, "remove read_list CB\n"); | 107 | dev_dbg(&dev->pdev->dev, "remove read_list CB\n"); |
195 | list_for_each_entry_safe(pos, next, | 108 | list_for_each_entry_safe(pos, next, &dev->read_list.list, list) |
196 | &dev->read_list.mei_cb.cb_list, cb_list) { | 109 | if (mei_cl_cmp_id(cl, pos->cl)) |
197 | struct mei_cl *cl_temp; | ||
198 | cl_temp = (struct mei_cl *)pos->file_private; | ||
199 | |||
200 | if (mei_cl_cmp_id(cl, cl_temp)) | ||
201 | return pos; | 110 | return pos; |
202 | } | ||
203 | return NULL; | 111 | return NULL; |
204 | } | 112 | } |
205 | 113 | ||
@@ -297,67 +205,51 @@ static int mei_release(struct inode *inode, struct file *file) | |||
297 | dev = cl->dev; | 205 | dev = cl->dev; |
298 | 206 | ||
299 | mutex_lock(&dev->device_lock); | 207 | mutex_lock(&dev->device_lock); |
300 | if (cl != &dev->iamthif_cl) { | 208 | if (cl == &dev->iamthif_cl) { |
301 | if (cl->state == MEI_FILE_CONNECTED) { | 209 | rets = mei_amthif_release(dev, file); |
302 | cl->state = MEI_FILE_DISCONNECTING; | 210 | goto out; |
303 | dev_dbg(&dev->pdev->dev, | 211 | } |
304 | "disconnecting client host client = %d, " | 212 | if (cl->state == MEI_FILE_CONNECTED) { |
305 | "ME client = %d\n", | 213 | cl->state = MEI_FILE_DISCONNECTING; |
306 | cl->host_client_id, | 214 | dev_dbg(&dev->pdev->dev, |
307 | cl->me_client_id); | 215 | "disconnecting client host client = %d, " |
308 | rets = mei_disconnect_host_client(dev, cl); | 216 | "ME client = %d\n", |
309 | } | ||
310 | mei_cl_flush_queues(cl); | ||
311 | dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n", | ||
312 | cl->host_client_id, | 217 | cl->host_client_id, |
313 | cl->me_client_id); | 218 | cl->me_client_id); |
219 | rets = mei_disconnect_host_client(dev, cl); | ||
220 | } | ||
221 | mei_cl_flush_queues(cl); | ||
222 | dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n", | ||
223 | cl->host_client_id, | ||
224 | cl->me_client_id); | ||
225 | |||
226 | if (dev->open_handle_count > 0) { | ||
227 | clear_bit(cl->host_client_id, dev->host_clients_map); | ||
228 | dev->open_handle_count--; | ||
229 | } | ||
230 | mei_me_cl_unlink(dev, cl); | ||
314 | 231 | ||
315 | if (dev->open_handle_count > 0) { | 232 | /* free read cb */ |
316 | clear_bit(cl->host_client_id, dev->host_clients_map); | 233 | cb = NULL; |
317 | dev->open_handle_count--; | 234 | if (cl->read_cb) { |
318 | } | 235 | cb = find_read_list_entry(dev, cl); |
319 | mei_remove_client_from_file_list(dev, cl->host_client_id); | 236 | /* Remove entry from read list */ |
320 | 237 | if (cb) | |
321 | /* free read cb */ | 238 | list_del(&cb->list); |
322 | cb = NULL; | ||
323 | if (cl->read_cb) { | ||
324 | cb = find_read_list_entry(dev, cl); | ||
325 | /* Remove entry from read list */ | ||
326 | if (cb) | ||
327 | list_del(&cb->cb_list); | ||
328 | |||
329 | cb = cl->read_cb; | ||
330 | cl->read_cb = NULL; | ||
331 | } | ||
332 | |||
333 | file->private_data = NULL; | ||
334 | |||
335 | if (cb) { | ||
336 | mei_free_cb_private(cb); | ||
337 | cb = NULL; | ||
338 | } | ||
339 | 239 | ||
340 | kfree(cl); | 240 | cb = cl->read_cb; |
341 | } else { | 241 | cl->read_cb = NULL; |
342 | if (dev->open_handle_count > 0) | 242 | } |
343 | dev->open_handle_count--; | ||
344 | |||
345 | if (dev->iamthif_file_object == file && | ||
346 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { | ||
347 | |||
348 | dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n", | ||
349 | dev->iamthif_state); | ||
350 | dev->iamthif_canceled = true; | ||
351 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) { | ||
352 | dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n"); | ||
353 | mei_run_next_iamthif_cmd(dev); | ||
354 | } | ||
355 | } | ||
356 | 243 | ||
357 | if (mei_clear_lists(dev, file)) | 244 | file->private_data = NULL; |
358 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
359 | 245 | ||
246 | if (cb) { | ||
247 | mei_io_cb_free(cb); | ||
248 | cb = NULL; | ||
360 | } | 249 | } |
250 | |||
251 | kfree(cl); | ||
252 | out: | ||
361 | mutex_unlock(&dev->device_lock); | 253 | mutex_unlock(&dev->device_lock); |
362 | return rets; | 254 | return rets; |
363 | } | 255 | } |
@@ -411,20 +303,19 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
411 | } | 303 | } |
412 | 304 | ||
413 | if (cl == &dev->iamthif_cl) { | 305 | if (cl == &dev->iamthif_cl) { |
414 | rets = amthi_read(dev, file, ubuf, length, offset); | 306 | rets = mei_amthif_read(dev, file, ubuf, length, offset); |
415 | goto out; | 307 | goto out; |
416 | } | 308 | } |
417 | 309 | ||
418 | if (cl->read_cb && cl->read_cb->information > *offset) { | 310 | if (cl->read_cb && cl->read_cb->buf_idx > *offset) { |
419 | cb = cl->read_cb; | 311 | cb = cl->read_cb; |
420 | goto copy_buffer; | 312 | goto copy_buffer; |
421 | } else if (cl->read_cb && cl->read_cb->information > 0 && | 313 | } else if (cl->read_cb && cl->read_cb->buf_idx > 0 && |
422 | cl->read_cb->information <= *offset) { | 314 | cl->read_cb->buf_idx <= *offset) { |
423 | cb = cl->read_cb; | 315 | cb = cl->read_cb; |
424 | rets = 0; | 316 | rets = 0; |
425 | goto free; | 317 | goto free; |
426 | } else if ((!cl->read_cb || !cl->read_cb->information) && | 318 | } else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) { |
427 | *offset > 0) { | ||
428 | /*Offset needs to be cleaned for contiguous reads*/ | 319 | /*Offset needs to be cleaned for contiguous reads*/ |
429 | *offset = 0; | 320 | *offset = 0; |
430 | rets = 0; | 321 | rets = 0; |
@@ -481,16 +372,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
481 | copy_buffer: | 372 | copy_buffer: |
482 | dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n", | 373 | dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n", |
483 | cb->response_buffer.size); | 374 | cb->response_buffer.size); |
484 | dev_dbg(&dev->pdev->dev, "cb->information - %lu\n", | 375 | dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx); |
485 | cb->information); | 376 | if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { |
486 | if (length == 0 || ubuf == NULL || *offset > cb->information) { | ||
487 | rets = -EMSGSIZE; | 377 | rets = -EMSGSIZE; |
488 | goto free; | 378 | goto free; |
489 | } | 379 | } |
490 | 380 | ||
491 | /* length is being truncated to PAGE_SIZE, however, */ | 381 | /* length is being truncated to PAGE_SIZE, |
492 | /* information size may be longer */ | 382 | * however buf_idx may point beyond that */ |
493 | length = min_t(size_t, length, (cb->information - *offset)); | 383 | length = min_t(size_t, length, cb->buf_idx - *offset); |
494 | 384 | ||
495 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) { | 385 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) { |
496 | rets = -EFAULT; | 386 | rets = -EFAULT; |
@@ -499,15 +389,15 @@ copy_buffer: | |||
499 | 389 | ||
500 | rets = length; | 390 | rets = length; |
501 | *offset += length; | 391 | *offset += length; |
502 | if ((unsigned long)*offset < cb->information) | 392 | if ((unsigned long)*offset < cb->buf_idx) |
503 | goto out; | 393 | goto out; |
504 | 394 | ||
505 | free: | 395 | free: |
506 | cb_pos = find_read_list_entry(dev, cl); | 396 | cb_pos = find_read_list_entry(dev, cl); |
507 | /* Remove entry from read list */ | 397 | /* Remove entry from read list */ |
508 | if (cb_pos) | 398 | if (cb_pos) |
509 | list_del(&cb_pos->cb_list); | 399 | list_del(&cb_pos->list); |
510 | mei_free_cb_private(cb); | 400 | mei_io_cb_free(cb); |
511 | cl->reading_state = MEI_IDLE; | 401 | cl->reading_state = MEI_IDLE; |
512 | cl->read_cb = NULL; | 402 | cl->read_cb = NULL; |
513 | cl->read_pending = 0; | 403 | cl->read_pending = 0; |
@@ -516,7 +406,6 @@ out: | |||
516 | mutex_unlock(&dev->device_lock); | 406 | mutex_unlock(&dev->device_lock); |
517 | return rets; | 407 | return rets; |
518 | } | 408 | } |
519 | |||
520 | /** | 409 | /** |
521 | * mei_write - the write function. | 410 | * mei_write - the write function. |
522 | * | 411 | * |
@@ -546,23 +435,39 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
546 | mutex_lock(&dev->device_lock); | 435 | mutex_lock(&dev->device_lock); |
547 | 436 | ||
548 | if (dev->dev_state != MEI_DEV_ENABLED) { | 437 | if (dev->dev_state != MEI_DEV_ENABLED) { |
549 | mutex_unlock(&dev->device_lock); | 438 | rets = -ENODEV; |
550 | return -ENODEV; | 439 | goto err; |
551 | } | 440 | } |
552 | 441 | ||
442 | i = mei_me_cl_by_id(dev, cl->me_client_id); | ||
443 | if (i < 0) { | ||
444 | rets = -ENODEV; | ||
445 | goto err; | ||
446 | } | ||
447 | if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { | ||
448 | rets = -EMSGSIZE; | ||
449 | goto err; | ||
450 | } | ||
451 | |||
452 | if (cl->state != MEI_FILE_CONNECTED) { | ||
453 | rets = -ENODEV; | ||
454 | dev_err(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d", | ||
455 | cl->host_client_id, cl->me_client_id); | ||
456 | goto err; | ||
457 | } | ||
553 | if (cl == &dev->iamthif_cl) { | 458 | if (cl == &dev->iamthif_cl) { |
554 | write_cb = find_amthi_read_list_entry(dev, file); | 459 | write_cb = mei_amthif_find_read_list_entry(dev, file); |
555 | 460 | ||
556 | if (write_cb) { | 461 | if (write_cb) { |
557 | timeout = write_cb->read_time + | 462 | timeout = write_cb->read_time + |
558 | msecs_to_jiffies(IAMTHIF_READ_TIMER); | 463 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); |
559 | 464 | ||
560 | if (time_after(jiffies, timeout) || | 465 | if (time_after(jiffies, timeout) || |
561 | cl->reading_state == MEI_READ_COMPLETE) { | 466 | cl->reading_state == MEI_READ_COMPLETE) { |
562 | *offset = 0; | 467 | *offset = 0; |
563 | list_del(&write_cb->cb_list); | 468 | list_del(&write_cb->list); |
564 | mei_free_cb_private(write_cb); | 469 | mei_io_cb_free(write_cb); |
565 | write_cb = NULL; | 470 | write_cb = NULL; |
566 | } | 471 | } |
567 | } | 472 | } |
568 | } | 473 | } |
@@ -572,8 +477,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
572 | *offset = 0; | 477 | *offset = 0; |
573 | write_cb = find_read_list_entry(dev, cl); | 478 | write_cb = find_read_list_entry(dev, cl); |
574 | if (write_cb) { | 479 | if (write_cb) { |
575 | list_del(&write_cb->cb_list); | 480 | list_del(&write_cb->list); |
576 | mei_free_cb_private(write_cb); | 481 | mei_io_cb_free(write_cb); |
577 | write_cb = NULL; | 482 | write_cb = NULL; |
578 | cl->reading_state = MEI_IDLE; | 483 | cl->reading_state = MEI_IDLE; |
579 | cl->read_cb = NULL; | 484 | cl->read_cb = NULL; |
@@ -583,24 +488,21 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
583 | *offset = 0; | 488 | *offset = 0; |
584 | 489 | ||
585 | 490 | ||
586 | write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | 491 | write_cb = mei_io_cb_init(cl, file); |
587 | if (!write_cb) { | 492 | if (!write_cb) { |
588 | mutex_unlock(&dev->device_lock); | 493 | dev_err(&dev->pdev->dev, "write cb allocation failed\n"); |
589 | return -ENOMEM; | 494 | rets = -ENOMEM; |
495 | goto err; | ||
590 | } | 496 | } |
497 | rets = mei_io_cb_alloc_req_buf(write_cb, length); | ||
498 | if (rets) | ||
499 | goto err; | ||
591 | 500 | ||
592 | write_cb->file_object = file; | 501 | dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length); |
593 | write_cb->file_private = cl; | ||
594 | write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL); | ||
595 | rets = -ENOMEM; | ||
596 | if (!write_cb->request_buffer.data) | ||
597 | goto unlock_dev; | ||
598 | |||
599 | dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length); | ||
600 | 502 | ||
601 | rets = -EFAULT; | 503 | rets = copy_from_user(write_cb->request_buffer.data, ubuf, length); |
602 | if (copy_from_user(write_cb->request_buffer.data, ubuf, length)) | 504 | if (rets) |
603 | goto unlock_dev; | 505 | goto err; |
604 | 506 | ||
605 | cl->sm_state = 0; | 507 | cl->sm_state = 0; |
606 | if (length == 4 && | 508 | if (length == 4 && |
@@ -612,139 +514,71 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
612 | write_cb->request_buffer.data, 4) == 0))) | 514 | write_cb->request_buffer.data, 4) == 0))) |
613 | cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT; | 515 | cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT; |
614 | 516 | ||
615 | INIT_LIST_HEAD(&write_cb->cb_list); | ||
616 | if (cl == &dev->iamthif_cl) { | 517 | if (cl == &dev->iamthif_cl) { |
617 | write_cb->response_buffer.data = | 518 | rets = mei_amthif_write(dev, write_cb); |
618 | kmalloc(dev->iamthif_mtu, GFP_KERNEL); | ||
619 | if (!write_cb->response_buffer.data) { | ||
620 | rets = -ENOMEM; | ||
621 | goto unlock_dev; | ||
622 | } | ||
623 | if (dev->dev_state != MEI_DEV_ENABLED) { | ||
624 | rets = -ENODEV; | ||
625 | goto unlock_dev; | ||
626 | } | ||
627 | i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); | ||
628 | if (i < 0) { | ||
629 | rets = -ENODEV; | ||
630 | goto unlock_dev; | ||
631 | } | ||
632 | if (length > dev->me_clients[i].props.max_msg_length || | ||
633 | length <= 0) { | ||
634 | rets = -EMSGSIZE; | ||
635 | goto unlock_dev; | ||
636 | } | ||
637 | 519 | ||
638 | write_cb->response_buffer.size = dev->iamthif_mtu; | 520 | if (rets) { |
639 | write_cb->major_file_operations = MEI_IOCTL; | 521 | dev_err(&dev->pdev->dev, |
640 | write_cb->information = 0; | 522 | "amthi write failed with status = %d\n", rets); |
641 | write_cb->request_buffer.size = length; | 523 | goto err; |
642 | if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) { | ||
643 | rets = -ENODEV; | ||
644 | goto unlock_dev; | ||
645 | } | ||
646 | |||
647 | if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) || | ||
648 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { | ||
649 | dev_dbg(&dev->pdev->dev, "amthi_state = %d\n", | ||
650 | (int) dev->iamthif_state); | ||
651 | dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n"); | ||
652 | list_add_tail(&write_cb->cb_list, | ||
653 | &dev->amthi_cmd_list.mei_cb.cb_list); | ||
654 | rets = length; | ||
655 | } else { | ||
656 | dev_dbg(&dev->pdev->dev, "call amthi write\n"); | ||
657 | rets = amthi_write(dev, write_cb); | ||
658 | |||
659 | if (rets) { | ||
660 | dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n", | ||
661 | rets); | ||
662 | goto unlock_dev; | ||
663 | } | ||
664 | rets = length; | ||
665 | } | 524 | } |
666 | mutex_unlock(&dev->device_lock); | 525 | mutex_unlock(&dev->device_lock); |
667 | return rets; | 526 | return length; |
668 | } | 527 | } |
669 | 528 | ||
670 | write_cb->major_file_operations = MEI_WRITE; | 529 | write_cb->fop_type = MEI_FOP_WRITE; |
671 | /* make sure information is zero before we start */ | ||
672 | |||
673 | write_cb->information = 0; | ||
674 | write_cb->request_buffer.size = length; | ||
675 | 530 | ||
676 | dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n", | 531 | dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n", |
677 | cl->host_client_id, cl->me_client_id); | 532 | cl->host_client_id, cl->me_client_id); |
678 | if (cl->state != MEI_FILE_CONNECTED) { | ||
679 | rets = -ENODEV; | ||
680 | dev_dbg(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d", | ||
681 | cl->host_client_id, | ||
682 | cl->me_client_id); | ||
683 | goto unlock_dev; | ||
684 | } | ||
685 | i = mei_me_cl_by_id(dev, cl->me_client_id); | ||
686 | if (i < 0) { | ||
687 | rets = -ENODEV; | ||
688 | goto unlock_dev; | ||
689 | } | ||
690 | if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { | ||
691 | rets = -EINVAL; | ||
692 | goto unlock_dev; | ||
693 | } | ||
694 | write_cb->file_private = cl; | ||
695 | |||
696 | rets = mei_flow_ctrl_creds(dev, cl); | 533 | rets = mei_flow_ctrl_creds(dev, cl); |
697 | if (rets < 0) | 534 | if (rets < 0) |
698 | goto unlock_dev; | 535 | goto err; |
699 | 536 | ||
700 | if (rets && dev->mei_host_buffer_is_empty) { | 537 | if (rets == 0 || dev->mei_host_buffer_is_empty == false) { |
701 | rets = 0; | 538 | write_cb->buf_idx = 0; |
702 | dev->mei_host_buffer_is_empty = false; | 539 | mei_hdr.msg_complete = 0; |
703 | if (length > mei_hbuf_max_data(dev)) { | ||
704 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
705 | mei_hdr.msg_complete = 0; | ||
706 | } else { | ||
707 | mei_hdr.length = length; | ||
708 | mei_hdr.msg_complete = 1; | ||
709 | } | ||
710 | mei_hdr.host_addr = cl->host_client_id; | ||
711 | mei_hdr.me_addr = cl->me_client_id; | ||
712 | mei_hdr.reserved = 0; | ||
713 | dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n", | ||
714 | *((u32 *) &mei_hdr)); | ||
715 | if (mei_write_message(dev, &mei_hdr, | ||
716 | (unsigned char *) (write_cb->request_buffer.data), | ||
717 | mei_hdr.length)) { | ||
718 | rets = -ENODEV; | ||
719 | goto unlock_dev; | ||
720 | } | ||
721 | cl->writing_state = MEI_WRITING; | 540 | cl->writing_state = MEI_WRITING; |
722 | write_cb->information = mei_hdr.length; | 541 | goto out; |
723 | if (mei_hdr.msg_complete) { | 542 | } |
724 | if (mei_flow_ctrl_reduce(dev, cl)) { | ||
725 | rets = -ENODEV; | ||
726 | goto unlock_dev; | ||
727 | } | ||
728 | list_add_tail(&write_cb->cb_list, | ||
729 | &dev->write_waiting_list.mei_cb.cb_list); | ||
730 | } else { | ||
731 | list_add_tail(&write_cb->cb_list, | ||
732 | &dev->write_list.mei_cb.cb_list); | ||
733 | } | ||
734 | 543 | ||
544 | dev->mei_host_buffer_is_empty = false; | ||
545 | if (length > mei_hbuf_max_data(dev)) { | ||
546 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
547 | mei_hdr.msg_complete = 0; | ||
735 | } else { | 548 | } else { |
549 | mei_hdr.length = length; | ||
550 | mei_hdr.msg_complete = 1; | ||
551 | } | ||
552 | mei_hdr.host_addr = cl->host_client_id; | ||
553 | mei_hdr.me_addr = cl->me_client_id; | ||
554 | mei_hdr.reserved = 0; | ||
555 | dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n", | ||
556 | *((u32 *) &mei_hdr)); | ||
557 | if (mei_write_message(dev, &mei_hdr, | ||
558 | write_cb->request_buffer.data, mei_hdr.length)) { | ||
559 | rets = -ENODEV; | ||
560 | goto err; | ||
561 | } | ||
562 | cl->writing_state = MEI_WRITING; | ||
563 | write_cb->buf_idx = mei_hdr.length; | ||
736 | 564 | ||
737 | write_cb->information = 0; | 565 | out: |
738 | cl->writing_state = MEI_WRITING; | 566 | if (mei_hdr.msg_complete) { |
739 | list_add_tail(&write_cb->cb_list, | 567 | if (mei_flow_ctrl_reduce(dev, cl)) { |
740 | &dev->write_list.mei_cb.cb_list); | 568 | rets = -ENODEV; |
569 | goto err; | ||
570 | } | ||
571 | list_add_tail(&write_cb->list, &dev->write_waiting_list.list); | ||
572 | } else { | ||
573 | list_add_tail(&write_cb->list, &dev->write_list.list); | ||
741 | } | 574 | } |
575 | |||
742 | mutex_unlock(&dev->device_lock); | 576 | mutex_unlock(&dev->device_lock); |
743 | return length; | 577 | return length; |
744 | 578 | ||
745 | unlock_dev: | 579 | err: |
746 | mutex_unlock(&dev->device_lock); | 580 | mutex_unlock(&dev->device_lock); |
747 | mei_free_cb_private(write_cb); | 581 | mei_io_cb_free(write_cb); |
748 | return rets; | 582 | return rets; |
749 | } | 583 | } |
750 | 584 | ||
@@ -860,15 +694,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) | |||
860 | 694 | ||
861 | 695 | ||
862 | if (cl == &dev->iamthif_cl) { | 696 | if (cl == &dev->iamthif_cl) { |
863 | mutex_unlock(&dev->device_lock); | 697 | mask = mei_amthif_poll(dev, file, wait); |
864 | poll_wait(file, &dev->iamthif_cl.wait, wait); | ||
865 | mutex_lock(&dev->device_lock); | ||
866 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && | ||
867 | dev->iamthif_file_object == file) { | ||
868 | mask |= (POLLIN | POLLRDNORM); | ||
869 | dev_dbg(&dev->pdev->dev, "run next amthi cb\n"); | ||
870 | mei_run_next_iamthif_cmd(dev); | ||
871 | } | ||
872 | goto out; | 698 | goto out; |
873 | } | 699 | } |
874 | 700 | ||
@@ -917,7 +743,7 @@ static struct miscdevice mei_misc_device = { | |||
917 | * | 743 | * |
918 | * returns true if ME Interface is valid, false otherwise | 744 | * returns true if ME Interface is valid, false otherwise |
919 | */ | 745 | */ |
920 | static bool __devinit mei_quirk_probe(struct pci_dev *pdev, | 746 | static bool mei_quirk_probe(struct pci_dev *pdev, |
921 | const struct pci_device_id *ent) | 747 | const struct pci_device_id *ent) |
922 | { | 748 | { |
923 | u32 reg; | 749 | u32 reg; |
@@ -939,7 +765,7 @@ static bool __devinit mei_quirk_probe(struct pci_dev *pdev, | |||
939 | * | 765 | * |
940 | * returns 0 on success, <0 on failure. | 766 | * returns 0 on success, <0 on failure. |
941 | */ | 767 | */ |
942 | static int __devinit mei_probe(struct pci_dev *pdev, | 768 | static int mei_probe(struct pci_dev *pdev, |
943 | const struct pci_device_id *ent) | 769 | const struct pci_device_id *ent) |
944 | { | 770 | { |
945 | struct mei_device *dev; | 771 | struct mei_device *dev; |
@@ -1003,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev, | |||
1003 | goto disable_msi; | 829 | goto disable_msi; |
1004 | } | 830 | } |
1005 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); | 831 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); |
832 | INIT_WORK(&dev->init_work, mei_host_client_init); | ||
833 | |||
1006 | if (mei_hw_init(dev)) { | 834 | if (mei_hw_init(dev)) { |
1007 | dev_err(&pdev->dev, "init hw failure.\n"); | 835 | dev_err(&pdev->dev, "init hw failure.\n"); |
1008 | err = -ENODEV; | 836 | err = -ENODEV; |
@@ -1054,7 +882,7 @@ end: | |||
1054 | * mei_remove is called by the PCI subsystem to alert the driver | 882 | * mei_remove is called by the PCI subsystem to alert the driver |
1055 | * that it should release a PCI device. | 883 | * that it should release a PCI device. |
1056 | */ | 884 | */ |
1057 | static void __devexit mei_remove(struct pci_dev *pdev) | 885 | static void mei_remove(struct pci_dev *pdev) |
1058 | { | 886 | { |
1059 | struct mei_device *dev; | 887 | struct mei_device *dev; |
1060 | 888 | ||
@@ -1087,8 +915,8 @@ static void __devexit mei_remove(struct pci_dev *pdev) | |||
1087 | 915 | ||
1088 | /* remove entry if already in list */ | 916 | /* remove entry if already in list */ |
1089 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); | 917 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); |
1090 | mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id); | 918 | mei_me_cl_unlink(dev, &dev->wd_cl); |
1091 | mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id); | 919 | mei_me_cl_unlink(dev, &dev->iamthif_cl); |
1092 | 920 | ||
1093 | dev->iamthif_current_cb = NULL; | 921 | dev->iamthif_current_cb = NULL; |
1094 | dev->me_clients_num = 0; | 922 | dev->me_clients_num = 0; |
@@ -1195,8 +1023,8 @@ static struct pci_driver mei_driver = { | |||
1195 | .name = KBUILD_MODNAME, | 1023 | .name = KBUILD_MODNAME, |
1196 | .id_table = mei_pci_tbl, | 1024 | .id_table = mei_pci_tbl, |
1197 | .probe = mei_probe, | 1025 | .probe = mei_probe, |
1198 | .remove = __devexit_p(mei_remove), | 1026 | .remove = mei_remove, |
1199 | .shutdown = __devexit_p(mei_remove), | 1027 | .shutdown = mei_remove, |
1200 | .driver.pm = MEI_PM_OPS, | 1028 | .driver.pm = MEI_PM_OPS, |
1201 | }; | 1029 | }; |
1202 | 1030 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index adb35fb9281c..25da04549d04 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
22 | #include <linux/poll.h> | ||
22 | #include <linux/mei.h> | 23 | #include <linux/mei.h> |
23 | #include "hw.h" | 24 | #include "hw.h" |
24 | 25 | ||
@@ -125,13 +126,20 @@ enum mei_wd_states { | |||
125 | MEI_WD_STOPPING, | 126 | MEI_WD_STOPPING, |
126 | }; | 127 | }; |
127 | 128 | ||
128 | /* MEI CB */ | 129 | /** |
129 | enum mei_cb_major_types { | 130 | * enum mei_cb_file_ops - file operation associated with the callback |
130 | MEI_READ = 0, | 131 | * @MEI_FOP_READ - read |
131 | MEI_WRITE, | 132 | * @MEI_FOP_WRITE - write |
132 | MEI_IOCTL, | 133 | * @MEI_FOP_IOCTL - ioctl |
133 | MEI_OPEN, | 134 | * @MEI_FOP_OPEN - open |
134 | MEI_CLOSE | 135 | * @MEI_FOP_CLOSE - close |
136 | */ | ||
137 | enum mei_cb_file_ops { | ||
138 | MEI_FOP_READ = 0, | ||
139 | MEI_FOP_WRITE, | ||
140 | MEI_FOP_IOCTL, | ||
141 | MEI_FOP_OPEN, | ||
142 | MEI_FOP_CLOSE | ||
135 | }; | 143 | }; |
136 | 144 | ||
137 | /* | 145 | /* |
@@ -143,13 +151,21 @@ struct mei_message_data { | |||
143 | }; | 151 | }; |
144 | 152 | ||
145 | 153 | ||
154 | struct mei_cl; | ||
155 | |||
156 | /** | ||
157 | * struct mei_cl_cb - file operation callback structure | ||
158 | * | ||
159 | * @cl - file client who is running this operation | ||
160 | * @fop_type - file operation type | ||
161 | */ | ||
146 | struct mei_cl_cb { | 162 | struct mei_cl_cb { |
147 | struct list_head cb_list; | 163 | struct list_head list; |
148 | enum mei_cb_major_types major_file_operations; | 164 | struct mei_cl *cl; |
149 | void *file_private; | 165 | enum mei_cb_file_ops fop_type; |
150 | struct mei_message_data request_buffer; | 166 | struct mei_message_data request_buffer; |
151 | struct mei_message_data response_buffer; | 167 | struct mei_message_data response_buffer; |
152 | unsigned long information; | 168 | unsigned long buf_idx; |
153 | unsigned long read_time; | 169 | unsigned long read_time; |
154 | struct file *file_object; | 170 | struct file *file_object; |
155 | }; | 171 | }; |
@@ -175,29 +191,23 @@ struct mei_cl { | |||
175 | struct mei_cl_cb *read_cb; | 191 | struct mei_cl_cb *read_cb; |
176 | }; | 192 | }; |
177 | 193 | ||
178 | struct mei_io_list { | ||
179 | struct mei_cl_cb mei_cb; | ||
180 | }; | ||
181 | |||
182 | /** | 194 | /** |
183 | * struct mei_deive - MEI private device struct | 195 | * struct mei_device - MEI private device struct |
184 | * @hbuf_depth - depth of host(write) buffer | 196 | * @hbuf_depth - depth of host(write) buffer |
197 | * @wr_ext_msg - buffer for hbm control responses (set in read cycle) | ||
185 | */ | 198 | */ |
186 | struct mei_device { | 199 | struct mei_device { |
187 | struct pci_dev *pdev; /* pointer to pci device struct */ | 200 | struct pci_dev *pdev; /* pointer to pci device struct */ |
188 | /* | 201 | /* |
189 | * lists of queues | 202 | * lists of queues |
190 | */ | 203 | */ |
191 | /* array of pointers to aio lists */ | 204 | /* array of pointers to aio lists */ |
192 | struct mei_io_list read_list; /* driver read queue */ | 205 | struct mei_cl_cb read_list; /* driver read queue */ |
193 | struct mei_io_list write_list; /* driver write queue */ | 206 | struct mei_cl_cb write_list; /* driver write queue */ |
194 | struct mei_io_list write_waiting_list; /* write waiting queue */ | 207 | struct mei_cl_cb write_waiting_list; /* write waiting queue */ |
195 | struct mei_io_list ctrl_wr_list; /* managed write IOCTL list */ | 208 | struct mei_cl_cb ctrl_wr_list; /* managed write IOCTL list */ |
196 | struct mei_io_list ctrl_rd_list; /* managed read IOCTL list */ | 209 | struct mei_cl_cb ctrl_rd_list; /* managed read IOCTL list */ |
197 | struct mei_io_list amthi_cmd_list; /* amthi list for cmd waiting */ | 210 | |
198 | |||
199 | /* driver managed amthi list for reading completed amthi cmd data */ | ||
200 | struct mei_io_list amthi_read_complete_list; | ||
201 | /* | 211 | /* |
202 | * list of files | 212 | * list of files |
203 | */ | 213 | */ |
@@ -235,11 +245,13 @@ struct mei_device { | |||
235 | u16 init_clients_timer; | 245 | u16 init_clients_timer; |
236 | bool need_reset; | 246 | bool need_reset; |
237 | 247 | ||
238 | u32 extra_write_index; | ||
239 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ | 248 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ |
240 | u32 wr_msg_buf[128]; /* used for control messages */ | ||
241 | u32 ext_msg_buf[8]; /* for control responses */ | ||
242 | u32 rd_msg_hdr; | 249 | u32 rd_msg_hdr; |
250 | u32 wr_msg_buf[128]; /* used for control messages */ | ||
251 | struct { | ||
252 | struct mei_msg_hdr hdr; | ||
253 | unsigned char data[4]; /* All HBM messages are 4 bytes */ | ||
254 | } wr_ext_msg; /* for control responses */ | ||
243 | 255 | ||
244 | struct hbm_version version; | 256 | struct hbm_version version; |
245 | 257 | ||
@@ -253,12 +265,15 @@ struct mei_device { | |||
253 | 265 | ||
254 | struct mei_cl wd_cl; | 266 | struct mei_cl wd_cl; |
255 | enum mei_wd_states wd_state; | 267 | enum mei_wd_states wd_state; |
256 | bool wd_interface_reg; | ||
257 | bool wd_pending; | 268 | bool wd_pending; |
258 | u16 wd_timeout; | 269 | u16 wd_timeout; |
259 | unsigned char wd_data[MEI_WD_START_MSG_SIZE]; | 270 | unsigned char wd_data[MEI_WD_START_MSG_SIZE]; |
260 | 271 | ||
261 | 272 | ||
273 | /* amthif list for cmd waiting */ | ||
274 | struct mei_cl_cb amthif_cmd_list; | ||
275 | /* driver managed amthif list for reading completed amthif cmd data */ | ||
276 | struct mei_cl_cb amthif_rd_complete_list; | ||
262 | struct file *iamthif_file_object; | 277 | struct file *iamthif_file_object; |
263 | struct mei_cl iamthif_cl; | 278 | struct mei_cl iamthif_cl; |
264 | struct mei_cl_cb *iamthif_current_cb; | 279 | struct mei_cl_cb *iamthif_current_cb; |
@@ -272,8 +287,15 @@ struct mei_device { | |||
272 | bool iamthif_flow_control_pending; | 287 | bool iamthif_flow_control_pending; |
273 | bool iamthif_ioctl; | 288 | bool iamthif_ioctl; |
274 | bool iamthif_canceled; | 289 | bool iamthif_canceled; |
290 | |||
291 | struct work_struct init_work; | ||
275 | }; | 292 | }; |
276 | 293 | ||
294 | static inline unsigned long mei_secs_to_jiffies(unsigned long sec) | ||
295 | { | ||
296 | return msecs_to_jiffies(sec * MSEC_PER_SEC); | ||
297 | } | ||
298 | |||
277 | 299 | ||
278 | /* | 300 | /* |
279 | * mei init function prototypes | 301 | * mei init function prototypes |
@@ -284,21 +306,34 @@ int mei_hw_init(struct mei_device *dev); | |||
284 | int mei_task_initialize_clients(void *data); | 306 | int mei_task_initialize_clients(void *data); |
285 | int mei_initialize_clients(struct mei_device *dev); | 307 | int mei_initialize_clients(struct mei_device *dev); |
286 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl); | 308 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl); |
287 | void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id); | ||
288 | void mei_host_init_iamthif(struct mei_device *dev); | ||
289 | void mei_allocate_me_clients_storage(struct mei_device *dev); | 309 | void mei_allocate_me_clients_storage(struct mei_device *dev); |
290 | 310 | ||
291 | 311 | ||
292 | int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | 312 | int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl, |
293 | const uuid_le *cguid, u8 host_client_id); | 313 | const uuid_le *cguid, u8 host_client_id); |
314 | void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl); | ||
294 | int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid); | 315 | int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid); |
295 | int mei_me_cl_by_id(struct mei_device *dev, u8 client_id); | 316 | int mei_me_cl_by_id(struct mei_device *dev, u8 client_id); |
296 | 317 | ||
297 | /* | 318 | /* |
298 | * MEI IO List Functions | 319 | * MEI IO Functions |
320 | */ | ||
321 | struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp); | ||
322 | void mei_io_cb_free(struct mei_cl_cb *priv_cb); | ||
323 | int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length); | ||
324 | int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length); | ||
325 | |||
326 | |||
327 | /** | ||
328 | * mei_io_list_init - Sets up a queue list. | ||
329 | * | ||
330 | * @list: An instance cl callback structure | ||
299 | */ | 331 | */ |
300 | void mei_io_list_init(struct mei_io_list *list); | 332 | static inline void mei_io_list_init(struct mei_cl_cb *list) |
301 | void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl); | 333 | { |
334 | INIT_LIST_HEAD(&list->list); | ||
335 | } | ||
336 | void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl); | ||
302 | 337 | ||
303 | /* | 338 | /* |
304 | * MEI ME Client Functions | 339 | * MEI ME Client Functions |
@@ -330,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1, | |||
330 | */ | 365 | */ |
331 | void mei_host_start_message(struct mei_device *dev); | 366 | void mei_host_start_message(struct mei_device *dev); |
332 | void mei_host_enum_clients_message(struct mei_device *dev); | 367 | void mei_host_enum_clients_message(struct mei_device *dev); |
333 | int mei_host_client_properties(struct mei_device *dev); | 368 | int mei_host_client_enumerate(struct mei_device *dev); |
369 | void mei_host_client_init(struct work_struct *work); | ||
334 | 370 | ||
335 | /* | 371 | /* |
336 | * MEI interrupt functions prototype | 372 | * MEI interrupt functions prototype |
@@ -347,18 +383,40 @@ int mei_ioctl_connect_client(struct file *file, | |||
347 | 383 | ||
348 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl); | 384 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl); |
349 | 385 | ||
350 | int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); | ||
351 | 386 | ||
352 | int amthi_read(struct mei_device *dev, struct file *file, | 387 | /* |
353 | char __user *ubuf, size_t length, loff_t *offset); | 388 | * AMTHIF - AMT Host Interface Functions |
389 | */ | ||
390 | void mei_amthif_reset_params(struct mei_device *dev); | ||
391 | |||
392 | void mei_amthif_host_init(struct mei_device *dev); | ||
393 | |||
394 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); | ||
354 | 395 | ||
355 | struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev, | 396 | int mei_amthif_read(struct mei_device *dev, struct file *file, |
397 | char __user *ubuf, size_t length, loff_t *offset); | ||
398 | |||
399 | unsigned int mei_amthif_poll(struct mei_device *dev, | ||
400 | struct file *file, poll_table *wait); | ||
401 | |||
402 | int mei_amthif_release(struct mei_device *dev, struct file *file); | ||
403 | |||
404 | struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, | ||
356 | struct file *file); | 405 | struct file *file); |
357 | 406 | ||
358 | void mei_run_next_iamthif_cmd(struct mei_device *dev); | 407 | void mei_amthif_run_next_cmd(struct mei_device *dev); |
408 | |||
359 | 409 | ||
360 | void mei_free_cb_private(struct mei_cl_cb *priv_cb); | 410 | int mei_amthif_read_message(struct mei_cl_cb *complete_list, |
411 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr); | ||
361 | 412 | ||
413 | int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots, | ||
414 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); | ||
415 | |||
416 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); | ||
417 | int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list, | ||
418 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr); | ||
419 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | ||
362 | 420 | ||
363 | /* | 421 | /* |
364 | * Register Access Function | 422 | * Register Access Function |
@@ -437,4 +495,15 @@ void mei_csr_clear_his(struct mei_device *dev); | |||
437 | void mei_enable_interrupts(struct mei_device *dev); | 495 | void mei_enable_interrupts(struct mei_device *dev); |
438 | void mei_disable_interrupts(struct mei_device *dev); | 496 | void mei_disable_interrupts(struct mei_device *dev); |
439 | 497 | ||
498 | static inline struct mei_msg_hdr *mei_hbm_hdr(u32 *buf, size_t length) | ||
499 | { | ||
500 | struct mei_msg_hdr *hdr = (struct mei_msg_hdr *)buf; | ||
501 | hdr->host_addr = 0; | ||
502 | hdr->me_addr = 0; | ||
503 | hdr->length = length; | ||
504 | hdr->msg_complete = 1; | ||
505 | hdr->reserved = 0; | ||
506 | return hdr; | ||
507 | } | ||
508 | |||
440 | #endif | 509 | #endif |
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index d96c537f046f..636409f9667f 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c | |||
@@ -62,6 +62,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) | |||
62 | */ | 62 | */ |
63 | int mei_wd_host_init(struct mei_device *dev) | 63 | int mei_wd_host_init(struct mei_device *dev) |
64 | { | 64 | { |
65 | int id; | ||
65 | mei_cl_init(&dev->wd_cl, dev); | 66 | mei_cl_init(&dev->wd_cl, dev); |
66 | 67 | ||
67 | /* look for WD client and connect to it */ | 68 | /* look for WD client and connect to it */ |
@@ -69,12 +70,11 @@ int mei_wd_host_init(struct mei_device *dev) | |||
69 | dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; | 70 | dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; |
70 | dev->wd_state = MEI_WD_IDLE; | 71 | dev->wd_state = MEI_WD_IDLE; |
71 | 72 | ||
72 | /* find ME WD client */ | 73 | /* Connect WD ME client to the host client */ |
73 | mei_me_cl_update_filext(dev, &dev->wd_cl, | 74 | id = mei_me_cl_link(dev, &dev->wd_cl, |
74 | &mei_wd_guid, MEI_WD_HOST_CLIENT_ID); | 75 | &mei_wd_guid, MEI_WD_HOST_CLIENT_ID); |
75 | 76 | ||
76 | dev_dbg(&dev->pdev->dev, "wd: check client\n"); | 77 | if (id < 0) { |
77 | if (MEI_FILE_CONNECTING != dev->wd_cl.state) { | ||
78 | dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); | 78 | dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); |
79 | return -ENOENT; | 79 | return -ENOENT; |
80 | } | 80 | } |
@@ -85,7 +85,7 @@ int mei_wd_host_init(struct mei_device *dev) | |||
85 | dev->wd_cl.host_client_id = 0; | 85 | dev->wd_cl.host_client_id = 0; |
86 | return -EIO; | 86 | return -EIO; |
87 | } | 87 | } |
88 | dev->wd_cl.timer_count = CONNECT_TIMEOUT; | 88 | dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT; |
89 | 89 | ||
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
@@ -360,23 +360,20 @@ void mei_watchdog_register(struct mei_device *dev) | |||
360 | if (watchdog_register_device(&amt_wd_dev)) { | 360 | if (watchdog_register_device(&amt_wd_dev)) { |
361 | dev_err(&dev->pdev->dev, | 361 | dev_err(&dev->pdev->dev, |
362 | "wd: unable to register watchdog device.\n"); | 362 | "wd: unable to register watchdog device.\n"); |
363 | dev->wd_interface_reg = false; | ||
364 | return; | 363 | return; |
365 | } | 364 | } |
366 | 365 | ||
367 | dev_dbg(&dev->pdev->dev, | 366 | dev_dbg(&dev->pdev->dev, |
368 | "wd: successfully register watchdog interface.\n"); | 367 | "wd: successfully register watchdog interface.\n"); |
369 | dev->wd_interface_reg = true; | ||
370 | watchdog_set_drvdata(&amt_wd_dev, dev); | 368 | watchdog_set_drvdata(&amt_wd_dev, dev); |
371 | } | 369 | } |
372 | 370 | ||
373 | void mei_watchdog_unregister(struct mei_device *dev) | 371 | void mei_watchdog_unregister(struct mei_device *dev) |
374 | { | 372 | { |
375 | if (!dev->wd_interface_reg) | 373 | if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status)) |
376 | return; | 374 | return; |
377 | 375 | ||
378 | watchdog_set_drvdata(&amt_wd_dev, NULL); | 376 | watchdog_set_drvdata(&amt_wd_dev, NULL); |
379 | watchdog_unregister_device(&amt_wd_dev); | 377 | watchdog_unregister_device(&amt_wd_dev); |
380 | dev->wd_interface_reg = false; | ||
381 | } | 378 | } |
382 | 379 | ||
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index c9f20dae1855..931e635aa491 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c | |||
@@ -666,7 +666,7 @@ static struct bin_attribute pch_bin_attr = { | |||
666 | .write = pch_phub_bin_write, | 666 | .write = pch_phub_bin_write, |
667 | }; | 667 | }; |
668 | 668 | ||
669 | static int __devinit pch_phub_probe(struct pci_dev *pdev, | 669 | static int pch_phub_probe(struct pci_dev *pdev, |
670 | const struct pci_device_id *id) | 670 | const struct pci_device_id *id) |
671 | { | 671 | { |
672 | int retval; | 672 | int retval; |
@@ -819,7 +819,7 @@ err_pci_enable_dev: | |||
819 | return ret; | 819 | return ret; |
820 | } | 820 | } |
821 | 821 | ||
822 | static void __devexit pch_phub_remove(struct pci_dev *pdev) | 822 | static void pch_phub_remove(struct pci_dev *pdev) |
823 | { | 823 | { |
824 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); | 824 | struct pch_phub_reg *chip = pci_get_drvdata(pdev); |
825 | 825 | ||
@@ -888,7 +888,7 @@ static struct pci_driver pch_phub_driver = { | |||
888 | .name = "pch_phub", | 888 | .name = "pch_phub", |
889 | .id_table = pch_phub_pcidev_id, | 889 | .id_table = pch_phub_pcidev_id, |
890 | .probe = pch_phub_probe, | 890 | .probe = pch_phub_probe, |
891 | .remove = __devexit_p(pch_phub_remove), | 891 | .remove = pch_phub_remove, |
892 | .suspend = pch_phub_suspend, | 892 | .suspend = pch_phub_suspend, |
893 | .resume = pch_phub_resume | 893 | .resume = pch_phub_resume |
894 | }; | 894 | }; |
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 21b28fc6d912..68b7c773d2cf 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -324,7 +324,7 @@ static irqreturn_t phantom_isr(int irq, void *data) | |||
324 | * Init and deinit driver | 324 | * Init and deinit driver |
325 | */ | 325 | */ |
326 | 326 | ||
327 | static unsigned int __devinit phantom_get_free(void) | 327 | static unsigned int phantom_get_free(void) |
328 | { | 328 | { |
329 | unsigned int i; | 329 | unsigned int i; |
330 | 330 | ||
@@ -335,7 +335,7 @@ static unsigned int __devinit phantom_get_free(void) | |||
335 | return i; | 335 | return i; |
336 | } | 336 | } |
337 | 337 | ||
338 | static int __devinit phantom_probe(struct pci_dev *pdev, | 338 | static int phantom_probe(struct pci_dev *pdev, |
339 | const struct pci_device_id *pci_id) | 339 | const struct pci_device_id *pci_id) |
340 | { | 340 | { |
341 | struct phantom_device *pht; | 341 | struct phantom_device *pht; |
@@ -435,7 +435,7 @@ err: | |||
435 | return retval; | 435 | return retval; |
436 | } | 436 | } |
437 | 437 | ||
438 | static void __devexit phantom_remove(struct pci_dev *pdev) | 438 | static void phantom_remove(struct pci_dev *pdev) |
439 | { | 439 | { |
440 | struct phantom_device *pht = pci_get_drvdata(pdev); | 440 | struct phantom_device *pht = pci_get_drvdata(pdev); |
441 | unsigned int minor = MINOR(pht->cdev.dev); | 441 | unsigned int minor = MINOR(pht->cdev.dev); |
@@ -487,7 +487,7 @@ static int phantom_resume(struct pci_dev *pdev) | |||
487 | #define phantom_resume NULL | 487 | #define phantom_resume NULL |
488 | #endif | 488 | #endif |
489 | 489 | ||
490 | static struct pci_device_id phantom_pci_tbl[] __devinitdata = { | 490 | static struct pci_device_id phantom_pci_tbl[] = { |
491 | { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, | 491 | { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, |
492 | .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050, | 492 | .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050, |
493 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, | 493 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, |
@@ -499,7 +499,7 @@ static struct pci_driver phantom_pci_driver = { | |||
499 | .name = "phantom", | 499 | .name = "phantom", |
500 | .id_table = phantom_pci_tbl, | 500 | .id_table = phantom_pci_tbl, |
501 | .probe = phantom_probe, | 501 | .probe = phantom_probe, |
502 | .remove = __devexit_p(phantom_remove), | 502 | .remove = phantom_remove, |
503 | .suspend = phantom_suspend, | 503 | .suspend = phantom_suspend, |
504 | .resume = phantom_resume | 504 | .resume = phantom_resume |
505 | }; | 505 | }; |
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index a1f0d174e687..f84ff0c06035 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c | |||
@@ -76,7 +76,7 @@ struct pti_dev { | |||
76 | */ | 76 | */ |
77 | static DEFINE_MUTEX(alloclock); | 77 | static DEFINE_MUTEX(alloclock); |
78 | 78 | ||
79 | static const struct pci_device_id pci_ids[] __devinitconst = { | 79 | static const struct pci_device_id pci_ids[] = { |
80 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)}, | 80 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)}, |
81 | {0} | 81 | {0} |
82 | }; | 82 | }; |
@@ -796,7 +796,7 @@ static const struct tty_port_operations tty_port_ops = { | |||
796 | * 0 for success | 796 | * 0 for success |
797 | * otherwise, error | 797 | * otherwise, error |
798 | */ | 798 | */ |
799 | static int __devinit pti_pci_probe(struct pci_dev *pdev, | 799 | static int pti_pci_probe(struct pci_dev *pdev, |
800 | const struct pci_device_id *ent) | 800 | const struct pci_device_id *ent) |
801 | { | 801 | { |
802 | unsigned int a; | 802 | unsigned int a; |
@@ -879,7 +879,7 @@ err: | |||
879 | * PCI bus. | 879 | * PCI bus. |
880 | * @pdev: variable containing pci info of PTI. | 880 | * @pdev: variable containing pci info of PTI. |
881 | */ | 881 | */ |
882 | static void __devexit pti_pci_remove(struct pci_dev *pdev) | 882 | static void pti_pci_remove(struct pci_dev *pdev) |
883 | { | 883 | { |
884 | struct pti_dev *drv_data = pci_get_drvdata(pdev); | 884 | struct pti_dev *drv_data = pci_get_drvdata(pdev); |
885 | unsigned int a; | 885 | unsigned int a; |
@@ -904,7 +904,7 @@ static struct pci_driver pti_pci_driver = { | |||
904 | .name = PCINAME, | 904 | .name = PCINAME, |
905 | .id_table = pci_ids, | 905 | .id_table = pci_ids, |
906 | .probe = pti_pci_probe, | 906 | .probe = pti_pci_probe, |
907 | .remove = __devexit_p(pti_pci_remove), | 907 | .remove = pti_pci_remove, |
908 | }; | 908 | }; |
909 | 909 | ||
910 | /** | 910 | /** |
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index 123ed98eec3e..7deb25dc86a7 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c | |||
@@ -711,7 +711,7 @@ static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config) | |||
711 | spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1); | 711 | spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1); |
712 | } | 712 | } |
713 | 713 | ||
714 | static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev) | 714 | static int spear_pcie_gadget_probe(struct platform_device *pdev) |
715 | { | 715 | { |
716 | struct resource *res0, *res1; | 716 | struct resource *res0, *res1; |
717 | unsigned int status = 0; | 717 | unsigned int status = 0; |
@@ -853,7 +853,7 @@ err_rel_res0: | |||
853 | return status; | 853 | return status; |
854 | } | 854 | } |
855 | 855 | ||
856 | static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev) | 856 | static int spear_pcie_gadget_remove(struct platform_device *pdev) |
857 | { | 857 | { |
858 | struct resource *res0, *res1; | 858 | struct resource *res0, *res1; |
859 | static struct pcie_gadget_target *target; | 859 | static struct pcie_gadget_target *target; |
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 46937b107261..b90a2241d79c 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c | |||
@@ -511,7 +511,6 @@ long st_register(struct st_proto_s *new_proto) | |||
511 | unsigned long flags = 0; | 511 | unsigned long flags = 0; |
512 | 512 | ||
513 | st_kim_ref(&st_gdata, 0); | 513 | st_kim_ref(&st_gdata, 0); |
514 | pr_info("%s(%d) ", __func__, new_proto->chnl_id); | ||
515 | if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL | 514 | if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL |
516 | || new_proto->reg_complete_cb == NULL) { | 515 | || new_proto->reg_complete_cb == NULL) { |
517 | pr_err("gdata/new_proto/recv or reg_complete_cb not ready"); | 516 | pr_err("gdata/new_proto/recv or reg_complete_cb not ready"); |
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 04a819944f6b..9ff942a346ed 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -705,9 +705,9 @@ static const struct file_operations list_debugfs_fops = { | |||
705 | static struct dentry *kim_debugfs_dir; | 705 | static struct dentry *kim_debugfs_dir; |
706 | static int kim_probe(struct platform_device *pdev) | 706 | static int kim_probe(struct platform_device *pdev) |
707 | { | 707 | { |
708 | long status; | ||
709 | struct kim_data_s *kim_gdata; | 708 | struct kim_data_s *kim_gdata; |
710 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 709 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
710 | int err; | ||
711 | 711 | ||
712 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { | 712 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { |
713 | /* multiple devices could exist */ | 713 | /* multiple devices could exist */ |
@@ -724,10 +724,11 @@ static int kim_probe(struct platform_device *pdev) | |||
724 | } | 724 | } |
725 | dev_set_drvdata(&pdev->dev, kim_gdata); | 725 | dev_set_drvdata(&pdev->dev, kim_gdata); |
726 | 726 | ||
727 | status = st_core_init(&kim_gdata->core_data); | 727 | err = st_core_init(&kim_gdata->core_data); |
728 | if (status != 0) { | 728 | if (err != 0) { |
729 | pr_err(" ST core init failed"); | 729 | pr_err(" ST core init failed"); |
730 | return -EIO; | 730 | err = -EIO; |
731 | goto err_core_init; | ||
731 | } | 732 | } |
732 | /* refer to itself */ | 733 | /* refer to itself */ |
733 | kim_gdata->core_data->kim_data = kim_gdata; | 734 | kim_gdata->core_data->kim_data = kim_gdata; |
@@ -738,10 +739,10 @@ static int kim_probe(struct platform_device *pdev) | |||
738 | init_completion(&kim_gdata->kim_rcvd); | 739 | init_completion(&kim_gdata->kim_rcvd); |
739 | init_completion(&kim_gdata->ldisc_installed); | 740 | init_completion(&kim_gdata->ldisc_installed); |
740 | 741 | ||
741 | status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp); | 742 | err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp); |
742 | if (status) { | 743 | if (err) { |
743 | pr_err("failed to create sysfs entries"); | 744 | pr_err("failed to create sysfs entries"); |
744 | return status; | 745 | goto err_sysfs_group; |
745 | } | 746 | } |
746 | 747 | ||
747 | /* copying platform data */ | 748 | /* copying platform data */ |
@@ -753,8 +754,8 @@ static int kim_probe(struct platform_device *pdev) | |||
753 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); | 754 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); |
754 | if (IS_ERR(kim_debugfs_dir)) { | 755 | if (IS_ERR(kim_debugfs_dir)) { |
755 | pr_err(" debugfs entries creation failed "); | 756 | pr_err(" debugfs entries creation failed "); |
756 | kim_debugfs_dir = NULL; | 757 | err = -EIO; |
757 | return -EIO; | 758 | goto err_debugfs_dir; |
758 | } | 759 | } |
759 | 760 | ||
760 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, | 761 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, |
@@ -763,6 +764,17 @@ static int kim_probe(struct platform_device *pdev) | |||
763 | kim_gdata, &list_debugfs_fops); | 764 | kim_gdata, &list_debugfs_fops); |
764 | pr_info(" debugfs entries created "); | 765 | pr_info(" debugfs entries created "); |
765 | return 0; | 766 | return 0; |
767 | |||
768 | err_debugfs_dir: | ||
769 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | ||
770 | |||
771 | err_sysfs_group: | ||
772 | st_core_exit(kim_gdata->core_data); | ||
773 | |||
774 | err_core_init: | ||
775 | kfree(kim_gdata); | ||
776 | |||
777 | return err; | ||
766 | } | 778 | } |
767 | 779 | ||
768 | static int kim_remove(struct platform_device *pdev) | 780 | static int kim_remove(struct platform_device *pdev) |
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c index 5acbba120de0..1d86407189eb 100644 --- a/drivers/misc/ti_dac7512.c +++ b/drivers/misc/ti_dac7512.c | |||
@@ -54,7 +54,7 @@ static const struct attribute_group dac7512_attr_group = { | |||
54 | .attrs = dac7512_attributes, | 54 | .attrs = dac7512_attributes, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static int __devinit dac7512_probe(struct spi_device *spi) | 57 | static int dac7512_probe(struct spi_device *spi) |
58 | { | 58 | { |
59 | int ret; | 59 | int ret; |
60 | 60 | ||
@@ -67,7 +67,7 @@ static int __devinit dac7512_probe(struct spi_device *spi) | |||
67 | return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group); | 67 | return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int __devexit dac7512_remove(struct spi_device *spi) | 70 | static int dac7512_remove(struct spi_device *spi) |
71 | { | 71 | { |
72 | sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group); | 72 | sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group); |
73 | return 0; | 73 | return 0; |
@@ -79,7 +79,7 @@ static struct spi_driver dac7512_driver = { | |||
79 | .owner = THIS_MODULE, | 79 | .owner = THIS_MODULE, |
80 | }, | 80 | }, |
81 | .probe = dac7512_probe, | 81 | .probe = dac7512_probe, |
82 | .remove = __devexit_p(dac7512_remove), | 82 | .remove = dac7512_remove, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | module_spi_driver(dac7512_driver); | 85 | module_spi_driver(dac7512_driver); |
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c index 0beb298a17dd..1e7bc0eb081e 100644 --- a/drivers/misc/tsl2550.c +++ b/drivers/misc/tsl2550.c | |||
@@ -347,7 +347,7 @@ static int tsl2550_init_client(struct i2c_client *client) | |||
347 | */ | 347 | */ |
348 | 348 | ||
349 | static struct i2c_driver tsl2550_driver; | 349 | static struct i2c_driver tsl2550_driver; |
350 | static int __devinit tsl2550_probe(struct i2c_client *client, | 350 | static int tsl2550_probe(struct i2c_client *client, |
351 | const struct i2c_device_id *id) | 351 | const struct i2c_device_id *id) |
352 | { | 352 | { |
353 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 353 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
@@ -405,7 +405,7 @@ exit: | |||
405 | return err; | 405 | return err; |
406 | } | 406 | } |
407 | 407 | ||
408 | static int __devexit tsl2550_remove(struct i2c_client *client) | 408 | static int tsl2550_remove(struct i2c_client *client) |
409 | { | 409 | { |
410 | sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group); | 410 | sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group); |
411 | 411 | ||
@@ -450,7 +450,7 @@ static struct i2c_driver tsl2550_driver = { | |||
450 | .suspend = tsl2550_suspend, | 450 | .suspend = tsl2550_suspend, |
451 | .resume = tsl2550_resume, | 451 | .resume = tsl2550_resume, |
452 | .probe = tsl2550_probe, | 452 | .probe = tsl2550_probe, |
453 | .remove = __devexit_p(tsl2550_remove), | 453 | .remove = tsl2550_remove, |
454 | .id_table = tsl2550_id, | 454 | .id_table = tsl2550_id, |
455 | }; | 455 | }; |
456 | 456 | ||