Hi Greg,

  I'm trying to write a driver for this specific usb-to-i2c chip
(mcp2221).  It only offers an In and Out Interrupt Endpoint.  To do a
single i2c read I need to:

1. Send a packet saying "I want to read from i2c"
2. Wait for a reply saying 'okay'.
3. Send another packet saying "Please now send me the data that you read"
4. Wait for that reply.

This means a delay of 2x8ms = 16ms  to get a single bit of data.  For
the specific case that I want to use the chip for, this means I'm
reading from my i2c sensor at 62 hz.  I'd really like to do better if
it at all possible.

Any suggestions?

Thanks,

John

On 15 October 2015 at 14:46, Greg KH <gre...@linuxfoundation.org> wrote:
> On Thu, Oct 15, 2015 at 12:05:52PM +0100, John Tapsell wrote:
>> Hi,
>>
>>   I'm working on a linux driver for a usb to i2c chip (the MCP2221).
>> The USB chip is USB 2.0  Full Speed, and the driver that I'm working
>> on is here:
>>
>> http://ww1.microchip.com/downloads/en/DeviceDoc/mcp2221_0_1.tar.gz
>>
>>   The driver uses HID Interrupt for communication, and both the in and
>> out endpoints have a bInterval of 1.
>>
>>   The problem is that the following function (from the above .tar.gz)
>> takes 8ms to complete, when I'm expecting 1 or 2ms maximum. It simply
>> sends a USB packet, then gets the reply.
>>
>>
>> static int mcp2221_ll_cmd(struct i2c_mcp2221 *dev)
>> {
>>        int rv;
>>
>>        /* tell everybody to leave the URB alone */
>>        dev->ongoing_usb_ll_op = 1;
>>
>>        /* submit the interrupt out ep packet */
>>        if (usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL)) {
>>                dev_err(&dev->interface->dev,
>>                                "mcp2221(ll): usb_submit_urb intr out 
>> failed\n");
>>                dev->ongoing_usb_ll_op = 0;
>>                return -EIO;
>>        }
>>
>>        /* wait for its completion */
>>        rv = wait_event_interruptible(dev->usb_urb_completion_wait,
>>                        (!dev->ongoing_usb_ll_op));
>>        if (rv < 0) {
>>                dev_err(&dev->interface->dev, "mcp2221(ll): wait 
>> interrupted\n");
>>                goto ll_exit_clear_flag;
>>        }
>>
>>        /* tell everybody to leave the URB alone */
>>        dev->ongoing_usb_ll_op = 1;
>>
>>        /* submit the interrupt in ep packet */
>>        if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) {
>>                dev_err(&dev->interface->dev, "mcp2221(ll):
>> usb_submit_urb intr in failed\n");
>>                dev->ongoing_usb_ll_op = 0;
>>                return -EIO;
>>        }
>>
>>        /* wait for its completion */
>>        rv = wait_event_interruptible(dev->usb_urb_completion_wait,
>>                        (!dev->ongoing_usb_ll_op));
>>        if (rv < 0) {
>>                dev_err(&dev->interface->dev, "mcp2221(ll): wait 
>> interrupted\n");
>>                goto ll_exit_clear_flag;
>>        }
>>
>> ll_exit_clear_flag:
>>        dev->ongoing_usb_ll_op = 0;
>>        return rv;
>> }
>>
>> (Please let me know what information to provide.  I have oscilloscope
>> outputs, lsusb outputs, more information about mcp2221, etc.  I just
>> didn't want to make this a huge dump of irrelevant information)
>
> I don't see anything wrong here, USB isn't guaranteed to have any
> specific latency, what you are doing here is the worst-possible-case for
> a USB system (i.e. send a packet, wait for it to complete, send another
> one, etc.)  There are lots of ways to get much better throughput if that
> is what you are wanting to do.
>
> In fact, what exactly are you trying to do?
>
> thanks,
>
> greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to