diff options
author | Jim Radford <radford@blackbean.org> | 2007-02-28 13:10:50 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-03-09 22:52:24 -0500 |
commit | 12bdbe03c8db7139de1de5c622cb0609d259cece (patch) | |
tree | 8d3938e4ddee18c9a23eac12750ad50ec7f46118 /drivers/usb/serial/ftdi_sio.c | |
parent | d9a7ecacac5f8274d2afce09aadcf37bdb42b93a (diff) |
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>
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 79 |
1 files changed, 35 insertions, 44 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 07884e0803b9..ada4e6c6f9cc 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -597,6 +597,8 @@ struct ftdi_private { | |||
597 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); | 597 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); |
598 | static int ftdi_sio_attach (struct usb_serial *serial); | 598 | static int ftdi_sio_attach (struct usb_serial *serial); |
599 | static void ftdi_shutdown (struct usb_serial *serial); | 599 | static void ftdi_shutdown (struct usb_serial *serial); |
600 | static int ftdi_sio_port_probe (struct usb_serial_port *port); | ||
601 | static int ftdi_sio_port_remove (struct usb_serial_port *port); | ||
600 | static int ftdi_open (struct usb_serial_port *port, struct file *filp); | 602 | static int ftdi_open (struct usb_serial_port *port, struct file *filp); |
601 | static void ftdi_close (struct usb_serial_port *port, struct file *filp); | 603 | static void ftdi_close (struct usb_serial_port *port, struct file *filp); |
602 | static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 604 | 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 = { | |||
631 | .num_bulk_out = 1, | 633 | .num_bulk_out = 1, |
632 | .num_ports = 1, | 634 | .num_ports = 1, |
633 | .probe = ftdi_sio_probe, | 635 | .probe = ftdi_sio_probe, |
636 | .port_probe = ftdi_sio_port_probe, | ||
637 | .port_remove = ftdi_sio_port_remove, | ||
634 | .open = ftdi_open, | 638 | .open = ftdi_open, |
635 | .close = ftdi_close, | 639 | .close = ftdi_close, |
636 | .throttle = ftdi_throttle, | 640 | .throttle = ftdi_throttle, |
@@ -1033,11 +1037,10 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a | |||
1033 | { | 1037 | { |
1034 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1038 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1035 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1039 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1036 | struct usb_device *udev; | 1040 | struct usb_device *udev = port->serial->dev; |
1037 | unsigned short latency = 0; | 1041 | unsigned short latency = 0; |
1038 | int rv = 0; | 1042 | int rv = 0; |
1039 | 1043 | ||
1040 | udev = to_usb_device(dev); | ||
1041 | 1044 | ||
1042 | dbg("%s",__FUNCTION__); | 1045 | dbg("%s",__FUNCTION__); |
1043 | 1046 | ||
@@ -1061,13 +1064,11 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * | |||
1061 | { | 1064 | { |
1062 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1065 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1063 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1066 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1064 | struct usb_device *udev; | 1067 | struct usb_device *udev = port->serial->dev; |
1065 | char buf[1]; | 1068 | char buf[1]; |
1066 | int v = simple_strtoul(valbuf, NULL, 10); | 1069 | int v = simple_strtoul(valbuf, NULL, 10); |
1067 | int rv = 0; | 1070 | int rv = 0; |
1068 | 1071 | ||
1069 | udev = to_usb_device(dev); | ||
1070 | |||
1071 | dbg("%s: setting latency timer = %i", __FUNCTION__, v); | 1072 | dbg("%s: setting latency timer = %i", __FUNCTION__, v); |
1072 | 1073 | ||
1073 | rv = usb_control_msg(udev, | 1074 | rv = usb_control_msg(udev, |
@@ -1092,13 +1093,11 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
1092 | { | 1093 | { |
1093 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1094 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1094 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1095 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1095 | struct usb_device *udev; | 1096 | struct usb_device *udev = port->serial->dev; |
1096 | char buf[1]; | 1097 | char buf[1]; |
1097 | int v = simple_strtoul(valbuf, NULL, 10); | 1098 | int v = simple_strtoul(valbuf, NULL, 10); |
1098 | int rv = 0; | 1099 | int rv = 0; |
1099 | 1100 | ||
1100 | udev = to_usb_device(dev); | ||
1101 | |||
1102 | dbg("%s: setting event char = %i", __FUNCTION__, v); | 1101 | dbg("%s: setting event char = %i", __FUNCTION__, v); |
1103 | 1102 | ||
1104 | rv = usb_control_msg(udev, | 1103 | rv = usb_control_msg(udev, |
@@ -1119,46 +1118,38 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
1119 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); | 1118 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); |
1120 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | 1119 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); |
1121 | 1120 | ||
1122 | static int create_sysfs_attrs(struct usb_serial *serial) | 1121 | static int create_sysfs_attrs(struct usb_serial_port *port) |
1123 | { | 1122 | { |
1124 | struct ftdi_private *priv; | 1123 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1125 | struct usb_device *udev; | ||
1126 | int retval = 0; | 1124 | int retval = 0; |
1127 | 1125 | ||
1128 | dbg("%s",__FUNCTION__); | 1126 | dbg("%s",__FUNCTION__); |
1129 | 1127 | ||
1130 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1131 | udev = serial->dev; | ||
1132 | |||
1133 | /* XXX I've no idea if the original SIO supports the event_char | 1128 | /* XXX I've no idea if the original SIO supports the event_char |
1134 | * sysfs parameter, so I'm playing it safe. */ | 1129 | * sysfs parameter, so I'm playing it safe. */ |
1135 | if (priv->chip_type != SIO) { | 1130 | if (priv->chip_type != SIO) { |
1136 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1131 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1137 | retval = device_create_file(&udev->dev, &dev_attr_event_char); | 1132 | retval = device_create_file(&port->dev, &dev_attr_event_char); |
1138 | if ((!retval) && | 1133 | if ((!retval) && |
1139 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { | 1134 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { |
1140 | retval = device_create_file(&udev->dev, | 1135 | retval = device_create_file(&port->dev, |
1141 | &dev_attr_latency_timer); | 1136 | &dev_attr_latency_timer); |
1142 | } | 1137 | } |
1143 | } | 1138 | } |
1144 | return retval; | 1139 | return retval; |
1145 | } | 1140 | } |
1146 | 1141 | ||
1147 | static void remove_sysfs_attrs(struct usb_serial *serial) | 1142 | static void remove_sysfs_attrs(struct usb_serial_port *port) |
1148 | { | 1143 | { |
1149 | struct ftdi_private *priv; | 1144 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1150 | struct usb_device *udev; | ||
1151 | 1145 | ||
1152 | dbg("%s",__FUNCTION__); | 1146 | dbg("%s",__FUNCTION__); |
1153 | 1147 | ||
1154 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1155 | udev = serial->dev; | ||
1156 | |||
1157 | /* XXX see create_sysfs_attrs */ | 1148 | /* XXX see create_sysfs_attrs */ |
1158 | if (priv->chip_type != SIO) { | 1149 | if (priv->chip_type != SIO) { |
1159 | device_remove_file(&udev->dev, &dev_attr_event_char); | 1150 | device_remove_file(&port->dev, &dev_attr_event_char); |
1160 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | 1151 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { |
1161 | device_remove_file(&udev->dev, &dev_attr_latency_timer); | 1152 | device_remove_file(&port->dev, &dev_attr_latency_timer); |
1162 | } | 1153 | } |
1163 | } | 1154 | } |
1164 | 1155 | ||
@@ -1178,13 +1169,9 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id | |||
1178 | return (0); | 1169 | return (0); |
1179 | } | 1170 | } |
1180 | 1171 | ||
1181 | /* attach subroutine */ | 1172 | static int ftdi_sio_port_probe(struct usb_serial_port *port) |
1182 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
1183 | { | 1173 | { |
1184 | struct usb_serial_port *port = serial->port[0]; | ||
1185 | struct ftdi_private *priv; | 1174 | struct ftdi_private *priv; |
1186 | struct ftdi_sio_quirk *quirk; | ||
1187 | int retval; | ||
1188 | 1175 | ||
1189 | dbg("%s",__FUNCTION__); | 1176 | dbg("%s",__FUNCTION__); |
1190 | 1177 | ||
@@ -1224,19 +1211,21 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1224 | kfree(port->bulk_out_buffer); | 1211 | kfree(port->bulk_out_buffer); |
1225 | port->bulk_out_buffer = NULL; | 1212 | port->bulk_out_buffer = NULL; |
1226 | 1213 | ||
1227 | usb_set_serial_port_data(serial->port[0], priv); | 1214 | usb_set_serial_port_data(port, priv); |
1228 | 1215 | ||
1229 | ftdi_determine_type (serial->port[0]); | 1216 | ftdi_determine_type (port); |
1230 | retval = create_sysfs_attrs(serial); | 1217 | create_sysfs_attrs(port); |
1231 | if (retval) | 1218 | return 0; |
1232 | dev_err(&serial->dev->dev, "Error creating sysfs files, " | 1219 | } |
1233 | "continuing\n"); | ||
1234 | 1220 | ||
1221 | /* attach subroutine */ | ||
1222 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
1223 | { | ||
1235 | /* Check for device requiring special set up. */ | 1224 | /* Check for device requiring special set up. */ |
1236 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); | 1225 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); |
1237 | if (quirk && quirk->setup) { | 1226 | |
1227 | if (quirk && quirk->setup) | ||
1238 | quirk->setup(serial); | 1228 | quirk->setup(serial); |
1239 | } | ||
1240 | 1229 | ||
1241 | return 0; | 1230 | return 0; |
1242 | } /* ftdi_sio_attach */ | 1231 | } /* ftdi_sio_attach */ |
@@ -1280,17 +1269,18 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) | |||
1280 | * calls __serial_close for each open of the port | 1269 | * calls __serial_close for each open of the port |
1281 | * shutdown is called then (ie ftdi_shutdown) | 1270 | * shutdown is called then (ie ftdi_shutdown) |
1282 | */ | 1271 | */ |
1283 | |||
1284 | |||
1285 | static void ftdi_shutdown (struct usb_serial *serial) | 1272 | static void ftdi_shutdown (struct usb_serial *serial) |
1286 | { /* ftdi_shutdown */ | 1273 | { |
1274 | dbg("%s", __FUNCTION__); | ||
1275 | } | ||
1287 | 1276 | ||
1288 | struct usb_serial_port *port = serial->port[0]; | 1277 | static int ftdi_sio_port_remove(struct usb_serial_port *port) |
1278 | { | ||
1289 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1279 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1290 | 1280 | ||
1291 | dbg("%s", __FUNCTION__); | 1281 | dbg("%s", __FUNCTION__); |
1292 | 1282 | ||
1293 | remove_sysfs_attrs(serial); | 1283 | remove_sysfs_attrs(port); |
1294 | 1284 | ||
1295 | /* all open ports are closed at this point | 1285 | /* all open ports are closed at this point |
1296 | * (by usbserial.c:__serial_close, which calls ftdi_close) | 1286 | * (by usbserial.c:__serial_close, which calls ftdi_close) |
@@ -1300,8 +1290,9 @@ static void ftdi_shutdown (struct usb_serial *serial) | |||
1300 | usb_set_serial_port_data(port, NULL); | 1290 | usb_set_serial_port_data(port, NULL); |
1301 | kfree(priv); | 1291 | kfree(priv); |
1302 | } | 1292 | } |
1303 | } /* ftdi_shutdown */ | ||
1304 | 1293 | ||
1294 | return 0; | ||
1295 | } | ||
1305 | 1296 | ||
1306 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) | 1297 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) |
1307 | { /* ftdi_open */ | 1298 | { /* ftdi_open */ |