From: Sreedevi Joshi <sreedevi.jo...@intel.com>

This contains fixes for the following issues:
1. When MTC program memory is read using character device, the
data is incorrect. This seems to be due to copy_to_user() not
working as expected when copying from _iomem pointer to user space
char pointer. The data is first copied to a byte array before
sending to user space now.
2. Incorrect setup of device configuration bits when using
TDO_NOREC_SHIFTDR mode is fixed.
3. To work with 32-bit user space applications, compat_ioctl
operation is defined.

Signed-off-by: Sreedevi Joshi <sreedevi.jo...@intel.com>
---
 drivers/misc/lsi-mtc.c | 58 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/drivers/misc/lsi-mtc.c b/drivers/misc/lsi-mtc.c
index a9285fe..354082b 100644
--- a/drivers/misc/lsi-mtc.c
+++ b/drivers/misc/lsi-mtc.c
@@ -30,7 +30,6 @@
 #include <linux/io.h>
 #include <linux/string.h>
 #include <linux/delay.h>
-
 #include "linux/lsi_mtc_ioctl.h"
 
 
@@ -3093,6 +3092,8 @@ mtc_dev_read(struct file *filp, char __user *data, size_t 
len, loff_t *ppose)
        u32 tdo_size_word, tdo_size_bit;        /* data to be read in words */
        struct ncp_axis_mtc_MTC_STATUS1_REG_ADDR_r_t status1Reg = { 0 };
        struct ncp_axis_mtc_MTC_EXECUTE1_REG_ADDR_r_t exec1Reg = { 0 };
+       u32 i = 0;
+       char *tmp_data = NULL;
 
        pr_debug("mtc_dev_read(%u @ %llu)\n", (unsigned int) len, *ppose);
        ptdo = dev->tdomem;
@@ -3116,10 +3117,33 @@ mtc_dev_read(struct file *filp, char __user *data, 
size_t len, loff_t *ppose)
        pr_debug("mtc_dev_read(), tdo_bit=%d tdo_word=%d\n",
                 tdo_size_bit, tdo_size_word);
 #endif
+
+       tmp_data = kmalloc(tdo_size_word*4, GFP_KERNEL);
+
+       if (!tmp_data)
+               return -EFAULT;
+
+       memset(tmp_data, 0, tdo_size_word * 4);
+       for (i = 0; i < tdo_size_word*4; i++) {
+#ifdef DEBUG
+               pr_debug("data[%d]=0x%x\n", i, ptdo[i]);
+#endif
+               tmp_data[i] = (ptdo[i/4] & (0xFF << ((i%4) * 8))) >>
+                       ((i%4) * 8);
+       }
        /* copy tdo data to user space, always read from location 0
           because we reset tdomem after each read */
-       if (copy_to_user(data, ptdo, tdo_size_word * 4))
+       if (copy_to_user((void *)data, tmp_data, tdo_size_word * 4)) {
+               kfree(tmp_data);
                return -EFAULT;
+       }
+#ifdef DEBUG
+       for (i = 0; i < tdo_size_word*4; i++) {
+               pr_debug("copied data[%d]=0x%x tmp_data=0x%x\n",
+                                i, data[i], tmp_data[i]);
+       }
+#endif
+       kfree(tmp_data);
 
        /* data sent to user, reset tdo capture buffer */
        memset(&exec1Reg, 0, sizeof(exec1Reg));
