Problems with ASMedia ASM1042 SuperSpeed USB Host

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I have some problems with an ASM1042 SuperSpeed Host Controller.
(IvyBridge + PantherPoint Motherboard).
I also read some comments that this particular Host Controller might have some problems, but I could
not find any details.

I am running Ubuntu 12.04, 64 bit, with a 3.4 kernel provided by Ubuntu.
"cat /proc/version" :
Linux version 3.4.0-030400-generic  ...

I also tried the stock 3.2.0-26-generic kernel usually provided by Ubuntu 12.04, but the problem is
the same.

Output of "lspci -v"
----------------------------------------------------------------------------
04:00.0 USB controller: ASMedia Technology Inc. ASM1042 SuperSpeed USB Host
Controller (prog-if 30 [XHCI])
	Subsystem: ASUSTeK Computer Inc. Device 8488
	Flags: bus master, fast devsel, latency 0, IRQ 18
	Memory at f7d00000 (64-bit, non-prefetchable) [size=32K]
	Capabilities: [50] MSI: Enable- Count=1/8 Maskable- 64bit+
	Capabilities: [68] MSI-X: Enable+ Count=8 Masked-
	Capabilities: [78] Power Management version 3
	Capabilities: [80] Express Legacy Endpoint, MSI 00
	Capabilities: [100] Virtual Channel
	Kernel driver in use: xhci_hcd
----------------------------------------------------------------------------


I try to read from a USB 3.0 device running at SuperSpeed.
The USB device is an evaluation board for a USB peripheral device
( http://www.plxtech.com/products/usbcontrollers/usb3380 )

I programmed the USB device to send data to the host in 0x2FFE == 12286 byte blocks.

My understanding is that this should result in 12 USB SuperSpeed packets to the host, where the last
packet only contains 0x3FE (==1022) bytes. So the last of these 12 packets should be a short packet
(<1024 bytes).

Now I try to read from this device with the following code:
--------------------------------------------
/*
 * fd                    : file handle to USB device after "claimInterface"
 * rdEp                  : Endpoint to read from
 *
 */
static int usbBulkReadSpeed(int fd, unsigned int rdEp)
{
#	define SPEED_URB_SIZE   (4096*4)
#	define SPEED_URBS       16
#	define SPEED_URBS_TOTAL (8192*4)

	static struct usbdevfs_urb readUrbs[SPEED_URBS];
	int loop,totalLength;
	unsigned char *speedBuf,*speedBufOrig;
	struct usbdevfs_urb *urb;
	struct timeval start,stop;
	struct pollfd pollArray[1];

	speedBuf=malloc(SPEED_URBS*SPEED_URB_SIZE+0x1000);
	speedBufOrig=speedBuf;
	loop=(int)(((intptr_t)speedBuf)&0xFFF);
	if (loop) {
		/* align to 4KB page */
		loop=0x1000-loop;
		speedBuf+=loop;
		loop=(intptr_t)speedBuf;
		printf("aligned transmit buffer to 4KB page, new pointer 0x%08x\n",loop);
	}
	pollArray[0].fd=fd;
	pollArray[0].events = POLLOUT;
	pollArray[0].revents = 0;
	totalLength=0;

	printf("Starting transfer\n");
	gettimeofday(&start,NULL);
	memset(&readUrbs,0,sizeof(readUrbs));
	for (loop=0;loop<SPEED_URBS;loop++) {
		readUrbs[loop].type          = USBDEVFS_URB_TYPE_BULK;
		readUrbs[loop].endpoint      = rdEp;
		readUrbs[loop].buffer        = speedBuf+(SPEED_URB_SIZE*loop);
		readUrbs[loop].buffer_length = SPEED_URB_SIZE;
		if (ioctl(fd,USBDEVFS_SUBMITURB,&(readUrbs[loop]))<0)
		{
			printf("bulk_read_urb, USBDEVFS_SUBMITURB error %d\n",errno);
			goto error;
		}
	}

	loop=0;
	while(loop<SPEED_URBS_TOTAL) {
		poll(pollArray,1,-1);
		if (ioctl(fd,USBDEVFS_REAPURB,&urb) < 0)
		{
			usbLastErrno = errno;
			printf("bulk_read_urb, USBDEVFS_REAPURB error %d %s\n",usbLastErrno,strerror(usbLastErrno));
			goto error;
		}
		if (urb->endpoint == rdEp)
		{
			totalLength+=urb->actual_length;
			// usbCheckReadData((uint32_t *)(urb->buffer),urb->actual_length);

			if (loop < SPEED_URBS_TOTAL-SPEED_URBS) {
				if (ioctl(fd,USBDEVFS_SUBMITURB,urb)<0)
				{
					printf("bulk_read_urb, USBDEVFS_SUBMITURB error %d\n",errno);
					goto error;
				}
			}
			loop++;
		}
	}
	gettimeofday(&stop,NULL);
	printf("Transferred %d bytes\n",totalLength);
	stop.tv_sec-=1;
	stop.tv_usec+=1000000;
	loop=(stop.tv_sec-start.tv_sec);
	loop*=1000;
	loop+=(stop.tv_usec - start.tv_usec)/1000;
	printf("Finished in %d ms\n",loop);
error:
	free(speedBufOrig);
	return -1;
}
-----------------------------------------------------------------

The sense of this code is to achieve maximum speed by overlapping URBs.
Basically 16 URBs are outstanding before the 1st URB is "reaped".

Each URB tries to read up to 0x4000 bytes from Endpoint 0x85.
The device should send 0x2FFE bytes.
My assumption was, that every 12th packet only contains 0x3FE bytes and thus stops the currently
active URB.

It seems the ASM1042 sometimes does not stop the transfer after receiving a short packet, or at
least the URB continues (stopping after 16KByte).

QUESTION: Is this a known problem or am I doing something wrong ?

The same code DOES work if I connect my USB device to the Panther Point USB 3.0 port. "lspci -v":

00:14.0 USB controller: Intel Corporation Panther Point USB xHCI Host
Controller (rev 04) (prog-if 30 [XHCI])
	Subsystem: ASUSTeK Computer Inc. Device 84ca
	Flags: bus master, medium devsel, latency 0, IRQ 45
	Memory at f7e00000 (64-bit, non-prefetchable) [size=64K]
	Capabilities: [70] Power Management version 2
	Capabilities: [80] MSI: Enable+ Count=1/8 Maskable- 64bit+
	Kernel driver in use: xhci_hcd

It also works on a NEC USB 3.0 HostController PCI Express card I tried before.

Any hints what is wrong ?

with best regards
  Ingo

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux