diff options
Diffstat (limited to 'drivers/char/tpm/tpm_ibmvtpm.c')
| -rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 145 |
1 files changed, 43 insertions, 102 deletions
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index efc4ab36a9d..af74c57e509 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c @@ -32,14 +32,12 @@ static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm"; -static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = { +static struct vio_device_id tpm_ibmvtpm_device_table[] = { { "IBM,vtpm", "IBM,vtpm"}, { "", "" } }; MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); -DECLARE_WAIT_QUEUE_HEAD(wq); - /** * ibmvtpm_send_crq - Send a CRQ request * @vdev: vio device struct @@ -66,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); if (chip) - return (struct ibmvtpm_dev *)chip->vendor.data; + return (struct ibmvtpm_dev *)TPM_VPRIV(chip); return NULL; } @@ -83,30 +81,32 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct ibmvtpm_dev *ibmvtpm; u16 len; + int sig; - ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); if (!ibmvtpm->rtce_buf) { dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); return 0; } - wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0); + sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0); + if (sig) + return -EINTR; + + len = ibmvtpm->res_len; - if (count < ibmvtpm->crq_res.len) { + if (count < len) { dev_err(ibmvtpm->dev, - "Invalid size in recv: count=%ld, crq_size=%d\n", - count, ibmvtpm->crq_res.len); + "Invalid size in recv: count=%zd, crq_size=%d\n", + count, len); return -EIO; } spin_lock(&ibmvtpm->rtce_lock); - memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len); - memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len); - ibmvtpm->crq_res.valid = 0; - ibmvtpm->crq_res.msg = 0; - len = ibmvtpm->crq_res.len; - ibmvtpm->crq_res.len = 0; + memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len); + memset(ibmvtpm->rtce_buf, 0, len); + ibmvtpm->res_len = 0; spin_unlock(&ibmvtpm->rtce_lock); return len; } @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) u64 *word = (u64 *) &crq; int rc; - ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); if (!ibmvtpm->rtce_buf) { dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); @@ -136,7 +136,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) if (count > ibmvtpm->rtce_size) { dev_err(ibmvtpm->dev, - "Invalid size in send: count=%ld, rtce_size=%d\n", + "Invalid size in send: count=%zd, rtce_size=%d\n", count, ibmvtpm->rtce_size); return -EIO; } @@ -267,13 +267,12 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) * Return value: * 0 */ -static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev) +static int tpm_ibmvtpm_remove(struct vio_dev *vdev) { struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); int rc = 0; free_irq(vdev->irq, ibmvtpm); - tasklet_kill(&ibmvtpm->tasklet); do { if (rc) @@ -372,7 +371,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm) static int tpm_ibmvtpm_resume(struct device *dev) { struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); - unsigned long flags; int rc = 0; do { @@ -387,10 +385,11 @@ static int tpm_ibmvtpm_resume(struct device *dev) return rc; } - spin_lock_irqsave(&ibmvtpm->lock, flags); - vio_disable_interrupts(ibmvtpm->vdev); - tasklet_schedule(&ibmvtpm->tasklet); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); + rc = vio_enable_interrupts(ibmvtpm->vdev); + if (rc) { + dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc); + return rc; + } rc = ibmvtpm_crq_send_init(ibmvtpm); if (rc) @@ -399,52 +398,19 @@ static int tpm_ibmvtpm_resume(struct device *dev) return rc; } -static const struct file_operations ibmvtpm_ops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = tpm_open, - .read = tpm_read, - .write = tpm_write, - .release = tpm_release, -}; - -static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); -static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); -static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); -static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); -static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); -static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, - NULL); -static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); -static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); -static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); -static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); - -static struct attribute *ibmvtpm_attrs[] = { - &dev_attr_pubek.attr, - &dev_attr_pcrs.attr, - &dev_attr_enabled.attr, - &dev_attr_active.attr, - &dev_attr_owned.attr, - &dev_attr_temp_deactivated.attr, - &dev_attr_caps.attr, - &dev_attr_cancel.attr, - &dev_attr_durations.attr, - &dev_attr_timeouts.attr, NULL, -}; - -static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs }; +static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status) +{ + return (status == 0); +} -static const struct tpm_vendor_specific tpm_ibmvtpm = { +static const struct tpm_class_ops tpm_ibmvtpm = { .recv = tpm_ibmvtpm_recv, .send = tpm_ibmvtpm_send, .cancel = tpm_ibmvtpm_cancel, .status = tpm_ibmvtpm_status, .req_complete_mask = 0, .req_complete_val = 0, - .req_canceled = 0, - .attr_group = &ibmvtpm_attr_grp, - .miscdev = { .fops = &ibmvtpm_ops, }, + .req_canceled = tpm_ibmvtpm_req_canceled, }; static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = { @@ -467,7 +433,7 @@ static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm) if (crq->valid & VTPM_MSG_RES) { if (++crq_q->index == crq_q->num_entry) crq_q->index = 0; - rmb(); + smp_rmb(); } else crq = NULL; return crq; @@ -503,7 +469,6 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg); return; } - return; case IBMVTPM_VALID_CMD: switch (crq->msg) { case VTPM_GET_RTCE_BUFFER_SIZE_RES: @@ -535,11 +500,9 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, ibmvtpm->vtpm_version = crq->data; return; case VTPM_TPM_COMMAND_RES: - ibmvtpm->crq_res.valid = crq->valid; - ibmvtpm->crq_res.msg = crq->msg; - ibmvtpm->crq_res.len = crq->len; - ibmvtpm->crq_res.data = crq->data; - wake_up_interruptible(&wq); + /* len of the data in rtce buffer */ + ibmvtpm->res_len = crq->len; + wake_up_interruptible(&ibmvtpm->wq); return; default: return; @@ -559,38 +522,19 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance) { struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance; - unsigned long flags; - - spin_lock_irqsave(&ibmvtpm->lock, flags); - vio_disable_interrupts(ibmvtpm->vdev); - tasklet_schedule(&ibmvtpm->tasklet); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); - - return IRQ_HANDLED; -} - -/** - * ibmvtpm_tasklet - Interrupt handler tasklet - * @data: ibm vtpm device struct - * - * Returns: - * Nothing - **/ -static void ibmvtpm_tasklet(void *data) -{ - struct ibmvtpm_dev *ibmvtpm = data; struct ibmvtpm_crq *crq; - unsigned long flags; - spin_lock_irqsave(&ibmvtpm->lock, flags); + /* while loop is needed for initial setup (get version and + * get rtce_size). There should be only one tpm request at any + * given time. + */ while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) { ibmvtpm_crq_process(crq, ibmvtpm); crq->valid = 0; - wmb(); + smp_wmb(); } - vio_enable_interrupts(ibmvtpm->vdev); - spin_unlock_irqrestore(&ibmvtpm->lock, flags); + return IRQ_HANDLED; } /** @@ -602,7 +546,7 @@ static void ibmvtpm_tasklet(void *data) * 0 - Success * Non-zero - Failure */ -static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, +static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, const struct vio_device_id *id) { struct ibmvtpm_dev *ibmvtpm; @@ -650,9 +594,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto reg_crq_cleanup; } - tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet, - (unsigned long)ibmvtpm); - rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0, tpm_ibmvtpm_driver_name, ibmvtpm); if (rc) { @@ -666,13 +607,14 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, goto init_irq_cleanup; } + init_waitqueue_head(&ibmvtpm->wq); + crq_q->index = 0; ibmvtpm->dev = dev; ibmvtpm->vdev = vio_dev; - chip->vendor.data = (void *)ibmvtpm; + TPM_VPRIV(chip) = (void *)ibmvtpm; - spin_lock_init(&ibmvtpm->lock); spin_lock_init(&ibmvtpm->rtce_lock); rc = ibmvtpm_crq_send_init(ibmvtpm); @@ -689,7 +631,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev, return rc; init_irq_cleanup: - tasklet_kill(&ibmvtpm->tasklet); do { rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); } while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1)); |
