diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/bmp085-i2c.c | 2 | ||||
-rw-r--r-- | drivers/misc/bmp085-spi.c | 2 | ||||
-rw-r--r-- | drivers/misc/bmp085.c | 39 | ||||
-rw-r--r-- | drivers/misc/bmp085.h | 2 | ||||
-rw-r--r-- | drivers/misc/eeprom/eeprom_93xx46.c | 1 | ||||
-rw-r--r-- | drivers/misc/lkdtm.c | 5 | ||||
-rw-r--r-- | drivers/misc/mei/client.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 17 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 79 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 13 | ||||
-rw-r--r-- | drivers/misc/mei/nfc.c | 6 | ||||
-rw-r--r-- | drivers/misc/mei/pci-me.c | 2 | ||||
-rw-r--r-- | drivers/misc/mic/host/mic_device.h | 3 | ||||
-rw-r--r-- | drivers/misc/mic/host/mic_main.c | 2 | ||||
-rw-r--r-- | drivers/misc/mic/host/mic_virtio.c | 2 | ||||
-rw-r--r-- | drivers/misc/mic/host/mic_x100.c | 36 | ||||
-rw-r--r-- | drivers/misc/ti-st/st_core.c | 2 | ||||
-rw-r--r-- | drivers/misc/ti-st/st_kim.c | 1 |
18 files changed, 137 insertions, 79 deletions
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c index 3abfcec..a7c1629 100644 --- a/drivers/misc/bmp085-i2c.c +++ b/drivers/misc/bmp085-i2c.c @@ -49,7 +49,7 @@ static int bmp085_i2c_probe(struct i2c_client *client, return err; } - return bmp085_probe(&client->dev, regmap); + return bmp085_probe(&client->dev, regmap, client->irq); } static int bmp085_i2c_remove(struct i2c_client *client) diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c index d6a5265..864ecac 100644 --- a/drivers/misc/bmp085-spi.c +++ b/drivers/misc/bmp085-spi.c @@ -41,7 +41,7 @@ static int bmp085_spi_probe(struct spi_device *client) return err; } - return bmp085_probe(&client->dev, regmap); + return bmp085_probe(&client->dev, regmap, client->irq); } static int bmp085_spi_remove(struct spi_device *client) diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c index 2704d88..820e53d 100644 --- a/drivers/misc/bmp085.c +++ b/drivers/misc/bmp085.c @@ -49,9 +49,11 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/delay.h> #include <linux/of.h> #include "bmp085.h" +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/gpio.h> #define BMP085_CHIP_ID 0x55 #define BMP085_CALIBRATION_DATA_START 0xAA @@ -84,8 +86,19 @@ struct bmp085_data { unsigned long last_temp_measurement; u8 chip_id; s32 b6; /* calculated temperature correction coefficient */ + int irq; + struct completion done; }; +static irqreturn_t bmp085_eoc_isr(int irq, void *devid) +{ + struct bmp085_data *data = devid; + + complete(&data->done); + + return IRQ_HANDLED; +} + static s32 bmp085_read_calibration_data(struct bmp085_data *data) { u16 tmp[BMP085_CALIBRATION_DATA_LENGTH]; @@ -116,6 +129,9 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + + init_completion(&data->done); + status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_TEMP_MEASUREMENT); if (status < 0) { @@ -123,7 +139,8 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data) "Error while requesting temperature measurement.\n"); goto exit; } - msleep(BMP085_TEMP_CONVERSION_TIME); + wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( + BMP085_TEMP_CONVERSION_TIME)); status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, &tmp, sizeof(tmp)); @@ -147,6 +164,9 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) s32 status; mutex_lock(&data->lock); + + init_completion(&data->done); + status = regmap_write(data->regmap, BMP085_CTRL_REG, BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting << 6)); @@ -157,8 +177,8 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data) } /* wait for the end of conversion */ - msleep(2+(3 << data->oversampling_setting)); - + wait_for_completion_timeout(&data->done, 1 + msecs_to_jiffies( + 2+(3 << data->oversampling_setting))); /* copy data into a u32 (4 bytes), but skip the first byte. */ status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB, ((u8 *)&tmp)+1, 3); @@ -420,7 +440,7 @@ struct regmap_config bmp085_regmap_config = { }; EXPORT_SYMBOL_GPL(bmp085_regmap_config); -int bmp085_probe(struct device *dev, struct regmap *regmap) +int bmp085_probe(struct device *dev, struct regmap *regmap, int irq) { struct bmp085_data *data; int err = 0; @@ -434,6 +454,15 @@ int bmp085_probe(struct device *dev, struct regmap *regmap) dev_set_drvdata(dev, data); data->dev = dev; data->regmap = regmap; + data->irq = irq; + + if (data->irq > 0) { + err = devm_request_irq(dev, data->irq, bmp085_eoc_isr, + IRQF_TRIGGER_RISING, "bmp085", + data); + if (err < 0) + goto exit_free; + } /* Initialize the BMP085 chip */ err = bmp085_init_client(data); diff --git a/drivers/misc/bmp085.h b/drivers/misc/bmp085.h index 2b8f615..8b8e3b1 100644 --- a/drivers/misc/bmp085.h +++ b/drivers/misc/bmp085.h @@ -26,7 +26,7 @@ extern struct regmap_config bmp085_regmap_config; -int bmp085_probe(struct device *dev, struct regmap *regmap); +int bmp085_probe(struct device *dev, struct regmap *regmap, int irq); int bmp085_remove(struct device *dev); int bmp085_detect(struct device *dev); diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 3a015ab..78e55b5 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -378,7 +378,6 @@ static int eeprom_93xx46_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_erase); sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin); - spi_set_drvdata(spi, NULL); kfree(edev); return 0; } diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index a2edb2e..a9a203d 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -334,9 +334,10 @@ static void execute_location(void *dst) static void execute_user_location(void *dst) { + /* Intentionally crossing kernel/user memory boundary. */ void (*func)(void) = dst; - if (copy_to_user(dst, do_nothing, EXEC_SIZE)) + if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) return; func(); } @@ -408,6 +409,8 @@ static void lkdtm_do_action(enum ctype which) case CT_SPINLOCKUP: /* Must be called twice to trigger. */ spin_lock(&lock_me_up); + /* Let sparse know we intended to exit holding the lock. */ + __release(&lock_me_up); break; case CT_HUNG_TASK: set_current_state(TASK_UNINTERRUPTIBLE); diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 87c96e4..6184e85 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -344,8 +344,6 @@ int mei_cl_unlink(struct mei_cl *cl) cl->state = MEI_FILE_INITIALIZING; - list_del_init(&cl->link); - return 0; } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index f7f3abb..83c879b 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -131,6 +131,15 @@ err: } EXPORT_SYMBOL_GPL(mei_start); + +void mei_cancel_work(struct mei_device *dev) +{ + cancel_work_sync(&dev->init_work); + + cancel_delayed_work(&dev->timer_work); +} +EXPORT_SYMBOL_GPL(mei_cancel_work); + /** * mei_reset - resets host and fw. * @@ -215,16 +224,14 @@ void mei_stop(struct mei_device *dev) { dev_dbg(&dev->pdev->dev, "stopping the device.\n"); - flush_scheduled_work(); + mei_cancel_work(dev); - mutex_lock(&dev->device_lock); + mei_nfc_host_exit(dev); - cancel_delayed_work(&dev->timer_work); + mutex_lock(&dev->device_lock); mei_wd_stop(dev); - mei_nfc_host_exit(); - dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev, 0); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 7a95c07..9c8225b 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -301,13 +301,11 @@ int mei_irq_read_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list, s32 *slots) { struct mei_msg_hdr *mei_hdr; - struct mei_cl *cl_pos = NULL; - struct mei_cl *cl_next = NULL; - int ret = 0; + struct mei_cl *cl; + int ret; if (!dev->rd_msg_hdr) { dev->rd_msg_hdr = mei_read_hdr(dev); - dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); (*slots)--; dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); } @@ -315,61 +313,64 @@ int mei_irq_read_handler(struct mei_device *dev, dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); if (mei_hdr->reserved || !dev->rd_msg_hdr) { - dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); + dev_err(&dev->pdev->dev, "corrupted message header 0x%08X\n", + dev->rd_msg_hdr); ret = -EBADMSG; goto end; } - if (mei_hdr->host_addr || mei_hdr->me_addr) { - list_for_each_entry_safe(cl_pos, cl_next, - &dev->file_list, link) { - dev_dbg(&dev->pdev->dev, - "list_for_each_entry_safe read host" - " client = %d, ME client = %d\n", - cl_pos->host_client_id, - cl_pos->me_client_id); - if (mei_cl_hbm_equal(cl_pos, mei_hdr)) - break; - } - - if (&cl_pos->link == &dev->file_list) { - dev_dbg(&dev->pdev->dev, "corrupted message header\n"); - ret = -EBADMSG; - goto end; - } - } - if (((*slots) * sizeof(u32)) < mei_hdr->length) { - dev_err(&dev->pdev->dev, - "we can't read the message slots =%08x.\n", + if (mei_slots2data(*slots) < mei_hdr->length) { + dev_err(&dev->pdev->dev, "less data available than length=%08x.\n", *slots); /* we can't read the message */ ret = -ERANGE; goto end; } - /* decide where to read the message too */ - if (!mei_hdr->host_addr) { - dev_dbg(&dev->pdev->dev, "call mei_hbm_dispatch.\n"); + /* HBM message */ + if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) { mei_hbm_dispatch(dev, mei_hdr); - dev_dbg(&dev->pdev->dev, "end mei_hbm_dispatch.\n"); - } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && - (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && - (dev->iamthif_state == MEI_IAMTHIF_READING)) { + ret = 0; + dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch.\n"); + goto reset_slots; + } - dev_dbg(&dev->pdev->dev, "call mei_amthif_irq_read_msg.\n"); - dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); + /* find recepient cl */ + list_for_each_entry(cl, &dev->file_list, link) { + if (mei_cl_hbm_equal(cl, mei_hdr)) { + cl_dbg(dev, cl, "got a message\n"); + break; + } + } + + /* if no recepient cl was found we assume corrupted header\n */ + if (&cl->link == &dev->file_list) { + dev_err(&dev->pdev->dev, "no destination client found 0x%08X\n", + dev->rd_msg_hdr); + ret = -EBADMSG; + goto end; + } + + if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && + MEI_FILE_CONNECTED == dev->iamthif_cl.state && + dev->iamthif_state == MEI_IAMTHIF_READING) { ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list); - if (ret) + if (ret) { + dev_err(&dev->pdev->dev, "mei_amthif_irq_read_msg failed = %d\n", + ret); goto end; + } } else { - dev_dbg(&dev->pdev->dev, "call mei_cl_irq_read_msg.\n"); - dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list); - if (ret) + if (ret) { + dev_err(&dev->pdev->dev, "mei_cl_irq_read_msg failed = %d\n", + ret); goto end; + } } +reset_slots: /* reset the number of slots and header */ *slots = mei_count_full_read_slots(dev); dev->rd_msg_hdr = 0; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 406f68e..4a7ee81 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -456,6 +456,16 @@ static inline u32 mei_data2slots(size_t length) return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); } +/** + * mei_slots2data- get data in slots - bytes from slots + * @slots - number of available slots + * returns - number of bytes in slots + */ +static inline u32 mei_slots2data(int slots) +{ + return slots * 4; +} + /* * mei init function prototypes */ @@ -463,6 +473,7 @@ void mei_device_init(struct mei_device *dev); void mei_reset(struct mei_device *dev, int interrupts); int mei_start(struct mei_device *dev); void mei_stop(struct mei_device *dev); +void mei_cancel_work(struct mei_device *dev); /* * MEI interrupt functions prototype @@ -510,7 +521,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); * NFC functions */ int mei_nfc_host_init(struct mei_device *dev); -void mei_nfc_host_exit(void); +void mei_nfc_host_exit(struct mei_device *dev); /* * NFC Client UUID diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index 994ca4a..0a89220 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c @@ -547,12 +547,16 @@ err: return ret; } -void mei_nfc_host_exit(void) +void mei_nfc_host_exit(struct mei_device *dev) { struct mei_nfc_dev *ndev = &nfc_dev; + cancel_work_sync(&ndev->init_work); + + mutex_lock(&dev->device_lock); if (ndev->cl && ndev->cl->device) mei_cl_remove_device(ndev->cl->device); mei_nfc_free(ndev); + mutex_unlock(&dev->device_lock); } diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 2cab3c0..7dfaa32 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -197,8 +197,8 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; release_irq: + mei_cancel_work(dev); mei_disable_interrupts(dev); - flush_scheduled_work(); free_irq(pdev->irq, dev); disable_msi: pci_disable_msi(pdev); diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 3574cc3..b2da289 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h @@ -134,6 +134,8 @@ struct mic_device { * @send_intr: Send an interrupt for a particular doorbell on the card. * @ack_interrupt: Hardware specific operations to ack the h/w on * receipt of an interrupt. + * @intr_workarounds: Hardware specific workarounds needed after + * handling an interrupt. * @reset: Reset the remote processor. * @reset_fw_ready: Reset firmware ready field. * @is_fw_ready: Check if firmware is ready for OS download. @@ -149,6 +151,7 @@ struct mic_hw_ops { void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val); void (*send_intr)(struct mic_device *mdev, int doorbell); u32 (*ack_interrupt)(struct mic_device *mdev); + void (*intr_workarounds)(struct mic_device *mdev); void (*reset)(struct mic_device *mdev); void (*reset_fw_ready)(struct mic_device *mdev); bool (*is_fw_ready)(struct mic_device *mdev); diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index ad838c7..c04a021 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c @@ -115,7 +115,7 @@ static irqreturn_t mic_shutdown_db(int irq, void *data) struct mic_device *mdev = data; struct mic_bootparam *bootparam = mdev->dp; - mdev->ops->ack_interrupt(mdev); + mdev->ops->intr_workarounds(mdev); switch (bootparam->shutdown_status) { case MIC_HALTED: diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index e04bb4f..752ff87 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c @@ -369,7 +369,7 @@ static irqreturn_t mic_virtio_intr_handler(int irq, void *data) struct mic_vdev *mvdev = data; struct mic_device *mdev = mvdev->mdev; - mdev->ops->ack_interrupt(mdev); + mdev->ops->intr_workarounds(mdev); schedule_work(&mvdev->virtio_bh_work); return IRQ_HANDLED; } diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index 0dfa8a8..5562fdd 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c @@ -174,35 +174,38 @@ static void mic_x100_send_intr(struct mic_device *mdev, int doorbell) } /** - * mic_ack_interrupt - Device specific interrupt handling. - * @mdev: pointer to mic_device instance + * mic_x100_ack_interrupt - Read the interrupt sources register and + * clear it. This function will be called in the MSI/INTx case. + * @mdev: Pointer to mic_device instance. * - * Returns: bitmask of doorbell events triggered. + * Returns: bitmask of interrupt sources triggered. */ static u32 mic_x100_ack_interrupt(struct mic_device *mdev) { - u32 reg = 0; - struct mic_mw *mw = &mdev->mmio; u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0; + u32 reg = mic_mmio_read(&mdev->mmio, sicr0); + mic_mmio_write(&mdev->mmio, reg, sicr0); + return reg; +} + +/** + * mic_x100_intr_workarounds - These hardware specific workarounds are + * to be invoked everytime an interrupt is handled. + * @mdev: Pointer to mic_device instance. + * + * Returns: none + */ +static void mic_x100_intr_workarounds(struct mic_device *mdev) +{ + struct mic_mw *mw = &mdev->mmio; /* Clear pending bit array. */ if (MIC_A0_STEP == mdev->stepping) mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_MSIXPBACR); - if (mdev->irq_info.num_vectors <= 1) { - reg = mic_mmio_read(mw, sicr0); - - if (unlikely(!reg)) - goto done; - - mic_mmio_write(mw, reg, sicr0); - } - if (mdev->stepping >= MIC_B0_STEP) mdev->intr_ops->enable_interrupts(mdev); -done: - return reg; } /** @@ -553,6 +556,7 @@ struct mic_hw_ops mic_x100_ops = { .write_spad = mic_x100_write_spad, .send_intr = mic_x100_send_intr, .ack_interrupt = mic_x100_ack_interrupt, + .intr_workarounds = mic_x100_intr_workarounds, .reset = mic_x100_hw_reset, .reset_fw_ready = mic_x100_reset_fw_ready, .is_fw_ready = mic_x100_is_fw_ready, diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 8d64b68..3aed525 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -812,7 +812,7 @@ static void st_tty_flush_buffer(struct tty_struct *tty) kfree_skb(st_gdata->tx_skb); st_gdata->tx_skb = NULL; - tty->ops->flush_buffer(tty); + tty_driver_flush_buffer(tty); return; } diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 96853a0..9d3dbb2 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -531,7 +531,6 @@ long st_kim_stop(void *kim_data) /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); - tty->ops->flush_buffer(tty); } /* send uninstall notification to UIM */ |