USB: usb_wwan/option: generalize option_send_setup for other drivers

Only the option driver implements the send_setup callback; it uses the
SET_CONTROL_LINE_STATE request in CDC ACM to generate DTR/RTS signals
on the port. This is not driver-specific though and is needed by other
drivers, so move the function to the usb_wwan driver (with formatting
tweaks), and replace the callback pointer with a flag that enables the
request.

Suggested-by: Bjørn Mork <bjorn@mork.no>
Suggested-by: Johan Hovold <johan@kernel.org>
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Signed-off-by: Johan Hovold <johan@kernel.org>
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 4d16c97..edfaec1 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -48,7 +48,6 @@
 			const struct usb_device_id *id);
 static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
-static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
 
 /* Vendor and product IDs */
@@ -1890,7 +1889,7 @@
 
 	if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
 						&blacklist->sendsetup)) {
-		data->send_setup = option_send_setup;
+		data->use_send_setup = 1;
 	}
 	spin_lock_init(&data->susp_lock);
 
@@ -1961,39 +1960,6 @@
 	}
 }
 
-/** send RTS/DTR state to the port.
- *
- * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
- * CDC.
-*/
-static int option_send_setup(struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-	struct usb_wwan_port_private *portdata;
-	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
-	int val = 0;
-	int res;
-
-	portdata = usb_get_serial_port_data(port);
-
-	if (portdata->dtr_state)
-		val |= 0x01;
-	if (portdata->rts_state)
-		val |= 0x02;
-
-	res = usb_autopm_get_interface(serial->interface);
-	if (res)
-		return res;
-
-	res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-				0x22, 0x21, val, ifNum, NULL,
-				0, USB_CTRL_SET_TIMEOUT);
-
-	usb_autopm_put_interface(serial->interface);
-
-	return res;
-}
-
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index f22dff5..44b25c0 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -34,9 +34,9 @@
 struct usb_wwan_intf_private {
 	spinlock_t susp_lock;
 	unsigned int suspended:1;
+	unsigned int use_send_setup:1;
 	int in_flight;
 	unsigned int open_ports;
-	int (*send_setup) (struct usb_serial_port *port);
 	void *private;
 };
 
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 825305c..be9cb61 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -36,6 +36,40 @@
 #include <linux/serial.h>
 #include "usb-wwan.h"
 
+/*
+ * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
+ * in CDC ACM.
+ */
+static int usb_wwan_send_setup(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct usb_wwan_port_private *portdata;
+	int val = 0;
+	int ifnum;
+	int res;
+
+	portdata = usb_get_serial_port_data(port);
+
+	if (portdata->dtr_state)
+		val |= 0x01;
+	if (portdata->rts_state)
+		val |= 0x02;
+
+	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+	res = usb_autopm_get_interface(serial->interface);
+	if (res)
+		return res;
+
+	res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				0x22, 0x21, val, ifnum, NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+
+	usb_autopm_put_interface(port->serial->interface);
+
+	return res;
+}
+
 void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 {
 	struct usb_wwan_port_private *portdata;
@@ -43,7 +77,7 @@
 
 	intfdata = usb_get_serial_data(port->serial);
 
-	if (!intfdata->send_setup)
+	if (!intfdata->use_send_setup)
 		return;
 
 	portdata = usb_get_serial_port_data(port);
@@ -51,7 +85,7 @@
 	portdata->rts_state = on;
 	portdata->dtr_state = on;
 
-	intfdata->send_setup(port);
+	usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_dtr_rts);
 
@@ -84,7 +118,7 @@
 	portdata = usb_get_serial_port_data(port);
 	intfdata = usb_get_serial_data(port->serial);
 
-	if (!intfdata->send_setup)
+	if (!intfdata->use_send_setup)
 		return -EINVAL;
 
 	/* FIXME: what locks portdata fields ? */
@@ -97,7 +131,7 @@
 		portdata->rts_state = 0;
 	if (clear & TIOCM_DTR)
 		portdata->dtr_state = 0;
-	return intfdata->send_setup(port);
+	return usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_tiocmset);