Re: [V2 PATCH 01/10] added media agnostic (MA) USB HCD driver

2014-11-14 Thread Sean O. Stalley
On Wed, Nov 12, 2014 at 05:03:18PM -0500, Alan Stern wrote:
 On Wed, 12 Nov 2014, Sean O. Stalley wrote:
  Our plan to support multiple MA devices is to have them all connected
  to the same virtual host controller, so only 1 would be needed.
  
  Would you prefer we have 1 host controller instance per MA device?
  We are definitely open to suggestions on how this should be architected.
 
 I haven't read the MA USB spec, so I don't know how it's intended to 
 work.  Still, what happens if you create a virtual host controller 
 with, say, 16 ports, and then someone wants to connect a 17th MA 
 device?

To summarize the spec:
MA USB groups a host  connected devices into MA service sets (MSS).
The architectural limit is 254 MA devices per MSS.

If the host needs to connect more devices than that, It can start a
new MSS and connect to 254 more MA devices.



Is supporting up to 254 devices on one machine sufficient?

Would it make sense (and does the usb stack support) having 254 root
ports on one host controller? If so, we could make our host
controller instance have 254 ports. I'm guessing the hub driver may have
a problem with this (especially for superspeed).

If that doesn't make sense (or isn't supported), we can have 1 host
controller instance per MA device. Would that be preferred?

 Also, I noticed that your patch adds a new bus type for these MA host 
 controllers.  It really seems like overkill to have a whole new bus 
 type if there's only going to be one device on it.

The bus was added when we were quickly trying to replace the platform
device code. It's probably not the right thing to do.

I'm still not sure why we can't make our hcd a platform device,
especially since dummy_hcd  the usbip's hcd are both platform devices.

  If we get rid of these locks, endpoints can't run simultaneously.
  MA USB IN endpoints have to copy data, which could take a while.
 
 I don't know what you mean by run simultaneously.  Certainly multiple 
 network packets can be transmitted and received concurrently even if 
 you use a single spinlock, since your locking won't affect the 
 networking subsystem.

I meant we couldn't have 2 threads in our driver. With one lock,
One thread would always have to wait for the other, even though
they could be working on 2 different endpoints doing completely
independent tasks.

  Couldn't this cause a bottleneck?
 
 Probably not enough to matter.  After all, the other host controller
 drivers rely on a single spinlock.  And if it did matter, you could
 drop the spinlock while copying the data.

Good point. We can cut our driver down to using 1 lock. If we find that
only having 1 spinlock does cause a bottleneck, we can deal with it then.


Thanks,
Sean
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [V2 PATCH 02/10] added media agnostic (MA) USB HCD roothubs

2014-11-12 Thread Sean O. Stalley
Thank you for your review. My responses are inline.

Greg has requested that we clean up the driver internally before
we resubmit another patchset to the mailing list. I will make
sure the changes you requested make it in, but it may be a while
before you see a patchset with the fixes included.

Thanks,
Sean O. Stalley

On Wed, Nov 12, 2014 at 09:35:42AM +0100, Oliver Neukum wrote:
 On Mon, 2014-11-10 at 18:09 -0800, Stephanie Wallick wrote:
  diff --git a/drivers/staging/mausb/drivers/mausb_hub.c 
  b/drivers/staging/mausb/drivers/mausb_hub.c
  new file mode 100644
  index 000..63c0fe4
  --- /dev/null
  +++ b/drivers/staging/mausb/drivers/mausb_hub.c
 
  +/**
  + * Returns true if the given is the superspeed HCD. Note: The primary HCD 
  is
  + * High Speed and the shared HCD is SuperSpeed.
  + */
 
 Why in that order?
 

