diff options
Diffstat (limited to 'drivers/misc')
42 files changed, 1816 insertions, 1684 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..3c09cbb70b1d 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
| @@ -18,6 +18,9 @@ | |||
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | 20 | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/pinctrl/consumer.h> | ||
| 23 | |||
| 21 | /* Serialize access to ssc_list and user count */ | 24 | /* Serialize access to ssc_list and user count */ |
| 22 | static DEFINE_SPINLOCK(user_lock); | 25 | static DEFINE_SPINLOCK(user_lock); |
| 23 | static LIST_HEAD(ssc_list); | 26 | static LIST_HEAD(ssc_list); |
| @@ -29,7 +32,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num) | |||
| 29 | 32 | ||
| 30 | spin_lock(&user_lock); | 33 | spin_lock(&user_lock); |
| 31 | list_for_each_entry(ssc, &ssc_list, list) { | 34 | list_for_each_entry(ssc, &ssc_list, list) { |
| 32 | if (ssc->pdev->id == ssc_num) { | 35 | if (ssc->pdev->dev.of_node) { |
| 36 | if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc") | ||
| 37 | == ssc_num) { | ||
| 38 | ssc_valid = 1; | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | } else if (ssc->pdev->id == ssc_num) { | ||
| 33 | ssc_valid = 1; | 42 | ssc_valid = 1; |
| 34 | break; | 43 | break; |
| 35 | } | 44 | } |
| @@ -68,39 +77,100 @@ void ssc_free(struct ssc_device *ssc) | |||
| 68 | } | 77 | } |
| 69 | EXPORT_SYMBOL(ssc_free); | 78 | EXPORT_SYMBOL(ssc_free); |
| 70 | 79 | ||
| 71 | static int __init ssc_probe(struct platform_device *pdev) | 80 | static struct atmel_ssc_platform_data at91rm9200_config = { |
| 81 | .use_dma = 0, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static struct atmel_ssc_platform_data at91sam9g45_config = { | ||
| 85 | .use_dma = 1, | ||
| 86 | }; | ||
| 87 | |||
| 88 | static const struct platform_device_id atmel_ssc_devtypes[] = { | ||
| 89 | { | ||
| 90 | .name = "at91rm9200_ssc", | ||
| 91 | .driver_data = (unsigned long) &at91rm9200_config, | ||
| 92 | }, { | ||
| 93 | .name = "at91sam9g45_ssc", | ||
| 94 | .driver_data = (unsigned long) &at91sam9g45_config, | ||
| 95 | }, { | ||
| 96 | /* sentinel */ | ||
| 97 | } | ||
| 98 | }; | ||
| 99 | |||
| 100 | #ifdef CONFIG_OF | ||
| 101 | static const struct of_device_id atmel_ssc_dt_ids[] = { | ||
| 102 | { | ||
| 103 | .compatible = "atmel,at91rm9200-ssc", | ||
| 104 | .data = &at91rm9200_config, | ||
| 105 | }, { | ||
| 106 | .compatible = "atmel,at91sam9g45-ssc", | ||
| 107 | .data = &at91sam9g45_config, | ||
| 108 | }, { | ||
| 109 | /* sentinel */ | ||
| 110 | } | ||
| 111 | }; | ||
| 112 | MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids); | ||
| 113 | #endif | ||
| 114 | |||
| 115 | static inline const struct atmel_ssc_platform_data * __init | ||
| 116 | atmel_ssc_get_driver_data(struct platform_device *pdev) | ||
| 117 | { | ||
| 118 | if (pdev->dev.of_node) { | ||
| 119 | const struct of_device_id *match; | ||
| 120 | match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node); | ||
| 121 | if (match == NULL) | ||
| 122 | return NULL; | ||
| 123 | return match->data; | ||
| 124 | } | ||
| 125 | |||
| 126 | return (struct atmel_ssc_platform_data *) | ||
| 127 | platform_get_device_id(pdev)->driver_data; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int ssc_probe(struct platform_device *pdev) | ||
| 72 | { | 131 | { |
| 73 | int retval = 0; | ||
| 74 | struct resource *regs; | 132 | struct resource *regs; |
| 75 | struct ssc_device *ssc; | 133 | struct ssc_device *ssc; |
| 134 | const struct atmel_ssc_platform_data *plat_dat; | ||
| 135 | struct pinctrl *pinctrl; | ||
| 136 | |||
| 137 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
| 138 | if (IS_ERR(pinctrl)) { | ||
| 139 | dev_err(&pdev->dev, "Failed to request pinctrl\n"); | ||
| 140 | return PTR_ERR(pinctrl); | ||
| 141 | } | ||
| 76 | 142 | ||
| 77 | ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); | 143 | ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); |
| 78 | if (!ssc) { | 144 | if (!ssc) { |
| 79 | dev_dbg(&pdev->dev, "out of memory\n"); | 145 | dev_dbg(&pdev->dev, "out of memory\n"); |
| 80 | retval = -ENOMEM; | 146 | return -ENOMEM; |
| 81 | goto out; | ||
| 82 | } | 147 | } |
| 83 | 148 | ||
| 149 | ssc->pdev = pdev; | ||
| 150 | |||
| 151 | plat_dat = atmel_ssc_get_driver_data(pdev); | ||
| 152 | if (!plat_dat) | ||
| 153 | return -ENODEV; | ||
| 154 | ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; | ||
| 155 | |||
| 84 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 156 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 85 | if (!regs) { | 157 | if (!regs) { |
| 86 | dev_dbg(&pdev->dev, "no mmio resource defined\n"); | 158 | dev_dbg(&pdev->dev, "no mmio resource defined\n"); |
| 87 | retval = -ENXIO; | 159 | return -ENXIO; |
| 88 | goto out_free; | ||
| 89 | } | ||
| 90 | |||
| 91 | ssc->clk = clk_get(&pdev->dev, "pclk"); | ||
| 92 | if (IS_ERR(ssc->clk)) { | ||
| 93 | dev_dbg(&pdev->dev, "no pclk clock defined\n"); | ||
| 94 | retval = -ENXIO; | ||
| 95 | goto out_free; | ||
| 96 | } | 160 | } |
| 97 | 161 | ||
| 98 | ssc->pdev = pdev; | 162 | ssc->regs = devm_request_and_ioremap(&pdev->dev, regs); |
| 99 | ssc->regs = ioremap(regs->start, resource_size(regs)); | ||
| 100 | if (!ssc->regs) { | 163 | if (!ssc->regs) { |
| 101 | dev_dbg(&pdev->dev, "ioremap failed\n"); | 164 | dev_dbg(&pdev->dev, "ioremap failed\n"); |
| 102 | retval = -EINVAL; | 165 | return -EINVAL; |
| 103 | goto out_clk; | 166 | } |
| 167 | |||
| 168 | ssc->phybase = regs->start; | ||
| 169 | |||
| 170 | ssc->clk = devm_clk_get(&pdev->dev, "pclk"); | ||
| 171 | if (IS_ERR(ssc->clk)) { | ||
| 172 | dev_dbg(&pdev->dev, "no pclk clock defined\n"); | ||
| 173 | return -ENXIO; | ||
| 104 | } | 174 | } |
| 105 | 175 | ||
| 106 | /* disable all interrupts */ | 176 | /* disable all interrupts */ |
| @@ -112,8 +182,7 @@ static int __init ssc_probe(struct platform_device *pdev) | |||
| 112 | ssc->irq = platform_get_irq(pdev, 0); | 182 | ssc->irq = platform_get_irq(pdev, 0); |
| 113 | if (!ssc->irq) { | 183 | if (!ssc->irq) { |
| 114 | dev_dbg(&pdev->dev, "could not get irq\n"); | 184 | dev_dbg(&pdev->dev, "could not get irq\n"); |
| 115 | retval = -ENXIO; | 185 | return -ENXIO; |
| 116 | goto out_unmap; | ||
| 117 | } | 186 | } |
| 118 | 187 | ||
| 119 | spin_lock(&user_lock); | 188 | spin_lock(&user_lock); |
| @@ -125,51 +194,31 @@ static int __init ssc_probe(struct platform_device *pdev) | |||
| 125 | dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", | 194 | dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", |
| 126 | ssc->regs, ssc->irq); | 195 | ssc->regs, ssc->irq); |
| 127 | 196 | ||
| 128 | goto out; | 197 | return 0; |
| 129 | |||
| 130 | out_unmap: | ||
| 131 | iounmap(ssc->regs); | ||
| 132 | out_clk: | ||
| 133 | clk_put(ssc->clk); | ||
| 134 | out_free: | ||
| 135 | kfree(ssc); | ||
| 136 | out: | ||
| 137 | return retval; | ||
| 138 | } | 198 | } |
| 139 | 199 | ||
| 140 | static int __devexit ssc_remove(struct platform_device *pdev) | 200 | static int ssc_remove(struct platform_device *pdev) |
| 141 | { | 201 | { |
| 142 | struct ssc_device *ssc = platform_get_drvdata(pdev); | 202 | struct ssc_device *ssc = platform_get_drvdata(pdev); |
| 143 | 203 | ||
| 144 | spin_lock(&user_lock); | 204 | spin_lock(&user_lock); |
| 145 | iounmap(ssc->regs); | ||
| 146 | clk_put(ssc->clk); | ||
| 147 | list_del(&ssc->list); | 205 | list_del(&ssc->list); |
| 148 | kfree(ssc); | ||
| 149 | spin_unlock(&user_lock); | 206 | spin_unlock(&user_lock); |
| 150 | 207 | ||
| 151 | return 0; | 208 | return 0; |
| 152 | } | 209 | } |
| 153 | 210 | ||
| 154 | static struct platform_driver ssc_driver = { | 211 | static struct platform_driver ssc_driver = { |
| 155 | .remove = __devexit_p(ssc_remove), | ||
| 156 | .driver = { | 212 | .driver = { |
| 157 | .name = "ssc", | 213 | .name = "ssc", |
| 158 | .owner = THIS_MODULE, | 214 | .owner = THIS_MODULE, |
| 215 | .of_match_table = of_match_ptr(atmel_ssc_dt_ids), | ||
| 159 | }, | 216 | }, |
| 217 | .id_table = atmel_ssc_devtypes, | ||
| 218 | .probe = ssc_probe, | ||
| 219 | .remove = ssc_remove, | ||
| 160 | }; | 220 | }; |
| 161 | 221 | module_platform_driver(ssc_driver); | |
| 162 | static int __init ssc_init(void) | ||
| 163 | { | ||
| 164 | return platform_driver_probe(&ssc_driver, ssc_probe); | ||
| 165 | } | ||
| 166 | module_init(ssc_init); | ||
| 167 | |||
| 168 | static void __exit ssc_exit(void) | ||
| 169 | { | ||
| 170 | platform_driver_unregister(&ssc_driver); | ||
| 171 | } | ||
| 172 | module_exit(ssc_exit); | ||
| 173 | 222 | ||
| 174 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); | 223 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); |
| 175 | MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); | 224 | MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); |
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..e40ffd9502d1 --- /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 | /* Locking again the Mutex */ | ||
| 191 | mutex_lock(&dev->device_lock); | ||
| 192 | |||
| 193 | if (wait_ret) | ||
| 194 | return -ERESTARTSYS; | ||
| 195 | |||
| 196 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | ||
| 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..9299a8c29a6f 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 (watchdog_get_drvdata(&amt_wd_dev) == NULL) |
| 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 4999b34b7a60..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,14 +879,17 @@ 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 | 886 | ||
| 886 | unregister_console(&pti_console); | 887 | unregister_console(&pti_console); |
| 887 | 888 | ||
| 888 | tty_unregister_device(pti_tty_driver, 0); | 889 | for (a = 0; a < PTITTY_MINOR_NUM; a++) { |
| 889 | tty_unregister_device(pti_tty_driver, 1); | 890 | tty_unregister_device(pti_tty_driver, a); |
| 891 | tty_port_destroy(&drv_data->port[a]); | ||
| 892 | } | ||
| 890 | 893 | ||
| 891 | iounmap(drv_data->pti_ioaddr); | 894 | iounmap(drv_data->pti_ioaddr); |
| 892 | pci_set_drvdata(pdev, NULL); | 895 | pci_set_drvdata(pdev, NULL); |
| @@ -901,7 +904,7 @@ static struct pci_driver pti_pci_driver = { | |||
| 901 | .name = PCINAME, | 904 | .name = PCINAME, |
| 902 | .id_table = pci_ids, | 905 | .id_table = pci_ids, |
| 903 | .probe = pti_pci_probe, | 906 | .probe = pti_pci_probe, |
| 904 | .remove = __devexit_p(pti_pci_remove), | 907 | .remove = pti_pci_remove, |
| 905 | }; | 908 | }; |
| 906 | 909 | ||
| 907 | /** | 910 | /** |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 8d082b46426b..d971817182f7 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
| @@ -53,6 +53,10 @@ | |||
| 53 | #include <linux/kthread.h> | 53 | #include <linux/kthread.h> |
| 54 | #include "xpc.h" | 54 | #include "xpc.h" |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_X86_64 | ||
| 57 | #include <asm/traps.h> | ||
| 58 | #endif | ||
| 59 | |||
| 56 | /* define two XPC debug device structures to be used with dev_dbg() et al */ | 60 | /* define two XPC debug device structures to be used with dev_dbg() et al */ |
| 57 | 61 | ||
| 58 | struct device_driver xpc_dbg_name = { | 62 | struct device_driver xpc_dbg_name = { |
| @@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | |||
| 1079 | return NOTIFY_DONE; | 1083 | return NOTIFY_DONE; |
| 1080 | } | 1084 | } |
| 1081 | 1085 | ||
| 1086 | /* Used to only allow one cpu to complete disconnect */ | ||
| 1087 | static unsigned int xpc_die_disconnecting; | ||
| 1088 | |||
| 1082 | /* | 1089 | /* |
| 1083 | * Notify other partitions to deactivate from us by first disengaging from all | 1090 | * Notify other partitions to deactivate from us by first disengaging from all |
| 1084 | * references to our memory. | 1091 | * references to our memory. |
| @@ -1092,6 +1099,9 @@ xpc_die_deactivate(void) | |||
| 1092 | long keep_waiting; | 1099 | long keep_waiting; |
| 1093 | long wait_to_print; | 1100 | long wait_to_print; |
| 1094 | 1101 | ||
| 1102 | if (cmpxchg(&xpc_die_disconnecting, 0, 1)) | ||
| 1103 | return; | ||
| 1104 | |||
| 1095 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | 1105 | /* keep xpc_hb_checker thread from doing anything (just in case) */ |
| 1096 | xpc_exiting = 1; | 1106 | xpc_exiting = 1; |
| 1097 | 1107 | ||
| @@ -1159,7 +1169,7 @@ xpc_die_deactivate(void) | |||
| 1159 | * about the lack of a heartbeat. | 1169 | * about the lack of a heartbeat. |
| 1160 | */ | 1170 | */ |
| 1161 | static int | 1171 | static int |
| 1162 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | 1172 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) |
| 1163 | { | 1173 | { |
| 1164 | #ifdef CONFIG_IA64 /* !!! temporary kludge */ | 1174 | #ifdef CONFIG_IA64 /* !!! temporary kludge */ |
| 1165 | switch (event) { | 1175 | switch (event) { |
| @@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
| 1191 | break; | 1201 | break; |
| 1192 | } | 1202 | } |
| 1193 | #else | 1203 | #else |
| 1194 | xpc_die_deactivate(); | 1204 | struct die_args *die_args = _die_args; |
| 1205 | |||
| 1206 | switch (event) { | ||
| 1207 | case DIE_TRAP: | ||
| 1208 | if (die_args->trapnr == X86_TRAP_DF) | ||
| 1209 | xpc_die_deactivate(); | ||
| 1210 | |||
| 1211 | if (((die_args->trapnr == X86_TRAP_MF) || | ||
| 1212 | (die_args->trapnr == X86_TRAP_XF)) && | ||
| 1213 | !user_mode_vm(die_args->regs)) | ||
| 1214 | xpc_die_deactivate(); | ||
| 1215 | |||
| 1216 | break; | ||
| 1217 | case DIE_INT3: | ||
| 1218 | case DIE_DEBUG: | ||
| 1219 | break; | ||
| 1220 | case DIE_OOPS: | ||
| 1221 | case DIE_GPF: | ||
| 1222 | default: | ||
| 1223 | xpc_die_deactivate(); | ||
| 1224 | } | ||
| 1195 | #endif | 1225 | #endif |
| 1196 | 1226 | ||
| 1197 | return NOTIFY_DONE; | 1227 | return NOTIFY_DONE; |
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..83269f1d16e3 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
| @@ -468,6 +468,11 @@ long st_kim_start(void *kim_data) | |||
| 468 | if (pdata->chip_enable) | 468 | if (pdata->chip_enable) |
| 469 | pdata->chip_enable(kim_gdata); | 469 | pdata->chip_enable(kim_gdata); |
| 470 | 470 | ||
| 471 | /* Configure BT nShutdown to HIGH state */ | ||
| 472 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
| 473 | mdelay(5); /* FIXME: a proper toggle */ | ||
| 474 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
| 475 | mdelay(100); | ||
| 471 | /* re-initialize the completion */ | 476 | /* re-initialize the completion */ |
| 472 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 477 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
| 473 | /* send notification to UIM */ | 478 | /* send notification to UIM */ |
| @@ -509,7 +514,8 @@ long st_kim_start(void *kim_data) | |||
| 509 | * (b) upon failure to either install ldisc or download firmware. | 514 | * (b) upon failure to either install ldisc or download firmware. |
| 510 | * The function is responsible to (a) notify UIM about un-installation, | 515 | * The function is responsible to (a) notify UIM about un-installation, |
| 511 | * (b) flush UART if the ldisc was installed. | 516 | * (b) flush UART if the ldisc was installed. |
| 512 | * (c) invoke platform's chip disabling routine. | 517 | * (c) reset BT_EN - pull down nshutdown at the end. |
| 518 | * (d) invoke platform's chip disabling routine. | ||
| 513 | */ | 519 | */ |
| 514 | long st_kim_stop(void *kim_data) | 520 | long st_kim_stop(void *kim_data) |
| 515 | { | 521 | { |
| @@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data) | |||
| 541 | err = -ETIMEDOUT; | 547 | err = -ETIMEDOUT; |
| 542 | } | 548 | } |
| 543 | 549 | ||
| 550 | /* By default configure BT nShutdown to LOW state */ | ||
| 551 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
| 552 | mdelay(1); | ||
| 553 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
| 554 | mdelay(1); | ||
| 555 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
| 556 | |||
| 544 | /* platform specific disable */ | 557 | /* platform specific disable */ |
| 545 | if (pdata->chip_disable) | 558 | if (pdata->chip_disable) |
| 546 | pdata->chip_disable(kim_gdata); | 559 | pdata->chip_disable(kim_gdata); |
| @@ -705,9 +718,9 @@ static const struct file_operations list_debugfs_fops = { | |||
| 705 | static struct dentry *kim_debugfs_dir; | 718 | static struct dentry *kim_debugfs_dir; |
| 706 | static int kim_probe(struct platform_device *pdev) | 719 | static int kim_probe(struct platform_device *pdev) |
| 707 | { | 720 | { |
| 708 | long status; | ||
| 709 | struct kim_data_s *kim_gdata; | 721 | struct kim_data_s *kim_gdata; |
| 710 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 722 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
| 723 | int err; | ||
| 711 | 724 | ||
| 712 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { | 725 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { |
| 713 | /* multiple devices could exist */ | 726 | /* multiple devices could exist */ |
| @@ -724,24 +737,39 @@ static int kim_probe(struct platform_device *pdev) | |||
| 724 | } | 737 | } |
| 725 | dev_set_drvdata(&pdev->dev, kim_gdata); | 738 | dev_set_drvdata(&pdev->dev, kim_gdata); |
| 726 | 739 | ||
| 727 | status = st_core_init(&kim_gdata->core_data); | 740 | err = st_core_init(&kim_gdata->core_data); |
| 728 | if (status != 0) { | 741 | if (err != 0) { |
| 729 | pr_err(" ST core init failed"); | 742 | pr_err(" ST core init failed"); |
| 730 | return -EIO; | 743 | err = -EIO; |
| 744 | goto err_core_init; | ||
| 731 | } | 745 | } |
| 732 | /* refer to itself */ | 746 | /* refer to itself */ |
| 733 | kim_gdata->core_data->kim_data = kim_gdata; | 747 | kim_gdata->core_data->kim_data = kim_gdata; |
| 734 | 748 | ||
| 749 | /* Claim the chip enable nShutdown gpio from the system */ | ||
| 750 | kim_gdata->nshutdown = pdata->nshutdown_gpio; | ||
| 751 | err = gpio_request(kim_gdata->nshutdown, "kim"); | ||
| 752 | if (unlikely(err)) { | ||
| 753 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | ||
| 754 | return err; | ||
| 755 | } | ||
| 756 | |||
| 757 | /* Configure nShutdown GPIO as output=0 */ | ||
| 758 | err = gpio_direction_output(kim_gdata->nshutdown, 0); | ||
| 759 | if (unlikely(err)) { | ||
| 760 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); | ||
| 761 | return err; | ||
| 762 | } | ||
| 735 | /* get reference of pdev for request_firmware | 763 | /* get reference of pdev for request_firmware |
| 736 | */ | 764 | */ |
| 737 | kim_gdata->kim_pdev = pdev; | 765 | kim_gdata->kim_pdev = pdev; |
| 738 | init_completion(&kim_gdata->kim_rcvd); | 766 | init_completion(&kim_gdata->kim_rcvd); |
| 739 | init_completion(&kim_gdata->ldisc_installed); | 767 | init_completion(&kim_gdata->ldisc_installed); |
| 740 | 768 | ||
| 741 | status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp); | 769 | err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp); |
| 742 | if (status) { | 770 | if (err) { |
| 743 | pr_err("failed to create sysfs entries"); | 771 | pr_err("failed to create sysfs entries"); |
| 744 | return status; | 772 | goto err_sysfs_group; |
| 745 | } | 773 | } |
| 746 | 774 | ||
| 747 | /* copying platform data */ | 775 | /* copying platform data */ |
| @@ -753,8 +781,8 @@ static int kim_probe(struct platform_device *pdev) | |||
| 753 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); | 781 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); |
| 754 | if (IS_ERR(kim_debugfs_dir)) { | 782 | if (IS_ERR(kim_debugfs_dir)) { |
| 755 | pr_err(" debugfs entries creation failed "); | 783 | pr_err(" debugfs entries creation failed "); |
| 756 | kim_debugfs_dir = NULL; | 784 | err = -EIO; |
| 757 | return -EIO; | 785 | goto err_debugfs_dir; |
| 758 | } | 786 | } |
| 759 | 787 | ||
| 760 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, | 788 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, |
| @@ -763,14 +791,33 @@ static int kim_probe(struct platform_device *pdev) | |||
| 763 | kim_gdata, &list_debugfs_fops); | 791 | kim_gdata, &list_debugfs_fops); |
| 764 | pr_info(" debugfs entries created "); | 792 | pr_info(" debugfs entries created "); |
| 765 | return 0; | 793 | return 0; |
| 794 | |||
| 795 | err_debugfs_dir: | ||
| 796 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | ||
| 797 | |||
| 798 | err_sysfs_group: | ||
| 799 | st_core_exit(kim_gdata->core_data); | ||
| 800 | |||
| 801 | err_core_init: | ||
| 802 | kfree(kim_gdata); | ||
| 803 | |||
| 804 | return err; | ||
| 766 | } | 805 | } |
| 767 | 806 | ||
| 768 | static int kim_remove(struct platform_device *pdev) | 807 | static int kim_remove(struct platform_device *pdev) |
| 769 | { | 808 | { |
| 809 | /* free the GPIOs requested */ | ||
| 810 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
| 770 | struct kim_data_s *kim_gdata; | 811 | struct kim_data_s *kim_gdata; |
| 771 | 812 | ||
| 772 | kim_gdata = dev_get_drvdata(&pdev->dev); | 813 | kim_gdata = dev_get_drvdata(&pdev->dev); |
| 773 | 814 | ||
| 815 | /* Free the Bluetooth/FM/GPIO | ||
| 816 | * nShutdown gpio from the system | ||
| 817 | */ | ||
| 818 | gpio_free(pdata->nshutdown_gpio); | ||
| 819 | pr_info("nshutdown GPIO Freed"); | ||
| 820 | |||
| 774 | debugfs_remove_recursive(kim_debugfs_dir); | 821 | debugfs_remove_recursive(kim_debugfs_dir); |
| 775 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | 822 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); |
| 776 | pr_info("sysfs entries removed"); | 823 | pr_info("sysfs entries removed"); |
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 | ||
