forked from Minki/linux
USB: ftdi_sio: use port_probe / port_remove thereby fixing access to the latency_timer
Convert all the port specific code in attach / shutdown to use the new port_probe / port_register callbacks from device_register / device_unregister allowing adding the sysfs attributes to be added at the correct time and to the serial port device itself, instead of to the unadorned usb device, avoiding a NULL dereference. Signed-off-by: Jim Radford <radford@blackbean.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
d9a7ecacac
commit
12bdbe03c8
@ -597,6 +597,8 @@ struct ftdi_private {
|
||||
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
|
||||
static int ftdi_sio_attach (struct usb_serial *serial);
|
||||
static void ftdi_shutdown (struct usb_serial *serial);
|
||||
static int ftdi_sio_port_probe (struct usb_serial_port *port);
|
||||
static int ftdi_sio_port_remove (struct usb_serial_port *port);
|
||||
static int ftdi_open (struct usb_serial_port *port, struct file *filp);
|
||||
static void ftdi_close (struct usb_serial_port *port, struct file *filp);
|
||||
static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||
@ -631,6 +633,8 @@ static struct usb_serial_driver ftdi_sio_device = {
|
||||
.num_bulk_out = 1,
|
||||
.num_ports = 1,
|
||||
.probe = ftdi_sio_probe,
|
||||
.port_probe = ftdi_sio_port_probe,
|
||||
.port_remove = ftdi_sio_port_remove,
|
||||
.open = ftdi_open,
|
||||
.close = ftdi_close,
|
||||
.throttle = ftdi_throttle,
|
||||
@ -1033,11 +1037,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
|
||||
{
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct usb_device *udev;
|
||||
struct usb_device *udev = port->serial->dev;
|
||||
unsigned short latency = 0;
|
||||
int rv = 0;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
|
||||
dbg("%s",__FUNCTION__);
|
||||
|
||||
@ -1061,13 +1064,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
|
||||
{
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct usb_device *udev;
|
||||
struct usb_device *udev = port->serial->dev;
|
||||
char buf[1];
|
||||
int v = simple_strtoul(valbuf, NULL, 10);
|
||||
int rv = 0;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
|
||||
dbg("%s: setting latency timer = %i", __FUNCTION__, v);
|
||||
|
||||
rv = usb_control_msg(udev,
|
||||
@ -1092,13 +1093,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
|
||||
{
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct usb_device *udev;
|
||||
struct usb_device *udev = port->serial->dev;
|
||||
char buf[1];
|
||||
int v = simple_strtoul(valbuf, NULL, 10);
|
||||
int rv = 0;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
|
||||
dbg("%s: setting event char = %i", __FUNCTION__, v);
|
||||
|
||||
rv = usb_control_msg(udev,
|
||||
@ -1119,46 +1118,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
|
||||
static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
|
||||
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
|
||||
|
||||
static int create_sysfs_attrs(struct usb_serial *serial)
|
||||
static int create_sysfs_attrs(struct usb_serial_port *port)
|
||||
{
|
||||
struct ftdi_private *priv;
|
||||
struct usb_device *udev;
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
int retval = 0;
|
||||
|
||||
dbg("%s",__FUNCTION__);
|
||||
|
||||
priv = usb_get_serial_port_data(serial->port[0]);
|
||||
udev = serial->dev;
|
||||
|
||||
/* XXX I've no idea if the original SIO supports the event_char
|
||||
* sysfs parameter, so I'm playing it safe. */
|
||||
if (priv->chip_type != SIO) {
|
||||
dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
|
||||
retval = device_create_file(&udev->dev, &dev_attr_event_char);
|
||||
retval = device_create_file(&port->dev, &dev_attr_event_char);
|
||||
if ((!retval) &&
|
||||
(priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
|
||||
retval = device_create_file(&udev->dev,
|
||||
retval = device_create_file(&port->dev,
|
||||
&dev_attr_latency_timer);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void remove_sysfs_attrs(struct usb_serial *serial)
|
||||
static void remove_sysfs_attrs(struct usb_serial_port *port)
|
||||
{
|
||||
struct ftdi_private *priv;
|
||||
struct usb_device *udev;
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
|
||||
dbg("%s",__FUNCTION__);
|
||||
|
||||
priv = usb_get_serial_port_data(serial->port[0]);
|
||||
udev = serial->dev;
|
||||
|
||||
/* XXX see create_sysfs_attrs */
|
||||
if (priv->chip_type != SIO) {
|
||||
device_remove_file(&udev->dev, &dev_attr_event_char);
|
||||
device_remove_file(&port->dev, &dev_attr_event_char);
|
||||
if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
|
||||
device_remove_file(&udev->dev, &dev_attr_latency_timer);
|
||||
device_remove_file(&port->dev, &dev_attr_latency_timer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1178,13 +1169,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* attach subroutine */
|
||||
static int ftdi_sio_attach (struct usb_serial *serial)
|
||||
static int ftdi_sio_port_probe(struct usb_serial_port *port)
|
||||
{
|
||||
struct usb_serial_port *port = serial->port[0];
|
||||
struct ftdi_private *priv;
|
||||
struct ftdi_sio_quirk *quirk;
|
||||
int retval;
|
||||
|
||||
dbg("%s",__FUNCTION__);
|
||||
|
||||
@ -1224,19 +1211,21 @@ static int ftdi_sio_attach (struct usb_serial *serial)
|
||||
kfree(port->bulk_out_buffer);
|
||||
port->bulk_out_buffer = NULL;
|
||||
|
||||
usb_set_serial_port_data(serial->port[0], priv);
|
||||
usb_set_serial_port_data(port, priv);
|
||||
|
||||
ftdi_determine_type (serial->port[0]);
|
||||
retval = create_sysfs_attrs(serial);
|
||||
if (retval)
|
||||
dev_err(&serial->dev->dev, "Error creating sysfs files, "
|
||||
"continuing\n");
|
||||
ftdi_determine_type (port);
|
||||
create_sysfs_attrs(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* attach subroutine */
|
||||
static int ftdi_sio_attach (struct usb_serial *serial)
|
||||
{
|
||||
/* Check for device requiring special set up. */
|
||||
quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
|
||||
if (quirk && quirk->setup) {
|
||||
struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
|
||||
|
||||
if (quirk && quirk->setup)
|
||||
quirk->setup(serial);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* ftdi_sio_attach */
|
||||
@ -1280,17 +1269,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
|
||||
* calls __serial_close for each open of the port
|
||||
* shutdown is called then (ie ftdi_shutdown)
|
||||
*/
|
||||
|
||||
|
||||
static void ftdi_shutdown (struct usb_serial *serial)
|
||||
{ /* ftdi_shutdown */
|
||||
{
|
||||
dbg("%s", __FUNCTION__);
|
||||
}
|
||||
|
||||
struct usb_serial_port *port = serial->port[0];
|
||||
static int ftdi_sio_port_remove(struct usb_serial_port *port)
|
||||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
remove_sysfs_attrs(serial);
|
||||
remove_sysfs_attrs(port);
|
||||
|
||||
/* all open ports are closed at this point
|
||||
* (by usbserial.c:__serial_close, which calls ftdi_close)
|
||||
@ -1300,8 +1290,9 @@ static void ftdi_shutdown (struct usb_serial *serial)
|
||||
usb_set_serial_port_data(port, NULL);
|
||||
kfree(priv);
|
||||
}
|
||||
} /* ftdi_shutdown */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftdi_open (struct usb_serial_port *port, struct file *filp)
|
||||
{ /* ftdi_open */
|
||||
|
Loading…
Reference in New Issue
Block a user