diff options
Diffstat (limited to 'drivers/net/usb/hso.c')
| -rw-r--r-- | drivers/net/usb/hso.c | 351 | 
1 files changed, 143 insertions, 208 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index be8cc2a8e21..a4272ed62da 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -106,13 +106,6 @@  #define MAX_RX_URBS			2 -static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty) -{ -	if (tty) -		return tty->driver_data; -	return NULL; -} -  /*****************************************************************************/  /* Debugging functions                                                       */  /*****************************************************************************/ @@ -192,7 +185,6 @@ enum rx_ctrl_state{  #define BM_REQUEST_TYPE (0xa1)  #define B_NOTIFICATION  (0x20)  #define W_VALUE         (0x0) -#define W_INDEX         (0x2)  #define W_LENGTH        (0x2)  #define B_OVERRUN       (0x1<<6) @@ -255,9 +247,8 @@ struct hso_serial {  	u8 dtr_state;  	unsigned tx_urb_used:1; +	struct tty_port port;  	/* from usb_serial_port */ -	struct tty_struct *tty; -	int open_count;  	spinlock_t serial_lock;  	int (*write_data) (struct hso_serial *serial); @@ -267,10 +258,8 @@ struct hso_serial {  	 * so as not to drop characters on the floor.  	 */  	int  curr_rx_urb_idx; -	u16  curr_rx_urb_offset;  	u8   rx_urb_filled[MAX_RX_URBS];  	struct tasklet_struct unthrottle_tasklet; -	struct work_struct    retry_unthrottle_workqueue;  };  struct hso_device { @@ -324,7 +313,7 @@ struct hso_device {  /* Prototypes                                                                */  /*****************************************************************************/  /* Serial driver functions */ -static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, +static int hso_serial_tiocmset(struct tty_struct *tty,  			       unsigned int set, unsigned int clear);  static void ctrl_callback(struct urb *urb);  static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial); @@ -958,10 +947,6 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,  				/* Packet is complete. Inject into stack. */  				/* We have IP packet here */  				odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP); -				/* don't check it */ -				odev->skb_rx_buf->ip_summed = -					CHECKSUM_UNNECESSARY; -  				skb_reset_mac_header(odev->skb_rx_buf);  				/* Ship it off to the kernel */ @@ -1001,6 +986,18 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,  	}  } +static void fix_crc_bug(struct urb *urb, __le16 max_packet_size) +{ +	static const u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; +	u32 rest = urb->actual_length % le16_to_cpu(max_packet_size); + +	if (((rest == 5) || (rest == 6)) && +	    !memcmp(((u8 *)urb->transfer_buffer) + urb->actual_length - 4, +		    crc_check, 4)) { +		urb->actual_length -= 4; +	} +} +  /* Moving data from usb to kernel (in interrupt state) */  static void read_bulk_callback(struct urb *urb)  { @@ -1029,17 +1026,8 @@ static void read_bulk_callback(struct urb *urb)  		return;  	} -	if (odev->parent->port_spec & HSO_INFO_CRC_BUG) { -		u32 rest; -		u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; -		rest = urb->actual_length % -			le16_to_cpu(odev->in_endp->wMaxPacketSize); -		if (((rest == 5) || (rest == 6)) && -		    !memcmp(((u8 *) urb->transfer_buffer) + -			    urb->actual_length - 4, crc_check, 4)) { -			urb->actual_length -= 4; -		} -	} +	if (odev->parent->port_spec & HSO_INFO_CRC_BUG) +		fix_crc_bug(urb, odev->in_endp->wMaxPacketSize);  	/* do we even have a packet? */  	if (urb->actual_length) { @@ -1115,8 +1103,7 @@ static void hso_init_termios(struct ktermios *termios)  static void _hso_serial_set_termios(struct tty_struct *tty,  				    struct ktermios *old)  { -	struct hso_serial *serial = get_serial_by_tty(tty); -	struct ktermios *termios; +	struct hso_serial *serial = tty->driver_data;  	if (!serial) {  		printk(KERN_ERR "%s: no tty structures", __func__); @@ -1128,16 +1115,15 @@ static void _hso_serial_set_termios(struct tty_struct *tty,  	/*  	 *	Fix up unsupported bits  	 */ -	termios = tty->termios; -	termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */ +	tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */ -	termios->c_cflag &= +	tty->termios.c_cflag &=  		~(CSIZE		/* no size */  		| PARENB	/* disable parity bit */  		| CBAUD		/* clear current baud rate */  		| CBAUDEX);	/* clear current buad rate */ -	termios->c_cflag |= CS8;	/* character size 8 bits */ +	tty->termios.c_cflag |= CS8;	/* character size 8 bits */  	/* baud rate 115200 */  	tty_encode_baud_rate(tty, 115200, 115200); @@ -1191,7 +1177,7 @@ static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial)  	struct urb *urb;  	urb = serial->rx_urb[0]; -	if (serial->open_count > 0) { +	if (serial->port.count > 0) {  		count = put_rxbuf_data(urb, serial);  		if (count == -1)  			return; @@ -1213,52 +1199,32 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)  	struct hso_serial *serial = urb->context;  	int status = urb->status; +	D4("\n--- Got serial_read_bulk callback %02x ---", status); +  	/* sanity check */  	if (!serial) {  		D1("serial == NULL");  		return; -	} else if (status) { +	} +	if (status) {  		handle_usb_error(status, __func__, serial->parent);  		return;  	} -	D4("\n--- Got serial_read_bulk callback %02x ---", status);  	D1("Actual length = %d\n", urb->actual_length);  	DUMP1(urb->transfer_buffer, urb->actual_length);  	/* Anyone listening? */ -	if (serial->open_count == 0) +	if (serial->port.count == 0)  		return; -	if (status == 0) { -		if (serial->parent->port_spec & HSO_INFO_CRC_BUG) { -			u32 rest; -			u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; -			rest = -			    urb->actual_length % -			    le16_to_cpu(serial->in_endp->wMaxPacketSize); -			if (((rest == 5) || (rest == 6)) && -			    !memcmp(((u8 *) urb->transfer_buffer) + -				    urb->actual_length - 4, crc_check, 4)) { -				urb->actual_length -= 4; -			} -		} -		/* Valid data, handle RX data */ -		spin_lock(&serial->serial_lock); -		serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; -		put_rxbuf_data_and_resubmit_bulk_urb(serial); -		spin_unlock(&serial->serial_lock); -	} else if (status == -ENOENT || status == -ECONNRESET) { -		/* Unlinked - check for throttled port. */ -		D2("Port %d, successfully unlinked urb", serial->minor); -		spin_lock(&serial->serial_lock); -		serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; -		hso_resubmit_rx_bulk_urb(serial, urb); -		spin_unlock(&serial->serial_lock); -	} else { -		D2("Port %d, status = %d for read urb", serial->minor, status); -		return; -	} +	if (serial->parent->port_spec & HSO_INFO_CRC_BUG) +		fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); +	/* Valid data, handle RX data */ +	spin_lock(&serial->serial_lock); +	serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; +	put_rxbuf_data_and_resubmit_bulk_urb(serial); +	spin_unlock(&serial->serial_lock);  }  /* @@ -1279,19 +1245,11 @@ static void hso_unthrottle_tasklet(struct hso_serial *serial)  static	void hso_unthrottle(struct tty_struct *tty)  { -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	tasklet_hi_schedule(&serial->unthrottle_tasklet);  } -static void hso_unthrottle_workfunc(struct work_struct *work) -{ -	struct hso_serial *serial = -	    container_of(work, struct hso_serial, -			 retry_unthrottle_workqueue); -	hso_unthrottle_tasklet(serial); -} -  /* open the requested serial port */  static int hso_serial_open(struct tty_struct *tty, struct file *filp)  { @@ -1315,27 +1273,22 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)  	kref_get(&serial->parent->ref);  	/* setup */ -	spin_lock_irq(&serial->serial_lock);  	tty->driver_data = serial; -	tty_kref_put(serial->tty); -	serial->tty = tty_kref_get(tty); -	spin_unlock_irq(&serial->serial_lock); +	tty_port_tty_set(&serial->port, tty);  	/* check for port already opened, if not set the termios */ -	serial->open_count++; -	if (serial->open_count == 1) { +	serial->port.count++; +	if (serial->port.count == 1) {  		serial->rx_state = RX_IDLE;  		/* Force default termio settings */  		_hso_serial_set_termios(tty, NULL);  		tasklet_init(&serial->unthrottle_tasklet,  			     (void (*)(unsigned long))hso_unthrottle_tasklet,  			     (unsigned long)serial); -		INIT_WORK(&serial->retry_unthrottle_workqueue, -			  hso_unthrottle_workfunc);  		result = hso_start_serial_device(serial->parent, GFP_KERNEL);  		if (result) {  			hso_stop_serial_device(serial->parent); -			serial->open_count--; +			serial->port.count--;  			kref_put(&serial->parent->ref, hso_serial_ref_free);  		}  	} else { @@ -1346,7 +1299,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)  	/* done */  	if (result) -		hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0); +		hso_serial_tiocmset(tty, TIOCM_RTS | TIOCM_DTR, 0);  err_out:  	mutex_unlock(&serial->parent->mutex);  	return result; @@ -1372,21 +1325,14 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)  	/* reset the rts and dtr */  	/* do the actual close */ -	serial->open_count--; +	serial->port.count--; -	if (serial->open_count <= 0) { -		serial->open_count = 0; -		spin_lock_irq(&serial->serial_lock); -		if (serial->tty == tty) { -			serial->tty->driver_data = NULL; -			serial->tty = NULL; -			tty_kref_put(tty); -		} -		spin_unlock_irq(&serial->serial_lock); +	if (serial->port.count <= 0) { +		serial->port.count = 0; +		tty_port_tty_set(&serial->port, NULL);  		if (!usb_gone)  			hso_stop_serial_device(serial->parent);  		tasklet_kill(&serial->unthrottle_tasklet); -		cancel_work_sync(&serial->retry_unthrottle_workqueue);  	}  	if (!usb_gone) @@ -1401,7 +1347,7 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)  static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf,  			    int count)  { -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	int space, tx_bytes;  	unsigned long flags; @@ -1433,7 +1379,7 @@ out:  /* how much room is there for writing */  static int hso_serial_write_room(struct tty_struct *tty)  { -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	int room;  	unsigned long flags; @@ -1448,19 +1394,19 @@ static int hso_serial_write_room(struct tty_struct *tty)  /* setup the term */  static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)  { -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	unsigned long flags;  	if (old)  		D5("Termios called with: cflags new[%d] - old[%d]", -		   tty->termios->c_cflag, old->c_cflag); +		   tty->termios.c_cflag, old->c_cflag);  	/* the actual setup */  	spin_lock_irqsave(&serial->serial_lock, flags); -	if (serial->open_count) +	if (serial->port.count)  		_hso_serial_set_termios(tty, old);  	else -		tty->termios = old; +		tty->termios = *old;  	spin_unlock_irqrestore(&serial->serial_lock, flags);  	/* done */ @@ -1469,7 +1415,7 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)  /* how many characters in the buffer */  static int hso_serial_chars_in_buffer(struct tty_struct *tty)  { -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	int chars;  	unsigned long flags; @@ -1517,6 +1463,7 @@ static void tiocmget_intr_callback(struct urb *urb)  	struct uart_icount *icount;  	struct hso_serial_state_notification *serial_state_notification;  	struct usb_device *usb; +	int if_num;  	/* Sanity checks */  	if (!serial) @@ -1525,15 +1472,24 @@ static void tiocmget_intr_callback(struct urb *urb)  		handle_usb_error(status, __func__, serial->parent);  		return;  	} + +	/* tiocmget is only supported on HSO_PORT_MODEM */  	tiocmget = serial->tiocmget;  	if (!tiocmget)  		return; +	BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM); +  	usb = serial->parent->usb; +	if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber; + +	/* wIndex should be the USB interface number of the port to which the +	 * notification applies, which should always be the Modem port. +	 */  	serial_state_notification = &tiocmget->serial_state_notification;  	if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||  	    serial_state_notification->bNotification != B_NOTIFICATION ||  	    le16_to_cpu(serial_state_notification->wValue) != W_VALUE || -	    le16_to_cpu(serial_state_notification->wIndex) != W_INDEX || +	    le16_to_cpu(serial_state_notification->wIndex) != if_num ||  	    le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {  		dev_warn(&usb->dev,  			 "hso received invalid serial state notification\n"); @@ -1640,10 +1596,10 @@ static int hso_get_count(struct tty_struct *tty,  		  struct serial_icounter_struct *icount)  {  	struct uart_icount cnow; -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	struct hso_tiocmget  *tiocmget = serial->tiocmget; -	memset(&icount, 0, sizeof(struct serial_icounter_struct)); +	memset(icount, 0, sizeof(struct serial_icounter_struct));  	if (!tiocmget)  		 return -ENOENT; @@ -1667,10 +1623,10 @@ static int hso_get_count(struct tty_struct *tty,  } -static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file) +static int hso_serial_tiocmget(struct tty_struct *tty)  {  	int retval; -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	struct hso_tiocmget  *tiocmget;  	u16 UART_state_bitmap; @@ -1698,13 +1654,13 @@ static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file)  	return retval;  } -static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, +static int hso_serial_tiocmset(struct tty_struct *tty,  			       unsigned int set, unsigned int clear)  {  	int val = 0;  	unsigned long flags;  	int if_num; -	struct hso_serial *serial = get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	/* sanity check */  	if (!serial) { @@ -1741,10 +1697,10 @@ static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,  			       USB_CTRL_SET_TIMEOUT);  } -static int hso_serial_ioctl(struct tty_struct *tty, struct file *file, +static int hso_serial_ioctl(struct tty_struct *tty,  			    unsigned int cmd, unsigned long arg)  { -	struct hso_serial *serial =  get_serial_by_tty(tty); +	struct hso_serial *serial = tty->driver_data;  	int ret = 0;  	D4("IOCTL cmd: %d, arg: %ld", cmd, arg); @@ -1916,7 +1872,7 @@ static void intr_callback(struct urb *urb)  				D1("Pending read interrupt on port %d\n", i);  				spin_lock(&serial->serial_lock);  				if (serial->rx_state == RX_IDLE && -					serial->open_count > 0) { +					serial->port.count > 0) {  					/* Setup and send a ctrl req read on  					 * port i */  					if (!serial->rx_urb_filled[0]) { @@ -1955,7 +1911,6 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)  {  	struct hso_serial *serial = urb->context;  	int status = urb->status; -	struct tty_struct *tty;  	/* sanity check */  	if (!serial) { @@ -1965,18 +1920,13 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)  	spin_lock(&serial->serial_lock);  	serial->tx_urb_used = 0; -	tty = tty_kref_get(serial->tty);  	spin_unlock(&serial->serial_lock);  	if (status) {  		handle_usb_error(status, __func__, serial->parent); -		tty_kref_put(tty);  		return;  	}  	hso_put_activity(serial->parent); -	if (tty) { -		tty_wakeup(tty); -		tty_kref_put(tty); -	} +	tty_port_tty_wakeup(&serial->port);  	hso_kick_transmit(serial);  	D1(" "); @@ -2012,7 +1962,6 @@ static void ctrl_callback(struct urb *urb)  	struct hso_serial *serial = urb->context;  	struct usb_ctrlrequest *req;  	int status = urb->status; -	struct tty_struct *tty;  	/* sanity check */  	if (!serial) @@ -2020,11 +1969,9 @@ static void ctrl_callback(struct urb *urb)  	spin_lock(&serial->serial_lock);  	serial->tx_urb_used = 0; -	tty = tty_kref_get(serial->tty);  	spin_unlock(&serial->serial_lock);  	if (status) {  		handle_usb_error(status, __func__, serial->parent); -		tty_kref_put(tty);  		return;  	} @@ -2043,20 +1990,17 @@ static void ctrl_callback(struct urb *urb)  		spin_unlock(&serial->serial_lock);  	} else {  		hso_put_activity(serial->parent); -		if (tty) -			tty_wakeup(tty); +		tty_port_tty_wakeup(&serial->port);  		/* response to a write command */  		hso_kick_transmit(serial);  	} -	tty_kref_put(tty);  }  /* handle RX data for serial port */  static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)  {  	struct tty_struct *tty; -	int write_length_remaining = 0; -	int curr_write_len; +	int count;  	/* Sanity check */  	if (urb == NULL || serial == NULL) { @@ -2064,34 +2008,30 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)  		return -2;  	} -	/* All callers to put_rxbuf_data hold serial_lock */ -	tty = tty_kref_get(serial->tty); +	tty = tty_port_tty_get(&serial->port); -	/* Push data to tty */ -	if (tty) { -		write_length_remaining = urb->actual_length - -			serial->curr_rx_urb_offset; -		D1("data to push to tty"); -		while (write_length_remaining) { -			if (test_bit(TTY_THROTTLED, &tty->flags)) { -				tty_kref_put(tty); -				return -1; -			} -			curr_write_len =  tty_insert_flip_string -				(tty, urb->transfer_buffer + -				 serial->curr_rx_urb_offset, -				 write_length_remaining); -			serial->curr_rx_urb_offset += curr_write_len; -			write_length_remaining -= curr_write_len; -			tty_flip_buffer_push(tty); -		} +	if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { +		tty_kref_put(tty); +		return -1;  	} -	if (write_length_remaining == 0) { -		serial->curr_rx_urb_offset = 0; -		serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; + +	/* Push data to tty */ +	D1("data to push to tty"); +	count = tty_buffer_request_room(&serial->port, urb->actual_length); +	if (count >= urb->actual_length) { +		tty_insert_flip_string(&serial->port, urb->transfer_buffer, +				       urb->actual_length); +		tty_flip_buffer_push(&serial->port); +	} else { +		dev_warn(&serial->parent->usb->dev, +			 "dropping data, %d bytes lost\n", urb->actual_length);  	} +  	tty_kref_put(tty); -	return write_length_remaining; + +	serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; + +	return 0;  } @@ -2262,7 +2202,6 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)  		}  	}  	serial->curr_rx_urb_idx = 0; -	serial->curr_rx_urb_offset = 0;  	if (serial->tx_urb)  		usb_kill_urb(serial->tx_urb); @@ -2307,6 +2246,7 @@ static void hso_serial_common_free(struct hso_serial *serial)  	/* unlink and free TX URB */  	usb_free_urb(serial->tx_urb);  	kfree(serial->tx_data); +	tty_port_destroy(&serial->port);  }  static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, @@ -2316,13 +2256,15 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,  	int minor;  	int i; +	tty_port_init(&serial->port); +  	minor = get_free_serial_index();  	if (minor < 0)  		goto exit;  	/* register our minor number */ -	serial->parent->dev = tty_register_device(tty_drv, minor, -					&serial->parent->interface->dev); +	serial->parent->dev = tty_port_register_device(&serial->port, tty_drv, +			minor, &serial->parent->interface->dev);  	dev = serial->parent->dev;  	dev_set_drvdata(dev, serial->parent);  	i = device_create_file(dev, &dev_attr_hsotype); @@ -2347,10 +2289,8 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,  		serial->rx_urb[i]->transfer_buffer_length = 0;  		serial->rx_data[i] = kzalloc(serial->rx_data_length,  					     GFP_KERNEL); -		if (!serial->rx_data[i]) { -			dev_err(dev, "%s - Out of memory\n", __func__); +		if (!serial->rx_data[i])  			goto exit; -		}  	}  	/* TX, allocate urb and initialize */ @@ -2366,15 +2306,12 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,  	serial->tx_buffer_count = 0;  	serial->tx_data_length = tx_size;  	serial->tx_data = kzalloc(serial->tx_data_length, GFP_KERNEL); -	if (!serial->tx_data) { -		dev_err(dev, "%s - Out of memory\n", __func__); +	if (!serial->tx_data)  		goto exit; -	} +  	serial->tx_buffer = kzalloc(serial->tx_data_length, GFP_KERNEL); -	if (!serial->tx_buffer) { -		dev_err(dev, "%s - Out of memory\n", __func__); +	if (!serial->tx_buffer)  		goto exit; -	}  	return 0;  exit: @@ -2432,10 +2369,8 @@ static void hso_free_net_device(struct hso_device *hso_dev)  	remove_net_device(hso_net->parent); -	if (hso_net->net) { +	if (hso_net->net)  		unregister_netdev(hso_net->net); -		free_netdev(hso_net->net); -	}  	/* start freeing */  	for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { @@ -2447,6 +2382,9 @@ static void hso_free_net_device(struct hso_device *hso_dev)  	kfree(hso_net->mux_bulk_tx_buf);  	hso_net->mux_bulk_tx_buf = NULL; +	if (hso_net->net) +		free_netdev(hso_net->net); +  	kfree(hso_dev);  } @@ -2471,7 +2409,7 @@ static void hso_net_init(struct net_device *net)  	net->type = ARPHRD_NONE;  	net->mtu = DEFAULT_MTU - 14;  	net->tx_queue_len = 10; -	SET_ETHTOOL_OPS(net, &ops); +	net->ethtool_ops = &ops;  	/* and initialize the semaphore */  	spin_lock_init(&hso_net->net_lock); @@ -2609,10 +2547,8 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,  		}  		hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE,  							   GFP_KERNEL); -		if (!hso_net->mux_bulk_rx_buf_pool[i]) { -			dev_err(&interface->dev, "Could not allocate rx buf\n"); +		if (!hso_net->mux_bulk_rx_buf_pool[i])  			goto exit; -		}  	}  	hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (!hso_net->mux_bulk_tx_urb) { @@ -2620,10 +2556,8 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,  		goto exit;  	}  	hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL); -	if (!hso_net->mux_bulk_tx_buf) { -		dev_err(&interface->dev, "Could not allocate tx buf\n"); +	if (!hso_net->mux_bulk_tx_buf)  		goto exit; -	}  	add_net_device(hso_dev); @@ -2639,15 +2573,15 @@ exit:  static void hso_free_tiomget(struct hso_serial *serial)  { -	struct hso_tiocmget *tiocmget = serial->tiocmget; +	struct hso_tiocmget *tiocmget; +	if (!serial) +		return; +	tiocmget = serial->tiocmget;  	if (tiocmget) { -		if (tiocmget->urb) { -			usb_free_urb(tiocmget->urb); -			tiocmget->urb = NULL; -		} +		usb_free_urb(tiocmget->urb); +		tiocmget->urb = NULL;  		serial->tiocmget = NULL;  		kfree(tiocmget); -  	}  } @@ -2847,10 +2781,8 @@ struct hso_shared_int *hso_create_shared_int(struct usb_interface *interface)  	mux->shared_intr_buf =  		kzalloc(le16_to_cpu(mux->intr_endp->wMaxPacketSize),  			GFP_KERNEL); -	if (!mux->shared_intr_buf) { -		dev_err(&interface->dev, "Could not allocate intr buf?\n"); +	if (!mux->shared_intr_buf)  		goto exit; -	}  	mutex_init(&mux->shared_int_lock); @@ -2867,13 +2799,16 @@ exit:  static int hso_get_config_data(struct usb_interface *interface)  {  	struct usb_device *usbdev = interface_to_usbdev(interface); -	u8 config_data[17]; +	u8 *config_data = kmalloc(17, GFP_KERNEL);  	u32 if_num = interface->altsetting->desc.bInterfaceNumber;  	s32 result; +	if (!config_data) +		return -ENOMEM;  	if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),  			    0x86, 0xC0, 0, 0, config_data, 17,  			    USB_CTRL_SET_TIMEOUT) != 0x11) { +		kfree(config_data);  		return -EIO;  	} @@ -2924,6 +2859,7 @@ static int hso_get_config_data(struct usb_interface *interface)  	if (config_data[16] & 0x1)  		result |= HSO_INFO_CRC_BUG; +	kfree(config_data);  	return result;  } @@ -2937,6 +2873,11 @@ static int hso_probe(struct usb_interface *interface,  	struct hso_shared_int *shared_int;  	struct hso_device *tmp_dev = NULL; +	if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { +		dev_err(&interface->dev, "Not our interface\n"); +		return -ENODEV; +	} +  	if_num = interface->altsetting->desc.bInterfaceNumber;  	/* Get the interface/port specification from either driver_info or from @@ -2946,10 +2887,6 @@ static int hso_probe(struct usb_interface *interface,  	else  		port_spec = hso_get_config_data(interface); -	if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) { -		dev_err(&interface->dev, "Not our interface\n"); -		return -ENODEV; -	}  	/* Check if we need to switch to alt interfaces prior to port  	 * configuration */  	if (interface->num_altsetting > 1) @@ -2993,12 +2930,14 @@ static int hso_probe(struct usb_interface *interface,  	case HSO_INTF_BULK:  		/* It's a regular bulk interface */ -		if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) && -		    !disable_net) -			hso_dev = hso_create_net_device(interface, port_spec); -		else +		if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) { +			if (!disable_net) +				hso_dev = +				    hso_create_net_device(interface, port_spec); +		} else {  			hso_dev =  			    hso_create_bulk_serial_device(interface, port_spec); +		}  		if (!hso_dev)  			goto exit;  		break; @@ -3106,7 +3045,7 @@ static int hso_resume(struct usb_interface *iface)  	/* Start all serial ports */  	for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {  		if (serial_table[i] && (serial_table[i]->interface == iface)) { -			if (dev2ser(serial_table[i])->open_count) { +			if (dev2ser(serial_table[i])->port.count) {  				result =  				    hso_start_serial_device(serial_table[i], GFP_NOIO);  				hso_kick_transmit(dev2ser(serial_table[i])); @@ -3173,20 +3112,14 @@ static void hso_serial_ref_free(struct kref *ref)  static void hso_free_interface(struct usb_interface *interface)  {  	struct hso_serial *hso_dev; -	struct tty_struct *tty;  	int i;  	for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {  		if (serial_table[i] &&  		    (serial_table[i]->interface == interface)) {  			hso_dev = dev2ser(serial_table[i]); -			spin_lock_irq(&hso_dev->serial_lock); -			tty = tty_kref_get(hso_dev->tty); -			spin_unlock_irq(&hso_dev->serial_lock); -			if (tty) -				tty_hangup(tty); +			tty_port_tty_hangup(&hso_dev->port, false);  			mutex_lock(&hso_dev->parent->mutex); -			tty_kref_put(tty);  			hso_dev->parent->usb_gone = 1;  			mutex_unlock(&hso_dev->parent->mutex);  			kref_put(&serial_table[i]->ref, hso_serial_ref_free); @@ -3299,6 +3232,7 @@ static struct usb_driver hso_driver = {  	.resume = hso_resume,  	.reset_resume = hso_resume,  	.supports_autosuspend = 1, +	.disable_hub_initiated_lpm = 1,  };  static int __init hso_init(void) @@ -3320,8 +3254,6 @@ static int __init hso_init(void)  		return -ENOMEM;  	/* fill in all needed values */ -	tty_drv->magic = TTY_DRIVER_MAGIC; -	tty_drv->owner = THIS_MODULE;  	tty_drv->driver_name = driver_name;  	tty_drv->name = tty_filename; @@ -3330,7 +3262,6 @@ static int __init hso_init(void)  		tty_drv->major = tty_major;  	tty_drv->minor_start = 0; -	tty_drv->num = HSO_SERIAL_TTY_MINORS;  	tty_drv->type = TTY_DRIVER_TYPE_SERIAL;  	tty_drv->subtype = SERIAL_TYPE_NORMAL;  	tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; @@ -3343,7 +3274,7 @@ static int __init hso_init(void)  	if (result) {  		printk(KERN_ERR "%s - tty_register_driver failed(%d)\n",  			__func__, result); -		return result; +		goto err_free_tty;  	}  	/* register this module as an usb driver */ @@ -3351,13 +3282,16 @@ static int __init hso_init(void)  	if (result) {  		printk(KERN_ERR "Could not register hso driver? error: %d\n",  			result); -		/* cleanup serial interface */ -		tty_unregister_driver(tty_drv); -		return result; +		goto err_unreg_tty;  	}  	/* done */  	return 0; +err_unreg_tty: +	tty_unregister_driver(tty_drv); +err_free_tty: +	put_tty_driver(tty_drv); +	return result;  }  static void __exit hso_exit(void) @@ -3365,6 +3299,7 @@ static void __exit hso_exit(void)  	printk(KERN_INFO "hso: unloaded\n");  	tty_unregister_driver(tty_drv); +	put_tty_driver(tty_drv);  	/* deregister the usb driver */  	usb_deregister(&hso_driver);  }  | 