@@ -3152,7 +3176,7 @@ _mtc_axi_dev_write(struct file *filp,
        if (!mtc_buf)
                return -EFAULT;
 
-       /* copy to a lcoal buffer */
+       /* copy to a local buffer */
        memset(mtc_buf, 0, len);
        if (copy_from_user((void *)mtc_buf, (void *)data, len)) {
                pr_debug("MTC Error write\n");
@@ -3170,8 +3194,8 @@ _mtc_axi_dev_write(struct file *filp,
 
        for (i = 0; i < size; i++) {
 #ifdef DEBUG
-               pr_debug("i=%d mtc_buf[i]=%d pprg=0x%x\n",
-                        i, mtc_buf[i], (u32) pprg);
+               pr_debug("i=%d mtc_buf[i]=%d pprg=0x%llx\n",
+                        i, mtc_buf[i], (u64) pprg);
 #endif
                *pprg = mtc_buf[i];
                pprg++;
@@ -3220,6 +3244,10 @@ mtc_dev_write(struct file *filp,
        size = len / 4;
        size1 = size;
 
+#ifdef DEBUG
+       for (i = 0; i < len; i++)
+               pr_debug("input data[%d]=0x%x\n", i, data[i]);
+#endif
        /* copy to a lcoal buffer */
        memset(mtc_buf, 0, 1024);
        if (copy_from_user((void *)mtc_buf, (void *)data, len)) {
@@ -3227,6 +3255,10 @@ mtc_dev_write(struct file *filp,
                return -EFAULT;
        }
 
+#ifdef DEBUG
+       for (i = 0; i < len; i++)
+               pr_debug("after copying: mtc_buf[%d]=0x%x\n", i, mtc_buf[i]);
+#endif
        /* read status 1register, find the starting write offset */
        status1Reg =
            *((struct ncp_axis_mtc_MTC_STATUS1_REG_ADDR_r_t *)
@@ -3257,8 +3289,8 @@ mtc_dev_write(struct file *filp,
 
        for (i = 0; i < size1; i++) {
 #ifdef DEBUG
-               pr_debug("i=%d mtc_buf[i]=%d pprg=0x%x\n",
-                        i, mtc_buf[i], (u32) pprg);
+               pr_debug("i=%d mtc_buf[i]=%d pprg=0x%llx\n",
+                        i, mtc_buf[i], (u64) pprg);
 #endif
                *pprg = mtc_buf[i];
                pprg++;
@@ -3273,8 +3305,8 @@ mtc_dev_write(struct file *filp,
 #endif
                for (i = 0; i < (size - size1); i++) {
 #ifdef DEBUG
-                       pr_debug("i=%d mtc_buf[size1+i]=%d pprg=0x%x\n", i,
-                                mtc_buf[size1 + i], (u32) pprg);
+                       pr_debug("i=%d mtc_buf[size1+i]=%d pprg=0x%llx\n", i,
+                                mtc_buf[size1 + i], (u64) pprg);
 #endif
                        *pprg = mtc_buf[size1 + i];
                        pprg++;
@@ -3301,7 +3333,6 @@ mtc_dev_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
        unsigned long numByteCopied;
 
        pr_debug("mtc_dev_ioctl(%#x, %#lx)\n", cmd, arg);
-
        switch (cmd) {
 
        case MTC_DEBUG_OP:
@@ -3930,7 +3961,8 @@ static const struct file_operations mtc_char_ops = {
        .llseek = generic_file_llseek,
        .read = mtc_dev_read,
        .write = mtc_dev_write,
-       .unlocked_ioctl = mtc_dev_ioctl
+       .unlocked_ioctl = mtc_dev_ioctl,
+       .compat_ioctl = mtc_dev_ioctl
 };
 
 static irqreturn_t mtc_isr(int irq_no, void *arg)
@@ -4178,8 +4210,8 @@ static long _mtc_config(struct mtc_device *dev, struct 
lsi_mtc_cfg_t *pMTCCfg)
                cfg1.record_tdo_in_shift_ir_state = 0;
                cfg1.record_tdo_in_shift_dr_state = 1;
        } else if (pMTCCfg->recMode == LSI_MTC_TDO_NOREC_SHIFTDR) {
-               cfg1.record_tdo_in_shift_ir_state = 0;
-               cfg1.record_tdo_in_shift_dr_state = 1;
+               cfg1.record_tdo_in_shift_ir_state = 1;
+               cfg1.record_tdo_in_shift_dr_state = 0;
        } else {
                /* recMode == ACELL_MTCI_TDO_REC_ALL */
                cfg1.record_tdo_in_shift_ir_state = 1;
-- 
2.7.4

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to