Allow copying partial data to user space. So that opal-prd daemon can read message size, reallocate memory and make read call to get rest of the data.
Cc: Jeremy Kerr <j...@ozlabs.org> Cc: Vaidyanathan Srinivasan <sva...@linux.vnet.ibm.com> Signed-off-by: Vasant Hegde <hegdevas...@linux.vnet.ibm.com> --- arch/powerpc/platforms/powernv/opal-prd.c | 27 ++++++++--------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c index 45f4223a790f..dac9d18293d8 100644 --- a/arch/powerpc/platforms/powernv/opal-prd.c +++ b/arch/powerpc/platforms/powernv/opal-prd.c @@ -153,20 +153,15 @@ static __poll_t opal_prd_poll(struct file *file, static ssize_t opal_prd_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct opal_prd_msg_queue_item *item; + struct opal_prd_msg_queue_item *item = NULL; unsigned long flags; - ssize_t size, err; + ssize_t size; int rc; /* we need at least a header's worth of data */ if (count < sizeof(item->msg)) return -EINVAL; - if (*ppos) - return -ESPIPE; - - item = NULL; - for (;;) { spin_lock_irqsave(&opal_prd_msg_queue_lock, flags); @@ -190,27 +185,23 @@ static ssize_t opal_prd_read(struct file *file, char __user *buf, } size = be16_to_cpu(item->msg.size); - if (size > count) { - err = -EINVAL; + rc = simple_read_from_buffer(buf, count, ppos, &item->msg, size); + if (rc < 0) goto err_requeue; - } - - rc = copy_to_user(buf, &item->msg, size); - if (rc) { - err = -EFAULT; + if (*ppos < size) goto err_requeue; - } + /* Reset position */ + *ppos = 0; kfree(item); - - return size; + return rc; err_requeue: /* eep! re-queue at the head of the list */ spin_lock_irqsave(&opal_prd_msg_queue_lock, flags); list_add(&item->list, &opal_prd_msg_queue); spin_unlock_irqrestore(&opal_prd_msg_queue_lock, flags); - return err; + return rc; } static ssize_t opal_prd_write(struct file *file, const char __user *buf, -- 2.21.0