Thread (6 messages) flat view 6 messages, 2 authors, 2017-09-08

Re: [patch v8 1/4] drivers: jtag: Add JTAG core driver

From: Arnd Bergmann <hidden>
Date: 2017-09-08 19:51:48
Also in: linux-arm-kernel, linux-devicetree, linux-serial, lkml, openbmc

On Fri, Sep 8, 2017 at 6:13 PM, Oleksandr Shamray
[off-list ref] wrote:
Initial patch for JTAG driver
JTAG class driver provide infrastructure to support hardware/software
JTAG platform drivers. It provide user layer API interface for flashing
and debugging external devices which equipped with JTAG interface
using standard transactions.

Driver exposes set of IOCTL to user space for:
- XFER:
- SIR (Scan Instruction Register, IEEE 1149.1 Data Register scan);
- SDR (Scan Data Register, IEEE 1149.1 Instruction Register scan);
- RUNTEST (Forces the IEEE 1149.1 bus to a run state for a specified
  number of clocks).
- SIOCFREQ/GIOCFREQ for setting and reading JTAG frequency.

Driver core provides set of internal APIs for allocation and
registration:
- jtag_register;
- jtag_unregister;
- jtag_alloc;
- jtag_free;

Platform driver on registration with jtag-core creates the next
entry in dev folder:
/dev/jtagX

Signed-off-by: Oleksandr Shamray <oleksandrs-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Jiri Pirko <jiri-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Acked-by: Arnd Bergmann <redacted>
My Ack was actually just for the device driver part, I had not
looked at the core again, sorry for not being clearer here.

The other two patches are fine, but looking at this one again,
I find a couple of things to improve:
+
+static __u64 jtag_copy_from_user(__u64 udata, unsigned long bit_size)
+{
+       unsigned long size;
+       void *kdata;
+
+       size = DIV_ROUND_UP(bit_size, BITS_PER_BYTE);
+       kdata = memdup_user(u64_to_user_ptr(udata), size);
+
+       return (__u64)(uintptr_t)kdata;
+}
+
+static unsigned long jtag_copy_to_user(__u64 udata, __u64 kdata,
+                                      unsigned long bit_size)
+{
+       unsigned long size;
+
+       size = DIV_ROUND_UP(bit_size, BITS_PER_BYTE);
+
+       return copy_to_user(u64_to_user_ptr(udata), jtag_u64_to_ptr(kdata),
+                           size);
+}
Only a style comment, but the casting to and from u64 multiple
times here seems overly complicated. Why not use a regular kernel
pointer here, and then pass that as a third argument to
ag->ops->xfer() ?
+
+       case JTAG_SIOCFREQ:
+               err = __get_user(value, uarg);
This needs to use get_user(), not __get_user(). I think you changed
all the other instances after an earlier comment, but missed this one.
+static int jtag_open(struct inode *inode, struct file *file)
+{
+       struct jtag *jtag = container_of(inode->i_cdev, struct jtag, cdev);
+
+       spin_lock(&jtag->lock);
+
+       if (jtag->open) {
+               dev_info(NULL, "jtag already opened\n");
+               spin_unlock(&jtag->lock);
+               return -EBUSY;
+       }
+
+       jtag->open++;
+       file->private_data = jtag;
+       spin_unlock(&jtag->lock);
+       return 0;
+}
The spinlock seems to not protect anything but the use count,
so this could be an atomic_t.

+       mutex_lock(&jtag_mutex);
+       list_add_tail(&jtag->list, &jtag_list);
+       mutex_unlock(&jtag_mutex);
Similarly, you only use the mutex to protect the list_add/list_del,
but nothing ever walks the list, so I think you can simply remove
both the list and the mutex.
+static int __init jtag_init(void)
+{
+       int err;
+
+       err = alloc_chrdev_region(&jtag_devt, 0, 1, "jtag");
+       if (err)
+               return err;
+       return class_register(&jtag_class);
+}
+
+static void __exit jtag_exit(void)
+{
+       class_unregister(&jtag_class);
+}
This looks a bit asymmetric:

- you allocate a chardev region but don't destroy it in jtag_exit,
  so presumably this leaks a major number allocation each
  time you load/unload the module

- you allocate a single minor number at module load time,
  but the individual devices each get another number, and
  the original one does not appear to be used, unless I
  misunderstand the API here.

     Arnd
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help