Re: [rfc patch 2/3] usb: gadget: u_serial: introduce gserial_start

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

 



On Monday 27 July 2009, Felipe Balbi wrote:
> this will prevent a possible problem where
> we will never connect to usb bus.

What problem is that?

NAK due to the obvious locking bug ...


> Cc: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx>
> Cc: Greg Kroah-Hartman <gregkh@xxxxxxx>
> Cc: Bryan Wu <cooloney@xxxxxxxxxx>
> Cc: Robert Jarzmik <robert.jarzmik@xxxxxxx>
> Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx>
> ---
>  drivers/usb/gadget/f_obex.c   |    1 +
>  drivers/usb/gadget/u_serial.c |   48 ++++++++++++++++++++++++++++++----------
>  drivers/usb/gadget/u_serial.h |    1 +
>  3 files changed, 38 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
> index 46d6266..1738e36 100644
> --- a/drivers/usb/gadget/f_obex.c
> +++ b/drivers/usb/gadget/f_obex.c
> @@ -387,6 +387,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
>  			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
>  			obex->port.in->name, obex->port.out->name);
>  
> +	gserial_start(&obex->port, obex->port_num);
>  	return 0;
>  
>  fail:
> diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
> index fc6e709..ab01440 100644
> --- a/drivers/usb/gadget/u_serial.c
> +++ b/drivers/usb/gadget/u_serial.c
> @@ -1201,6 +1201,42 @@ void gserial_cleanup(void)
>  }
>  
>  /**
> + * gserial_start - starts gserial
> + * @gser: the function to be started
> + * @port_num: which port to start
> + * Context: any (usually called from ->bind())
> + *
> + * This should be called in early stage (usualy bind())
> + * in order to let the gaget driver connect to the bus
> + * and let the gser->connect() be called.

I don't follow.  What's the problem with just
having the function call gser_connect() when it's
activated?  Why should there be any bind-time hook
beyond a single call to gserial_setup()?


> + */
> +void gserial_start(struct gserial *gser, u8 port_num)
> +{
> +	struct gs_port	*port;
> +	unsigned long	flags;
> +	int		status;
> +
> +	if (!gs_tty_driver || port_num >= n_ports)
> +		return;
> +
> +	/* we "know" gserial_cleanup() hasn't been called */
> +	port = ports[port_num].port;
> +
> +	/* then tell the tty glue that I/O can work */
> +	spin_lock_irqsave(&port->port_lock, flags);
> +	gser->ioport = port;
> +	port->port_usb = gser;
> +
> +	/* REVISIT unclear how best to handle this state...
> +	 * we don't really couple it with the Linux TTY.
> +	 */
> +	gser->port_line_coding = port->port_line_coding;
> +
> +	/* REVISIT if waiting on "carrier detect", signal. */
> +	spin_unlock_irqrestore(&port->port_lock, flags);
> +}
> +
> +/**
>   * gserial_connect - notify TTY I/O glue that USB link is active
>   * @gser: the function, set up with endpoints and descriptors
>   * @port_num: which port is active
> @@ -1244,18 +1280,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
>  		goto fail_out;
>  	gser->out->driver_data = port;
>  
> -	/* then tell the tty glue that I/O can work */
> -	spin_lock_irqsave(&port->port_lock, flags);

.... the tty layer locking is a bit delicate and non-obvious
(though one hopes Alan's work has cleaned it up).

However, *NO* software will be happy with breaking basic
locking rules like this.  Observe:  you remove the lock,
leave sensitive code which relies on being locked in order
to guarantee correctness, then later you release a *lock
that you do not hold* ...


> -	gser->ioport = port;
> -	port->port_usb = gser;
> -

So you somehow want to couple the /dev/ttyGS* port
to a given function before that's even activated?

How's that supposed to work ... given that the same
port may need to be coupled to a *DIFFERENT* function
when another configuration is active?  (Maybe using
a CDC veneer in one case, proprietary in another.)


> -	/* REVISIT unclear how best to handle this state...
> -	 * we don't really couple it with the Linux TTY.
> -	 */
> -	gser->port_line_coding = port->port_line_coding;
> -
> -	/* REVISIT if waiting on "carrier detect", signal. */
> -
>  	/* if it's already open, start I/O ... and notify the serial
>  	 * protocol about open/close status (connect/disconnect).
>  	 */
> diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
> index 300f0ed..b4c791a 100644
> --- a/drivers/usb/gadget/u_serial.h
> +++ b/drivers/usb/gadget/u_serial.h
> @@ -56,6 +56,7 @@ int gserial_setup(struct usb_gadget *g, unsigned n_ports);
>  void gserial_cleanup(void);
>  
>  /* connect/disconnect is handled by individual functions */
> +void gserial_start(struct gserial *, u8 port_num);
>  int gserial_connect(struct gserial *, u8 port_num);
>  void gserial_disconnect(struct gserial *);
>  
> -- 
> 1.6.3.3.385.g60647
> 
> 



--
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