diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-05-30 06:25:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-13 18:23:53 -0400 |
commit | e463c6dda8f5ee0baa6a5400e45d300287339536 (patch) | |
tree | e62b4039f909feba48d5b86bedd1dc3aa1f56be1 /drivers/usb/serial/option.c | |
parent | 378fac2a46decbcd16b42044303ba8a1a3f8001e (diff) |
USB: option: handle send_setup blacklisting at probe
Determine whether to use send_setup at probe time rather than at every
call to send_setup.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/option.c')
-rw-r--r-- | drivers/usb/serial/option.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ccf7f3c9a7c6..9520c4c54743 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -1276,6 +1276,10 @@ static struct usb_serial_driver * const serial_drivers[] = { | |||
1276 | 1276 | ||
1277 | static bool debug; | 1277 | static bool debug; |
1278 | 1278 | ||
1279 | struct option_private { | ||
1280 | u8 bInterfaceNumber; | ||
1281 | }; | ||
1282 | |||
1279 | module_usb_serial_driver(serial_drivers, option_ids); | 1283 | module_usb_serial_driver(serial_drivers, option_ids); |
1280 | 1284 | ||
1281 | static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, | 1285 | static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, |
@@ -1306,6 +1310,7 @@ static int option_probe(struct usb_serial *serial, | |||
1306 | const struct usb_device_id *id) | 1310 | const struct usb_device_id *id) |
1307 | { | 1311 | { |
1308 | struct usb_wwan_intf_private *data; | 1312 | struct usb_wwan_intf_private *data; |
1313 | struct option_private *priv; | ||
1309 | struct usb_interface_descriptor *iface_desc = | 1314 | struct usb_interface_descriptor *iface_desc = |
1310 | &serial->interface->cur_altsetting->desc; | 1315 | &serial->interface->cur_altsetting->desc; |
1311 | struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; | 1316 | struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; |
@@ -1346,9 +1351,22 @@ static int option_probe(struct usb_serial *serial, | |||
1346 | data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); | 1351 | data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); |
1347 | if (!data) | 1352 | if (!data) |
1348 | return -ENOMEM; | 1353 | return -ENOMEM; |
1349 | data->send_setup = option_send_setup; | 1354 | |
1355 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
1356 | if (!priv) { | ||
1357 | kfree(data); | ||
1358 | return -ENOMEM; | ||
1359 | } | ||
1360 | |||
1361 | priv->bInterfaceNumber = iface_desc->bInterfaceNumber; | ||
1362 | data->private = priv; | ||
1363 | |||
1364 | if (!is_blacklisted(iface_desc->bInterfaceNumber, | ||
1365 | OPTION_BLACKLIST_SENDSETUP, | ||
1366 | (struct option_blacklist_info *)id->driver_info)) { | ||
1367 | data->send_setup = option_send_setup; | ||
1368 | } | ||
1350 | spin_lock_init(&data->susp_lock); | 1369 | spin_lock_init(&data->susp_lock); |
1351 | data->private = (void *)id->driver_info; | ||
1352 | 1370 | ||
1353 | usb_set_serial_data(serial, data); | 1371 | usb_set_serial_data(serial, data); |
1354 | 1372 | ||
@@ -1357,11 +1375,13 @@ static int option_probe(struct usb_serial *serial, | |||
1357 | 1375 | ||
1358 | static void option_release(struct usb_serial *serial) | 1376 | static void option_release(struct usb_serial *serial) |
1359 | { | 1377 | { |
1360 | struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); | 1378 | struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); |
1379 | struct option_private *priv = intfdata->private; | ||
1361 | 1380 | ||
1362 | usb_wwan_release(serial); | 1381 | usb_wwan_release(serial); |
1363 | 1382 | ||
1364 | kfree(priv); | 1383 | kfree(priv); |
1384 | kfree(intfdata); | ||
1365 | } | 1385 | } |
1366 | 1386 | ||
1367 | static void option_instat_callback(struct urb *urb) | 1387 | static void option_instat_callback(struct urb *urb) |
@@ -1429,16 +1449,10 @@ static int option_send_setup(struct usb_serial_port *port) | |||
1429 | { | 1449 | { |
1430 | struct usb_serial *serial = port->serial; | 1450 | struct usb_serial *serial = port->serial; |
1431 | struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); | 1451 | struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); |
1452 | struct option_private *priv = intfdata->private; | ||
1432 | struct usb_wwan_port_private *portdata; | 1453 | struct usb_wwan_port_private *portdata; |
1433 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | ||
1434 | int val = 0; | 1454 | int val = 0; |
1435 | 1455 | ||
1436 | if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP, | ||
1437 | (struct option_blacklist_info *) intfdata->private)) { | ||
1438 | dbg("No send_setup on blacklisted interface #%d\n", ifNum); | ||
1439 | return -EIO; | ||
1440 | } | ||
1441 | |||
1442 | portdata = usb_get_serial_port_data(port); | 1456 | portdata = usb_get_serial_port_data(port); |
1443 | 1457 | ||
1444 | if (portdata->dtr_state) | 1458 | if (portdata->dtr_state) |
@@ -1446,9 +1460,9 @@ static int option_send_setup(struct usb_serial_port *port) | |||
1446 | if (portdata->rts_state) | 1460 | if (portdata->rts_state) |
1447 | val |= 0x02; | 1461 | val |= 0x02; |
1448 | 1462 | ||
1449 | return usb_control_msg(serial->dev, | 1463 | return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
1450 | usb_rcvctrlpipe(serial->dev, 0), | 1464 | 0x22, 0x21, val, priv->bInterfaceNumber, NULL, |
1451 | 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); | 1465 | 0, USB_CTRL_SET_TIMEOUT); |
1452 | } | 1466 | } |
1453 | 1467 | ||
1454 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1468 | MODULE_AUTHOR(DRIVER_AUTHOR); |