Skip to contentSkip to conversation

usb: usbtmc: Add vendor specific/asynchronous read/write ioctls

PATCH New Greg Kroah-Hartman 1 participant 1 message May 22, 2018 USB

lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

PATCH 6/12 usb: usbtmc: Add vendor specific/asynchronous read/write ioctls

Quoted 48 lines · On Tue, May 22, 2018 at 11:36:13AM +0000, [email protected] wrote:

Zitat von Greg KH <[email protected]>:

Quoted 32 lines · On Mon, May 21, 2018 at 08:41:22PM +0000, [email protected] wrote:
Quoted 31 lines

Zitat von Greg KH <[email protected]>:

Quoted 14 lines · On Fri, May 18, 2018 at 02:48:11PM +0000, [email protected] wrote:
Quoted 13 lines

Zitat von Greg KH <[email protected]>:

Quoted 10 lines · Guido Kiener
Quoted 9 lines
(quoted diff) +9 -0
+/*
+ * usbtmc_message->flags:
+ */
+#define USBTMC_FLAG_ASYNC		0x0001
+#define USBTMC_FLAG_APPEND		0x0002
+#define USBTMC_FLAG_IGNORE_TRAILER	0x0004
+
+struct usbtmc_message {
+	void __user *message; /* pointer to header and data */
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	__u64 transfer_size; /* size of bytes to transfer */
+	__u64 transferred; /* size of received/written bytes */
+	__u32 flags; /* bit 0: 0 = synchronous; 1 = asynchronous */
+} __attribute__ ((packed));

Very odd structure. Your userspace pointer is going to be totally out of alignment on 32bit systems running on a 64bit kernel. Why have a separate pointer at all? Why not just put the mesage at the

end of this

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

structure directly with something like:

	__u8 message[0];

?

Quoted 8 lines
Quoted 5 lines

Using a __u8 message[0] ends up with an extra malloc, memcpy, and free operation in userland, since we always have to append the data of a given user pointer to this struct. E.g. when I send 4 MByte on my (old) laptop this takes about plus 6 ms, and decreases bandwidth from 31,0 MByte/s to 29,5 MByte/s with USB 2.0.

Really? That feels like you are doing something really odd. I guess you need to figure out how you get the data to/from userspace.

A typically user API is something like this:
ssize_t write(int fd, const void *buf, size_t count); ssize_t send(int sockfd, const void *buf, size_t len, int flags);

Quoted 5 lines

We use a similar function:
ViStatus viWrite(ViSession vi, ViBuf buf, ViUInt32 count, ViPUInt32 retCount)

When a user calls viWrite(vi, "*IDN? + 4 MB ...\n", 40000000, &retcont) how can we pass the big buf to the kernel without any copy operation?

Your function looks _just_ like a normal write() call, why are you even trying to wrap it in an ioctl? Just use write()!

Quoted 15 lines
Quoted 9 lines
Quoted 8 lines

I hope this struct looks better (in compat mode):

struct usbtmc_message {
__u64 transfer_size; /* size of bytes to transfer */ __u64 transferred; /* size of received/written bytes */ void __user *message; /* pointer to header and data */ __u32 flags; /* bit 0: 0 = synchronous; 1 = asynchronous */
} __attribute__ ((packed));

Quoted 3 lines

No, that will not work at all. Again, think about the size of that pointer.

The compat structure is:

Quoted 8 lines
struct compat_usbtmc_message {
	u64 transfer_size;
	u64 transferred;
	compat_uptr_t message;
	u32 flags;
} __packed;

For AMD64 it works.

Show me the size and layout of both structures for a 32bit and 64bit userspace please. There are tools that do this.

Again, this is not how to do it! You do not put a variable sized variable in the middle of a structure. void * changes size! Either align everything properly or throw it at the end or even better yet, DON'T DO THIS AT ALL, JUST USE write()! :)

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

BTW the driver has no .compat_ioctl entry.

Because you didn't need it until now.

ioctl(fd,USBTMC_IOCTL_CLEAR) returns errno = 25 (=ENOTTY) in Linux Kernel 4.15 when running test-raw32 created with
gcc -m32 test-raw.c -o test-raw32
Does it work with other kernel versions?

I have no idea what you are testing here, sorry.

Quoted 9 lines
Quoted 9 lines
Quoted 2 lines

So I wonder how it could work with 32 bit applications on 64 bit systems before submission of our patches. Do I miss something?

You are creating structures that have different sizes on those two different userspaces. Because of that, you would be forced to have a compat layer. The smart thing to do is to design the interface to not have that type of problem at all, don't create new apis that are not just 64-bit sane to start with.

Quoted 6 lines
Quoted 4 lines

Copying memory is fast, really fast, much much faster than sending the data across the USB connection. If you are seeing major problems here, then I would first look at your userspace code, and then see what the kernel code does.

I just do not like to be slower than libusb or other operating systems.

If you do this correctly, your bottleneck will be the USB connection.

thanks,

greg k-h
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html