We should probably switch this  make the superspeed hub primary.
That way we match the xhci driver.

  +bool mausb_is_ss_hcd(struct usb_hcd *hcd)
  +{
  +   if (usb_hcd_is_primary_hcd(hcd))
  +   return false;
  +   else
  +   return true;
  +}
 
 
 
  +
  +/**
  + * Called by usb core when polling for a port status change.
  + *
  + * @hcd:   USB HCD being polled.
  + * @buf:   Holds port status changes (if any).
  + *
  + * Returns zero if there is no status change, otherwise returns number of
  + * bytes in buf. When there is a status change on a port, the bit indexed
  + * at the port number + 1 (e.g. bit 2 for port 1) is set in the buffer.
  + */
  +int mausb_hub_status_data(struct usb_hcd *hcd, char *buf)
  +{
  +   int  i;
  +   u16  port_change = 0;
  +   u32  status = 0;
  +   int  ret = 1;
  +   struct mausb_hcd *mhcd = usb_hcd_to_mausb_hcd(hcd);
  +   struct mausb_root_hub*roothub = usb_hcd_to_roothub(hcd);
  +
  +   /*
  +* Buf should never be more that 2 bytes. USB 3.0 hubs cannot have
  +* more than 15 downstream ports.
  +*/
  +   buf[0] = 0;
  +   if (MAUSB_ROOTHUB_NUM_PORTS  7) {
  +   buf[1] = 0;
  +   ret++;
  +   }
 
 Endianness bug.
 

Could you elaborate?
It was my understanding that this buffer was host-endian.
Is this an unacceptable way to clear the buffer?

  +
  +   for (i = 0; i  MAUSB_ROOTHUB_NUM_PORTS; i++) {
  +   port_change = roothub-port_status[i].wPortChange;
  +   if (port_change)
  +   status |= (1  (i + 1));
  +   }
  +
  +   mausb_dbg(mhcd, %s: hub status is 0x%x\n, __func__, status);
  +
  +   /* hcd might be suspended, resume if there is a status change */
  +   if (mhcd-disabled == 0) {
  +   if ((hcd-state == HC_STATE_SUSPENDED)  status)
  +   usb_hcd_resume_root_hub(hcd);
  +   }
  +
  +   memcpy(buf, (char *)status, ret);
  +
  +   return status ? ret : 0;
  +}
  +
  +/**
  + * Sets the bitfields in the hub descriptor of the 2.0 root hub. Always
  + * returns zero.
  + */
  +int mausb_set_hub_descriptor(struct usb_hub_descriptor *hub_des)
  +{
  +   /* set the values to the default */
  +   hub_des-bDescLength  = sizeof(struct usb_hub_descriptor);
  +   hub_des-bDescriptorType  = USB_DT_HUB;
  +   hub_des-bNbrPorts= MAUSB_ROOTHUB_NUM_PORTS;
  +   hub_des-wHubCharacteristics  = MAUSB_ROOTHUB_CHAR;
  +   hub_des-bPwrOn2PwrGood   = MAUSB_ROOTHUB_PWR_ON_2_PWR_GOOD;
  +   hub_des-bHubContrCurrent = MAUSB_ROOTHUB_CONTR_CURRENT;
 
 Is that descriptor in bus or host endianness?
 

All of the fields are little-endian. We should be using cpu_to_le16()
when setting wHubCharacteristics.

  +
  +   return 0;
  +}
  +
  +/**
  + * Sets the bitfields in the hub descriptor of the 3.0 root hub. Always
  + * returns zero.
 
 Then why return anything?
 

Good point. I will change this (and mausb_set_hub_descriptor()) to be void.

  + */
  +int mausb_set_ss_hub_descriptor(struct usb_hub_descriptor *hub_des)
  +{
  +   /* set the values to the default */
  +   hub_des-bDescLength  = sizeof(struct usb_hub_descriptor);
  +   hub_des-bDescriptorType  = USB_DT_SS_HUB;
  +   hub_des-bNbrPorts= MAUSB_ROOTHUB_NUM_PORTS;
  +   hub_des-wHubCharacteristics  = MAUSB_ROOTHUB_CHAR;
  +   hub_des-bPwrOn2PwrGood   = MAUSB_ROOTHUB_PWR_ON_2_PWR_GOOD;
  +   hub_des-bHubContrCurrent = MAUSB_ROOTHUB_CONTR_CURRENT;
  +
  +   /* USB3-specific parameters */
  +   hub_des-u.ss.bHubHdrDecLat   = MAUSB_ROOTHUB_HDR_DEC_LAT;
  +   hub_des-u.ss.wHubDelay   = MAUSB_ROOTHUB_DELAY;
  +   hub_des-u.ss.DeviceRemovable = MAUSB_ALL_DEV_REMOVABLE;
  +
  +   return 0;
  +}
 
 
  +/**
  + * Contains all the structures required to emulate a root hub. One instance
  + * exists per root hub.
  + */
  +struct __attribute__((__packed__)) mausb_root_hub {
 
 Why __packed__ ?

Doesn't need to be. I will remove.

  +
  +   /* hub parameters */
  +   struct usb_hub_descriptor descriptor;
  +   struct usb_hub_status status;
  +
  +   /* port

Re: [PATCH 05/10] added media specific (MS) TCP drivers

2014-11-12 Thread Sean O. Stalley
Thank You for reviewing our code.

I believe most of the problems you pointed out in mausb_ioctl.c
were addressed in [V2 PATCH 5/10]. I am working on adding the proper
error checking to the TCP drivers.

Greg has requested that we clean up our code internally before
submitting another patchset to the mailing list. I will make sure
we fix the problems you pointed out, but it may be a while before
you see another patchset.

Thanks,
Sean

On Tue, Nov 04, 2014 at 09:48:33AM +0100, Tobias Klauser wrote:
 On 2014-11-03 at 21:42:52 +0100, Stephanie Wallick 
 stephanie.s.wall...@intel.com wrote:
  This is where we handle media specific packets and transport. The MS driver
  interfaces with a media agnostic (MA) driver via a series of transfer pairs.
  Transfer pairs consist of a set of functions to pass MA USB packets back
  and forth between MA and MS drivers. There is one transfer pair per device
  endpoint and one transfer pair for control/management traffic. When the MA
  driver needs to send an MA USB packet, it hands the packet off to the MS
  layer where the packet is converted into an MS form and sent via TCP over
  the underlying ethernet or wireless medium. When the MS driver receives a
  packet, it converts it into an MA USB packet and hands it off the the MA
  driver for handling.
  
  In addition, the MS driver provides an interface to inititate connection 
  events.
  Because there are no physical MA USB ports in an MA USB host, the host must 
  be
  notified via software when a device is connected.
  
  Lastly, the MS driver contains a number of ioctl functions that are used by 
  a
  utility to adjust medium-related driver parameters and connect or 
  disconnect the
  MA USB host and device drivers.
  
  Signed-off-by: Sean O. Stalley sean.stal...@intel.com
  Signed-off-by: Stephanie Wallick stephanie.s.wall...@intel.com
  ---
   drivers/staging/mausb/drivers/mausb_ioctl.c  | 373 +++
   drivers/staging/mausb/drivers/mausb_ioctl.h  |  99 +
   drivers/staging/mausb/drivers/mausb_msapi.c  | 110 ++
   drivers/staging/mausb/drivers/mausb_msapi.h  | 232 
   drivers/staging/mausb/drivers/mausb_tcp-device.c | 147 
   drivers/staging/mausb/drivers/mausb_tcp-host.c   | 144 
   drivers/staging/mausb/drivers/mausb_tcp.c| 446 
  +++
   drivers/staging/mausb/drivers/mausb_tcp.h| 129 +++
   8 files changed, 1680 insertions(+)
   create mode 100644 drivers/staging/mausb/drivers/mausb_ioctl.c
   create mode 100644 drivers/staging/mausb/drivers/mausb_ioctl.h
   create mode 100644 drivers/staging/mausb/drivers/mausb_msapi.c
   create mode 100644 drivers/staging/mausb/drivers/mausb_msapi.h
   create mode 100644 drivers/staging/mausb/drivers/mausb_tcp-device.c
   create mode 100644 drivers/staging/mausb/drivers/mausb_tcp-host.c
   create mode 100644 drivers/staging/mausb/drivers/mausb_tcp.c
   create mode 100644 drivers/staging/mausb/drivers/mausb_tcp.h
  
  diff --git a/drivers/staging/mausb/drivers/mausb_ioctl.c 
  b/drivers/staging/mausb/drivers/mausb_ioctl.c
  new file mode 100644
  index 000..0c6c6bd
  --- /dev/null
  +++ b/drivers/staging/mausb/drivers/mausb_ioctl.c
 
 [...]
 
  +/**
  + * This function is used to send a message to the user, in other words, the
  + * calling process. It basically copies the message one byte at a time.
  + *
  + * @msg:   The message to be sent to the user.
  + * @buffer:The buffer in which to put the message. This buffer was 
  given to
  + * us to fill.
  + */
  +void to_user(char *msg, long unsigned int buffer)
  +{
  +   int length = (int)strlen(msg);
  +   int bytes = 0;
  +
  +   while (length  *msg) {
  +   put_user(*(msg++), (char *)buffer++);
  +   length--;
  +   bytes++;
  +   }
 
 Any reason not to use copy_to_user here? That way, access_ok would only
 need to be executed once for the whole range.
 
 In any case, the return value of put_user/copy_to_user will need to be
 checked.
 
  +
  +   put_user('\0', (char *)buffer + bytes);
  +}
 
 [...]
 
  +/**
  + * This function is used to read from the device file. From the 
  perspective of
  + * the device, the user is reading information from us. This is one of the
  + * entry points to this module.
  + *
  + * @file:  The device file. We don't use it directly, but it's passed in.
  + * @buffer:The buffer to put the message into.
  + * @length:The max length to be read.
  + * @offset:File offset, which we don't use but it is passed in 
  nontheless.
  + */
  +static ssize_t mausb_read(struct file *file, char __user *buffer,
  +   size_t length, loff_t *offset)
  +{
  +   int bytes_read = 0;
  +
  +   if (*message_point == 0)
  +   return 0;
  +   while (length  *message_point) {
  +   put_user(*(message_point++), buffer++);
  +   length--;
  +   bytes_read++;
  +   }
 
 See comment for to_user above. Why

Re: [V2 PATCH 01/10] added media agnostic (MA) USB HCD driver

2014-11-12 Thread Sean O. Stalley
Thanks for reviewing. My responses are inline.

Greg has asked that we clean up this code internally before we
send out another patchset to the mailing list. I will address
the issues you pointed out, but it may be a while before you see
another patchset.

Thanks Again,
Sean

On Tue, Nov 11, 2014 at 10:54:30AM -0500, Alan Stern wrote:
 On Mon, 10 Nov 2014, Stephanie Wallick wrote:
 
  +static struct mausb_hcd mhcd;
 
 Only one statically-allocated structure?  What if somebody wants to 
 have more than one of these things in their system?
 

Our plan to support multiple MA devices is to have them all connected
to the same virtual host controller, so only 1 would be needed.

Would you prefer we have 1 host controller instance per MA device?
We are definitely open to suggestions on how this should be architected.

  +/**
  + * @maurb: Media agnostic structure with URB to release.
  + * @status:Status for URB that is getting released.
  + *
  + * Removes an URB from the queue, deletes the media agnostic information in
  + * the urb, and gives the URB back to the HCD. Caller must be holding the
  + * driver's spinlock.
  + */
  +void mausb_unlink_giveback_urb(struct mausb_urb *maurb, int status)
  +{
  +   struct urb  *urb;
  +   struct usb_hcd  *hcd;
  +   struct api_context  *ctx = NULL;
  +   unsigned long   irq_flags;
  +
  +   hcd = mausb_hcd_to_usb_hcd(mhcd);
  +
  +   spin_lock_irqsave(mhcd.giveback_lock, irq_flags);
 
 Why do you need multiple spinlocks?  Isn't one lock sufficient?
 
We will simplify the locking scheme before resubmitting.

I think it might be worthwhile to have a per-endpoint lock, see below.

  +   if (!maurb) {
  +   mausb_err(mhcd, %s: no maurb\n, __func__);
  +   spin_unlock_irqrestore(mhcd.giveback_lock, irq_flags);
  +   return;
  +   } else {
  +   urb = maurb-urb;
  +   ctx = urb-context;
  +   }
  +
  +   if (!urb) {
  +   mausb_err(mhcd, %s: no urb\n, __func__);
  +   mausb_internal_drop_maurb(maurb, mhcd);
  +   spin_unlock_irqrestore(mhcd.giveback_lock, irq_flags);
  +   return;
  +   }
  +
  +   mausb_dbg(mhcd, %s: returning urb with status %i\n, __func__, 
  status);
  +
  +   usb_hcd_unlink_urb_from_ep(hcd, urb);
  +   usb_hcd_giveback_urb(hcd, urb, status);
 
 You must not call this function while holding any spinlocks.  What happens
 if the URB's completion routine tries to resubmit?
 

This works with our multi-lock scheme, but I will fix when we move to 1 lock.

  +
  +   /* remove the mausb-specific data */
  +   mausb_internal_drop_maurb(maurb, mhcd);
  +
  +   spin_unlock_irqrestore(mhcd.giveback_lock, irq_flags);
  +}
  +
  +/**
  + * Adds an URB to the endpoint queue then calls the URB handler. URB is 
  wrapped
  + * in media agnostic structure before being enqueued.
  + */
  +static int mausb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
  +   gfp_t memflags)
  +{
  +   int ret = 0;
  +   struct mausb_urb*maurb;
  +   struct mausb_host_ep*ep;
  +   unsigned long   irq_flags;
  +
  +   if (!hcd || !urb) {
  +   pr_err(%s: no %s\n, __func__, (hcd ? urb : USB hcd));
  +   }
 
 This can never happen.  The USB core guarantees it; you don't need 
 to check.
 

I will remove this check (along with any other unnecessary checks for things
guaranteed from usbcore).

  +   ep   = usb_to_ma_endpoint(urb-ep);
  +
  +   if (!ep) {
  +   mausb_err(mhcd, %s: no endpoint\n, __func__);
  +   return -EINVAL;
  +   }
  +
  +   if (urb-status != -EINPROGRESS) {
  +   mausb_err(mhcd, %s: urb already unlinked, status is %i\n,
  +   __func__, urb-status);
  +   return urb-status;
  +   }
 
 You also don't need to check this.
 
Will remove.

  +   /* If the endpoint isn't activated, we can't enqueue anything. */
  +   if (MAUSB_EP_HANDLE_UNASSIGNED == ep-ep_handle_state) {
  +   mausb_err(mhcd, %s: endpoint handle unassigned\n, __func__);
  +   return -EPIPE;
  +   }
  +
  +   if (USB_SPEED_FULL != urb-dev-speed) /* suppress checks */
  +   ep-max_pkt = usb_endpoint_maxp(urb-ep-desc);
 
 What happens to full-speed devices?  Don't they have maxpacket values?
 
  +
  +   /* initialize the maurb */
  +   maurb = mausb_alloc_maurb(ep, memflags);
  +   if (!maurb) {
  +   mausb_err(mhcd, could not allocate memory for MA USB urb\n);
  +   return -ENOMEM;
  +   }
  +
  +   /* set maurb member values */
  +   maurb-urb = urb;
  +   urb-hcpriv = maurb;
  +
  +   /* submit urb to hcd and add to endpoint queue */
  +   ret = usb_hcd_link_urb_to_ep(hcd, urb);
 
 Read the kerneldoc for this function.  You must hold your private
 spinlock when you call it.
 

Will fix this  make sure we hold our lock.

  +   if (ret  0) {
  +   mausb_err(mhcd, urb enqueue failed: error %d\n, ret);
  +   usb_hcd_unlink_urb_from_ep(hcd, urb);
  

Re: [V2 PATCH 03/10] added media agnostic (MA) data structures and handling

2014-11-11 Thread Sean O. Stalley
On Tue, Nov 11, 2014 at 01:38:21PM +0900, Greg KH wrote:
 On Mon, Nov 10, 2014 at 06:09:34PM -0800, Stephanie Wallick wrote:
 Intel has a whole group of very experienced Linux kernel developers who
 will review code before you sent it out publicly.  Please take advantage
 of them and run this all through them before resending this out again.
 
 If you did run this code through that group, please let me know who it
 was specifically that allowed this stuff to get through, and why they
 didn't want their name on this code submission.  I need to have a strong
 word with them...

We submitted the patches for internal review and got no objections to
release. We will be more aggressive in seeking out feedback (and approval)
before resubmitting any code.
 
 Yes, I am holding you to a higher standard than staging code normally
 is, and yes, it is purely because of the company you work for.  But I
 only do that because your company knows how to do this stuff right, and
 you have access to the resources and talent to help make this code
 right.  Other people and companies do not have the kind of advantage
 that you do.

We know we are fortunate to work for a company with so much talent and
resources and we don't mind being held to a higher standard. We have been
receiving multiple requests for our host driver and wanted to make it
available as soon as possible for others to use. We thought putting our
host driver into staging would be a good way to release it, but realize now
that it was premature. 

 Wasting community member's time (i.e. mine) by forcing _them_ to review
 stuff like this, is something that your company knows better than to do,
 as should you as well.
 
 I want to see some more senior Intel kernel developer's signed-off-by
 lines on this code before I will ever consider accepting it for the
 kernel.  Please do not resend this code until that happens.
 
 greg k-h

We apologize for wasting everyone's time and will certainly learn from this.
We won't resubmit the driver until a senior kernel developer has signed off on 
it.

Sincerely,
Sean O. Stalley
Stephanie S. Wallick
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel