summaryrefslogtreecommitdiff
path: root/drivers/usb/serial/mos7840.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r--drivers/usb/serial/mos7840.c226
1 files changed, 73 insertions, 153 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 2f6da1e89bfa..5311819170d9 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -218,12 +218,10 @@ struct moschip_port {
int port_num; /*Actual port number in the device(1,2,etc) */
struct urb *write_urb; /* write URB for this port */
struct urb *read_urb; /* read URB for this port */
- struct urb *int_urb;
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
char open;
char open_ports;
- char zombie;
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
int delta_msr_cond;
@@ -493,7 +491,6 @@ static void mos7840_control_callback(struct urb *urb)
unsigned char *data;
struct moschip_port *mos7840_port;
__u8 regval = 0x0;
- int result = 0;
int status = urb->status;
mos7840_port = urb->context;
@@ -512,7 +509,7 @@ static void mos7840_control_callback(struct urb *urb)
default:
dbg("%s - nonzero urb status received: %d", __func__,
status);
- goto exit;
+ return;
}
dbg("%s urb buffer size is %d", __func__, urb->actual_length);
@@ -525,17 +522,6 @@ static void mos7840_control_callback(struct urb *urb)
mos7840_handle_new_msr(mos7840_port, regval);
else if (mos7840_port->MsrLsr == 1)
mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie)
- result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
- spin_unlock(&mos7840_port->pool_lock);
- if (result) {
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting interrupt urb\n",
- __func__, result);
- }
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -704,14 +690,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
wreg = MODEM_STATUS_REGISTER;
break;
}
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie) {
- rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
- } else {
- spin_unlock(&mos7840_port->pool_lock);
- return;
- }
- spin_unlock(&mos7840_port->pool_lock);
+ rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
}
}
}
@@ -2426,52 +2405,43 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
return mos7840_num_ports;
}
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct moschip_port *mos7840_port;
- struct usb_device *dev;
- int i, status;
+ int status;
+ int pnum;
__u16 Data;
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return -1;
- }
-
- dev = serial->dev;
-
/* we set up the pointers to the endpoints in the mos7840_open *
* function, as the structures aren't created yet. */
- /* set up port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- dbg ("mos7840_startup: configuring port %d............", i);
+ pnum = port->number - serial->minor;
+
+ /* FIXME: remove do-while(0) loop used to keep stable patch minimal.
+ */
+ do {
+ dbg("mos7840_startup: configuring port %d............", pnum);
mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) {
- dev_err(&dev->dev, "%s - Out of memory\n", __func__);
- status = -ENOMEM;
- i--; /* don't follow NULL pointer cleaning up */
- goto error;
+ dev_err(&port->dev, "%s - Out of memory\n", __func__);
+ return -ENOMEM;
}
/* Initialize all port interrupt end point to port 0 int
* endpoint. Our device has only one interrupt end point
* common to all port */
- mos7840_port->port = serial->port[i];
- mos7840_set_port_private(serial->port[i], mos7840_port);
+ mos7840_port->port = port;
+ mos7840_set_port_private(port, mos7840_port);
spin_lock_init(&mos7840_port->pool_lock);
/* minor is not initialised until later by
* usb-serial.c:get_free_serial() and cannot therefore be used
* to index device instances */
- mos7840_port->port_num = i + 1;
- dbg ("serial->port[i]->number = %d", serial->port[i]->number);
- dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor);
+ mos7840_port->port_num = pnum + 1;
+ dbg("port->number = %d", port->number);
+ dbg("port->serial->minor = %d", port->serial->minor);
dbg ("mos7840_port->port_num = %d", mos7840_port->port_num);
dbg ("serial->minor = %d", serial->minor);
@@ -2501,10 +2471,10 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_port->DcrRegOffset = 0x1c;
}
mos7840_dump_serial_port(mos7840_port);
- mos7840_set_port_private(serial->port[i], mos7840_port);
+ mos7840_set_port_private(port, mos7840_port);
/* enable rx_disable bit in control register */
- status = mos7840_get_reg_sync(serial->port[i],
+ status = mos7840_get_reg_sync(port,
mos7840_port->ControlRegOffset, &Data);
if (status < 0) {
dbg("Reading ControlReg failed status-0x%x", status);
@@ -2512,12 +2482,13 @@ static int mos7840_startup(struct usb_serial *serial)
} else
dbg("ControlReg Reading success val is %x, status%d",
Data, status);
+
Data |= 0x08; /* setting driver done bit */
Data |= 0x04; /* sp1_bit to have cts change reflect in
modem status reg */
/* Data |= 0x20; //rx_disable bit */
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dbg("Writing ControlReg failed(rx_disable) status-0x%x", status);
@@ -2529,7 +2500,7 @@ static int mos7840_startup(struct usb_serial *serial)
/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
and 0x24 in DCR3 */
Data = 0x01;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 0), Data);
if (status < 0) {
dbg("Writing DCR0 failed status-0x%x", status);
@@ -2538,7 +2509,7 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR0 Writing success status%d", status);
Data = 0x05;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 1), Data);
if (status < 0) {
dbg("Writing DCR1 failed status-0x%x", status);
@@ -2547,7 +2518,7 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR1 Writing success status%d", status);
Data = 0x24;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 2), Data);
if (status < 0) {
dbg("Writing DCR2 failed status-0x%x", status);
@@ -2557,7 +2528,7 @@ static int mos7840_startup(struct usb_serial *serial)
/* write values in clkstart0x0 and clkmulti 0x20 */
Data = 0x0;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
CLK_START_VALUE_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x", status);
@@ -2566,7 +2537,7 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("CLK_START_VALUE_REGISTER Writing success status%d", status);
Data = 0x20;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
CLK_MULTI_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_MULTI_REGISTER failed status-0x%x",
@@ -2578,7 +2549,7 @@ static int mos7840_startup(struct usb_serial *serial)
/* write value 0x0 to scratchpad register */
Data = 0x00;
- status = mos7840_set_uart_reg(serial->port[i],
+ status = mos7840_set_uart_reg(port,
SCRATCH_PAD_REGISTER, Data);
if (status < 0) {
dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x",
@@ -2593,7 +2564,7 @@ static int mos7840_startup(struct usb_serial *serial)
&& (serial->num_ports == 2)) {
Data = 0xff;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
(__u16) (ZLP_REG1 +
((__u16)mos7840_port->port_num)), Data);
dbg("ZLIP offset %x",
@@ -2601,14 +2572,14 @@ static int mos7840_startup(struct usb_serial *serial)
((__u16) mos7840_port->port_num)));
if (status < 0) {
dbg("Writing ZLP_REG%d failed status-0x%x",
- i + 2, status);
+ pnum + 2, status);
break;
} else
dbg("ZLP_REG%d Writing success status%d",
- i + 2, status);
+ pnum + 2, status);
} else {
Data = 0xff;
- status = mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(port,
(__u16) (ZLP_REG1 +
((__u16)mos7840_port->port_num) - 0x1), Data);
dbg("ZLIP offset %x",
@@ -2616,11 +2587,11 @@ static int mos7840_startup(struct usb_serial *serial)
((__u16) mos7840_port->port_num) - 0x1));
if (status < 0) {
dbg("Writing ZLP_REG%d failed status-0x%x",
- i + 1, status);
+ pnum + 1, status);
break;
} else
dbg("ZLP_REG%d Writing success status%d",
- i + 1, status);
+ pnum + 1, status);
}
mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -2657,108 +2628,58 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_port->led_flag = false;
/* Turn off LED */
- mos7840_set_led_sync(serial->port[i],
+ mos7840_set_led_sync(port,
MODEM_CONTROL_REGISTER, 0x0300);
}
- }
- dbg ("mos7840_startup: all ports configured...........");
+ } while (0);
- /* Zero Length flag enable */
- Data = 0x0f;
- status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
- if (status < 0) {
- dbg("Writing ZLP_REG5 failed status-0x%x", status);
- goto error;
- } else
- dbg("ZLP_REG5 Writing success status%d", status);
-
- /* setting configuration feature to one */
- usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
+ if (pnum == serial->num_ports - 1) {
+ dbg("mos7840_startup: all ports configured...........");
+
+ /* Zero Length flag enable */
+ Data = 0x0f;
+ status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+ if (status < 0) {
+ dbg("Writing ZLP_REG5 failed status-0x%x", status);
+ goto error;
+ } else
+ dbg("ZLP_REG5 Writing success status%d", status);
+
+ /* setting configuration feature to one */
+ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+ MOS_WDR_TIMEOUT);
+ }
return 0;
error:
- for (/* nothing */; i >= 0; i--) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
+ kfree(mos7840_port->dr);
+ kfree(mos7840_port->ctrl_buf);
+ usb_free_urb(mos7840_port->control_urb);
+ kfree(mos7840_port);
- kfree(mos7840_port->dr);
- kfree(mos7840_port->ctrl_buf);
- usb_free_urb(mos7840_port->control_urb);
- kfree(mos7840_port);
- serial->port[i] = NULL;
- }
return status;
}
-/****************************************************************************
- * mos7840_disconnect
- * This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
{
- int i;
- unsigned long flags;
struct moschip_port *mos7840_port;
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return;
- }
-
- /* check for the ports to be closed,close the ports and disconnect */
-
- /* free private structure allocated for serial port *
- * stop reads and writes on all ports */
-
- for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
- dbg ("mos7840_port %d = %p", i, mos7840_port);
- if (mos7840_port) {
- spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- mos7840_port->zombie = 1;
- spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
- usb_kill_urb(mos7840_port->control_urb);
- }
- }
-}
-
-/****************************************************************************
- * mos7840_release
- * This function is called when the usb_serial structure is freed.
- ****************************************************************************/
+ mos7840_port = mos7840_get_port_private(port);
-static void mos7840_release(struct usb_serial *serial)
-{
- int i;
- struct moschip_port *mos7840_port;
+ if (mos7840_port->has_led) {
+ /* Turn off LED */
+ mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
- if (!serial) {
- dbg("%s", "Invalid Handler");
- return;
+ del_timer_sync(&mos7840_port->led_timer1);
+ del_timer_sync(&mos7840_port->led_timer2);
}
+ usb_kill_urb(mos7840_port->control_urb);
+ usb_free_urb(mos7840_port->control_urb);
+ kfree(mos7840_port->ctrl_buf);
+ kfree(mos7840_port->dr);
+ kfree(mos7840_port);
- /* check for the ports to be closed,close the ports and disconnect */
-
- /* free private structure allocated for serial port *
- * stop reads and writes on all ports */
-
- for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
- dbg("mos7840_port %d = %p", i, mos7840_port);
- if (mos7840_port) {
- if (mos7840_port->has_led) {
- /* Turn off LED */
- mos7840_set_led_sync(mos7840_port->port,
- MODEM_CONTROL_REGISTER, 0x0300);
-
- del_timer_sync(&mos7840_port->led_timer1);
- del_timer_sync(&mos7840_port->led_timer2);
- }
- kfree(mos7840_port->ctrl_buf);
- kfree(mos7840_port->dr);
- kfree(mos7840_port);
- }
- }
+ return 0;
}
static struct usb_serial_driver moschip7840_4port_device = {
@@ -2786,9 +2707,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
.tiocmget = mos7840_tiocmget,
.tiocmset = mos7840_tiocmset,
.get_icount = mos7840_get_icount,
- .attach = mos7840_startup,
- .disconnect = mos7840_disconnect,
- .release = mos7840_release,
+ .port_probe = mos7840_port_probe,
+ .port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback,
.read_int_callback = mos7840_interrupt_callback,
};