diff options
Diffstat (limited to 'drivers/usb/serial/keyspan.c')
| -rw-r--r-- | drivers/usb/serial/keyspan.c | 181 | 
1 files changed, 88 insertions, 93 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d737d..7179b0c5f81 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1374,13 +1374,9 @@ static struct callbacks {  	   data in device_details */  static void keyspan_setup_urbs(struct usb_serial *serial)  { -	int				i, j;  	struct keyspan_serial_private 	*s_priv;  	const struct keyspan_device_details	*d_details; -	struct usb_serial_port		*port; -	struct keyspan_port_private	*p_priv;  	struct callbacks		*cback; -	int				endp;  	s_priv = usb_get_serial_data(serial);  	d_details = s_priv->device_details; @@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)  		(serial, d_details->glocont_endpoint, USB_DIR_OUT,  		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,  		 cback->glocont_callback); - -	/* Setup endpoints for each port specific thing */ -	for (i = 0; i < d_details->num_ports; i++) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); - -		/* Do indat endpoints first, once for each flip */ -		endp = d_details->indat_endpoints[i]; -		for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { -			p_priv->in_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_IN, port, -				 p_priv->in_buffer[j], 64, -				 cback->indat_callback); -		} -		for (; j < 2; ++j) -			p_priv->in_urbs[j] = NULL; - -		/* outdat endpoints also have flip */ -		endp = d_details->outdat_endpoints[i]; -		for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { -			p_priv->out_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_OUT, port, -				 p_priv->out_buffer[j], 64, -				 cback->outdat_callback); -		} -		for (; j < 2; ++j) -			p_priv->out_urbs[j] = NULL; - -		/* inack endpoint */ -		p_priv->inack_urb = keyspan_setup_urb -			(serial, d_details->inack_endpoints[i], USB_DIR_IN, -			 port, p_priv->inack_buffer, 1, cback->inack_callback); - -		/* outcont endpoint */ -		p_priv->outcont_urb = keyspan_setup_urb -			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT, -			 port, p_priv->outcont_buffer, 64, -			 cback->outcont_callback); -	}  }  /* usa19 function doesn't require prescaler */ @@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)  static int keyspan_startup(struct usb_serial *serial)  {  	int				i, err; -	struct usb_serial_port		*port;  	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv;  	const struct keyspan_device_details	*d_details;  	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)  	s_priv->device_details = d_details;  	usb_set_serial_data(serial, s_priv); -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		p_priv = kzalloc(sizeof(struct keyspan_port_private), -								GFP_KERNEL); -		if (!p_priv) { -			dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); -			return 1; -		} -		p_priv->device_details = d_details; -		usb_set_serial_port_data(port, p_priv); -	} -  	keyspan_setup_urbs(serial);  	if (s_priv->instat_urb != NULL) { @@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)  static void keyspan_disconnect(struct usb_serial *serial)  { -	int				i, j; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv; +	struct keyspan_serial_private *s_priv;  	s_priv = usb_get_serial_data(serial); -	/* Stop reading/writing urbs */  	stop_urb(s_priv->instat_urb);  	stop_urb(s_priv->glocont_urb);  	stop_urb(s_priv->indat_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		stop_urb(p_priv->inack_urb); -		stop_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			stop_urb(p_priv->in_urbs[j]); -			stop_urb(p_priv->out_urbs[j]); -		} -	} +} + +static void keyspan_release(struct usb_serial *serial) +{ +	struct keyspan_serial_private *s_priv; + +	s_priv = usb_get_serial_data(serial); -	/* Now free them */  	usb_free_urb(s_priv->instat_urb);  	usb_free_urb(s_priv->indat_urb);  	usb_free_urb(s_priv->glocont_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		usb_free_urb(p_priv->inack_urb); -		usb_free_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			usb_free_urb(p_priv->in_urbs[j]); -			usb_free_urb(p_priv->out_urbs[j]); -		} -	} + +	kfree(s_priv);  } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port)  { -	int				i; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; +	struct usb_serial *serial = port->serial; +	struct keyspan_port_private *s_priv; +	struct keyspan_port_private *p_priv; +	const struct keyspan_device_details *d_details; +	struct callbacks *cback; +	int endp; +	int port_num; +	int i;  	s_priv = usb_get_serial_data(serial); +	d_details = s_priv->device_details; -	kfree(s_priv); +	p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); +	if (!p_priv) +		return -ENOMEM; -	/* Now free per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		kfree(usb_get_serial_port_data(port)); +	s_priv = usb_get_serial_data(port->serial); +	p_priv->device_details = d_details; + +	/* Setup values for the various callback routines */ +	cback = &keyspan_callbacks[d_details->msg_format]; + +	port_num = port->number - port->serial->minor; + +	/* Do indat endpoints first, once for each flip */ +	endp = d_details->indat_endpoints[port_num]; +	for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { +		p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_IN, port, +						p_priv->in_buffer[i], 64, +						cback->indat_callback);  	} +	/* outdat endpoints also have flip */ +	endp = d_details->outdat_endpoints[port_num]; +	for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { +		p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_OUT, port, +						p_priv->out_buffer[i], 64, +						cback->outdat_callback); +	} +	/* inack endpoint */ +	p_priv->inack_urb = keyspan_setup_urb(serial, +					d_details->inack_endpoints[port_num], +					USB_DIR_IN, port, +					p_priv->inack_buffer, 1, +					cback->inack_callback); +	/* outcont endpoint */ +	p_priv->outcont_urb = keyspan_setup_urb(serial, +					d_details->outcont_endpoints[port_num], +					USB_DIR_OUT, port, +					p_priv->outcont_buffer, 64, +					 cback->outcont_callback); + +	usb_set_serial_port_data(port, p_priv); + +	return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ +	struct keyspan_port_private *p_priv; +	int i; + +	p_priv = usb_get_serial_port_data(port); + +	stop_urb(p_priv->inack_urb); +	stop_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		stop_urb(p_priv->in_urbs[i]); +		stop_urb(p_priv->out_urbs[i]); +	} + +	usb_free_urb(p_priv->inack_urb); +	usb_free_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		usb_free_urb(p_priv->in_urbs[i]); +		usb_free_urb(p_priv->out_urbs[i]); +	} + +	kfree(p_priv); + +	return 0;  }  MODULE_AUTHOR(DRIVER_AUTHOR);  |