Make sure that needs_remote_wake up is always set when there are open ports. Currently close() would unconditionally set needs_remote_wakeup to 0 even though there might still be open ports. This could lead to blocked input and possibly dropped data on devices that do not support remote wakeup (and which must therefore not be runtime suspended while open). Add an open_ports counter (protected by the susp_lock) and only clear needs_remote_wakeup when the last port is closed. Note that there are currently no multi-port drivers using the usb_wwan implementation. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
70 lines
2.2 KiB
C
70 lines
2.2 KiB
C
/*
|
|
* Definitions for USB serial mobile broadband cards
|
|
*/
|
|
|
|
#ifndef __LINUX_USB_USB_WWAN
|
|
#define __LINUX_USB_USB_WWAN
|
|
|
|
extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
|
|
extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
|
|
extern void usb_wwan_close(struct usb_serial_port *port);
|
|
extern int usb_wwan_port_probe(struct usb_serial_port *port);
|
|
extern int usb_wwan_port_remove(struct usb_serial_port *port);
|
|
extern int usb_wwan_write_room(struct tty_struct *tty);
|
|
extern void usb_wwan_set_termios(struct tty_struct *tty,
|
|
struct usb_serial_port *port,
|
|
struct ktermios *old);
|
|
extern int usb_wwan_tiocmget(struct tty_struct *tty);
|
|
extern int usb_wwan_tiocmset(struct tty_struct *tty,
|
|
unsigned int set, unsigned int clear);
|
|
extern int usb_wwan_ioctl(struct tty_struct *tty,
|
|
unsigned int cmd, unsigned long arg);
|
|
extern int usb_wwan_send_setup(struct usb_serial_port *port);
|
|
extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
|
|
const unsigned char *buf, int count);
|
|
extern int usb_wwan_chars_in_buffer(struct tty_struct *tty);
|
|
#ifdef CONFIG_PM
|
|
extern int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message);
|
|
extern int usb_wwan_resume(struct usb_serial *serial);
|
|
#endif
|
|
|
|
/* per port private data */
|
|
|
|
#define N_IN_URB 4
|
|
#define N_OUT_URB 4
|
|
#define IN_BUFLEN 4096
|
|
#define OUT_BUFLEN 4096
|
|
|
|
struct usb_wwan_intf_private {
|
|
spinlock_t susp_lock;
|
|
unsigned int suspended:1;
|
|
int in_flight;
|
|
unsigned int open_ports;
|
|
int (*send_setup) (struct usb_serial_port *port);
|
|
void *private;
|
|
};
|
|
|
|
struct usb_wwan_port_private {
|
|
/* Input endpoints and buffer for this port */
|
|
struct urb *in_urbs[N_IN_URB];
|
|
u8 *in_buffer[N_IN_URB];
|
|
/* Output endpoints and buffer for this port */
|
|
struct urb *out_urbs[N_OUT_URB];
|
|
u8 *out_buffer[N_OUT_URB];
|
|
unsigned long out_busy; /* Bit vector of URBs in use */
|
|
int opened;
|
|
struct usb_anchor delayed;
|
|
|
|
/* Settings for the port */
|
|
int rts_state; /* Handshaking pins (outputs) */
|
|
int dtr_state;
|
|
int cts_state; /* Handshaking pins (inputs) */
|
|
int dsr_state;
|
|
int dcd_state;
|
|
int ri_state;
|
|
|
|
unsigned long tx_start_time[N_OUT_URB];
|
|
};
|
|
|
|
#endif /* __LINUX_USB_USB_WWAN */
|