patch-2.4.15 linux/drivers/usb/serial/io_edgeport.c
Next file: linux/drivers/usb/serial/io_tables.h
Previous file: linux/drivers/usb/serial/ftdi_sio.c
Back to the patch index
Back to the overall index
- Lines: 476
- Date:
Wed Nov 21 09:59:11 2001
- Orig file:
v2.4.14/linux/drivers/usb/serial/io_edgeport.c
- Orig date:
Thu Oct 11 08:02:26 2001
diff -u --recursive --new-file v2.4.14/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c
@@ -25,6 +25,14 @@
*
* Version history:
*
+ * 2.2 2001_11_14 greg kroah-hartman
+ * - fixed bug in edge_close that kept the port from being used more
+ * than once.
+ * - fixed memory leak on device removal.
+ * - fixed potential double free of memory when command urb submitting
+ * failed.
+ * - other small cleanups when the device is removed
+ *
* 2.1 2001_07_09 greg kroah-hartman
* - added support for TIOCMBIS and TIOCMBIC.
*
@@ -263,7 +271,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.1"
+#define DRIVER_VERSION "v2.2"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
@@ -433,7 +441,7 @@
/* function prototypes for all URB callbacks */
static void edge_interrupt_callback (struct urb *urb);
-static void edge_bulk_in_callback (struct urb *urb);
+static void edge_bulk_in_callback (struct urb *urb);
static void edge_bulk_out_data_callback (struct urb *urb);
static void edge_bulk_out_cmd_callback (struct urb *urb);
@@ -646,12 +654,6 @@
}
#endif
-
-
-/************************************************************************
- * *
- * *
- ************************************************************************/
static void get_product_info(struct edgeport_serial *edge_serial)
{
struct edgeport_product_info *product_info = &edge_serial->product_info;
@@ -933,7 +935,7 @@
dbg(__FUNCTION__" - FREE URB %p (outstanding %d)", urb, CmdUrbs);
- /* if this urb had a transfer buffer already (old transfer) free it */
+ /* clean up the transfer buffer */
if (urb->transfer_buffer != NULL) {
kfree(urb->transfer_buffer);
}
@@ -957,7 +959,6 @@
/* tell the tty driver that something has changed */
wake_up_interruptible(&tty->write_wait);
-
/* we have completed the command */
edge_port->commandPending = FALSE;
wake_up_interruptible(&edge_port->wait_command);
@@ -987,6 +988,9 @@
dbg(__FUNCTION__ " - port %d", port->number);
+ if (edge_port == NULL)
+ return -ENODEV;
+
++port->open_count;
MOD_INC_USE_COUNT;
@@ -1002,6 +1006,12 @@
as the structures were not set up at that time.) */
serial = port->serial;
edge_serial = (struct edgeport_serial *)serial->private;
+ if (edge_serial == NULL) {
+ port->active = 0;
+ port->open_count = 0;
+ MOD_DEC_USE_COUNT;
+ return -ENODEV;
+ }
if (edge_serial->interrupt_in_buffer == NULL) {
struct usb_serial_port *port0 = &serial->port[0];
@@ -1015,25 +1025,22 @@
edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
/* set up our interrupt urb */
- /* Like to use FILL_INT_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
- edge_serial->interrupt_read_urb->complete = edge_interrupt_callback;
- edge_serial->interrupt_read_urb->context = edge_serial;
- /* FILL_INT_URB(edge_serial->interrupt_read_urb, serial->dev,
- usb_rcvintpipe (serial->dev, edge_serial->interrupt_in_endpoint),
- edge_serial->interrupt_in_buffer, edge_serial->interrupt_in_endpoint.wMaxPacketSize,
- edge_interrupt_callback, edge_serial, edge_serial->interrupt_in_endpoint.bInterval);
- */
+ FILL_INT_URB(edge_serial->interrupt_read_urb,
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ port0->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ edge_serial->interrupt_read_urb->transfer_buffer_length,
+ edge_interrupt_callback, edge_serial,
+ edge_serial->interrupt_read_urb->interval);
/* set up our bulk in urb */
- /* Like to use FILL_BULK_URB, but we don't know wMaxPacketSize or bInterval, something to change for 2.5... */
- edge_serial->read_urb->complete = edge_bulk_in_callback;
- edge_serial->read_urb->context = edge_serial;
- /* FILL_BULK_URB(edge_serial->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev, edge_serial->bulk_in_endpoint),
- edge_serial->bulk_in_buffer, edge_serial->bulk_in_endpoint->wMaxPacketSize,
+ FILL_BULK_URB(edge_serial->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),
+ port0->bulk_in_buffer,
+ edge_serial->read_urb->transfer_buffer_length,
edge_bulk_in_callback, edge_serial);
- */
-
+
/* start interrupt read for this edgeport
* this interrupt will continue as long as the edgeport is connected */
response = usb_submit_urb (edge_serial->interrupt_read_urb);
@@ -1237,7 +1244,9 @@
edge_serial = (struct edgeport_serial *)serial->private;
edge_port = (struct edgeport_port *)port->private;
-
+ if ((edge_serial == NULL) || (edge_port == NULL))
+ return;
+
--port->open_count;
if (port->open_count <= 0) {
@@ -1283,15 +1292,14 @@
if (edge_port->txfifo.fifo) {
kfree(edge_port->txfifo.fifo);
}
+ port->active = 0;
+ port->open_count = 0;
}
MOD_DEC_USE_COUNT;
dbg(__FUNCTION__" exited");
}
-
-
-
/*****************************************************************************
* SerialWrite
* this function is called by the tty driver when data should be written to
@@ -1310,6 +1318,9 @@
dbg(__FUNCTION__ " - port %d", port->number);
+ if (edge_port == NULL)
+ return -ENODEV;
+
// get a pointer to the Tx fifo
fifo = &edge_port->txfifo;
@@ -1399,7 +1410,6 @@
struct urb *urb;
unsigned char *buffer;
int status;
- unsigned long flags;
int count;
int bytesleft;
int firsthalf;
@@ -1407,13 +1417,9 @@
dbg(__FUNCTION__"(%d)", edge_port->port->number);
- /* find our next free urb */ // ICK!!! FIXME!!!
- save_flags(flags); cli();
-
if (edge_port->write_in_progress ||
!edge_port->open ||
(fifo->count == 0)) {
- restore_flags(flags);
dbg(__FUNCTION__"(%d) EXIT - fifo %d, PendingWrite = %d", edge_port->port->number, fifo->count, edge_port->write_in_progress);
return;
}
@@ -1426,14 +1432,12 @@
// it's better to wait for more credits so we can do a larger
// write.
if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
- restore_flags(flags);
dbg(__FUNCTION__"(%d) Not enough credit - fifo %d TxCredit %d", edge_port->port->number, fifo->count, edge_port->txCredits );
return;
}
// lock this write
edge_port->write_in_progress = TRUE;
- restore_flags(flags);
// get a pointer to the write_urb
urb = edge_port->write_urb;
@@ -1514,9 +1518,10 @@
dbg(__FUNCTION__);
- if (edge_port->closePending == TRUE) {
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->closePending == TRUE)
return -ENODEV;
- }
dbg(__FUNCTION__" - port %d", port->number);
@@ -1549,6 +1554,11 @@
dbg(__FUNCTION__);
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->closePending == TRUE)
+ return -ENODEV;
+
if (!edge_port->open) {
dbg (__FUNCTION__" - port not opened");
return -EINVAL;
@@ -1576,6 +1586,9 @@
dbg(__FUNCTION__" - port %d", port->number);
+ if (edge_port == NULL)
+ return;
+
if (!edge_port->open) {
dbg (__FUNCTION__" - port not opened");
return;
@@ -1618,6 +1631,9 @@
dbg(__FUNCTION__" - port %d", port->number);
+ if (edge_port == NULL)
+ return;
+
if (!edge_port->open) {
dbg (__FUNCTION__" - port not opened");
return;
@@ -1675,6 +1691,9 @@
dbg(__FUNCTION__" - port %d", port->number);
+ if (edge_port == NULL)
+ return;
+
if (!edge_port->open) {
dbg (__FUNCTION__" - port not opened");
return;
@@ -1833,7 +1852,6 @@
struct async_icount cnow;
struct async_icount cprev;
struct serial_icounter_struct icount;
- unsigned long flags;
dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);
@@ -1845,14 +1863,6 @@
return get_number_bytes_avail(edge_port, (unsigned int *) arg);
break;
-// case TCGETS:
-// dbg(__FUNCTION__" (%d) TCGETS", port->number);
-// break;
-
-// case TCSETS:
-// dbg(__FUNCTION__" (%d) TCSETS", port->number);
-// break;
-
case TIOCSERGETLSR:
dbg(__FUNCTION__" (%d) TIOCSERGETLSR", port->number);
return get_lsr_info(edge_port, (unsigned int *) arg);
@@ -1878,17 +1888,13 @@
case TIOCMIWAIT:
dbg(__FUNCTION__" (%d) TIOCMIWAIT", port->number);
- save_flags(flags); cli();
cprev = edge_port->icount;
- restore_flags(flags);
while (1) {
interruptible_sleep_on(&edge_port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
- save_flags(flags); cli();
- cnow = edge_port->icount; /* atomic copy */
- restore_flags(flags);
+ cnow = edge_port->icount;
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
return -EIO; /* no change => error */
@@ -1904,9 +1910,7 @@
break;
case TIOCGICOUNT:
- save_flags(flags); cli();
cnow = edge_port->icount;
- restore_flags(flags);
icount.cts = cnow.cts;
icount.dsr = cnow.dsr;
icount.rng = cnow.rng;
@@ -2477,15 +2481,12 @@
/* Allocate our next urb */
urb = usb_alloc_urb (0);
+ if (!urb)
+ return -ENOMEM;
CmdUrbs++;
-
dbg(__FUNCTION__" - ALLOCATE URB %p (outstanding %d)", urb, CmdUrbs);
- if (!urb) {
- return -ENOMEM;
- }
-
FILL_BULK_URB (urb, edge_serial->serial->dev,
usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
buffer, length, edge_bulk_out_cmd_callback, edge_port);
@@ -2494,17 +2495,11 @@
urb->transfer_flags |= USB_QUEUE_BULK;
edge_port->commandPending = TRUE;
- urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(urb);
if (status) {
/* something went wrong */
dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
-
- /* if this urb had a transfer buffer already (old transfer) free it */
- if (urb->transfer_buffer != NULL) {
- kfree(urb->transfer_buffer);
- }
usb_unlink_urb (urb);
usb_free_urb (urb);
return status;
@@ -2568,6 +2563,10 @@
MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+ if (status) {
+ /* something bad happened, let's free up the memory */
+ kfree (cmdBuffer);
+ }
return status;
}
@@ -2643,6 +2642,10 @@
MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->number, regNum, regValue);
status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
+ if (status) {
+ /* something bad happened, let's free up the memory */
+ kfree (cmdBuffer);
+ }
return status;
}
@@ -2727,10 +2730,8 @@
unsigned char stop_char = STOP_CHAR(tty);
unsigned char start_char = START_CHAR(tty);
- {
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
- }
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
@@ -2982,10 +2983,11 @@
get_product_info(edge_serial);
/* set the number of ports from the manufacturing description */
- // FIXME should we override this???
- //serial->num_ports = serial->product_info.NumPorts;
+ /* serial->num_ports = serial->product_info.NumPorts; */
if (edge_serial->product_info.NumPorts != serial->num_ports) {
- warn(__FUNCTION__ " - Device Reported %d serial ports vs core thinking we have %d ports, email greg@kroah.com this info.", edge_serial->product_info.NumPorts, serial->num_ports);
+ warn(__FUNCTION__ " - Device Reported %d serial ports vs core "
+ "thinking we have %d ports, email greg@kroah.com this info.",
+ edge_serial->product_info.NumPorts, serial->num_ports);
}
dbg(__FUNCTION__ " - time 1 %ld", jiffies);
@@ -3025,10 +3027,9 @@
/****************************************************************************
- * usb_edgeport_disconnect
+ * edge_shutdown
* This function is called whenever the device is removed from the usb bus.
****************************************************************************/
-//static void usb_edgeport_disconnect (struct usb_device *dev, void *ptr)
static void edge_shutdown (struct usb_serial *serial)
{
int i;
@@ -3040,11 +3041,11 @@
while (serial->port[i].open_count > 0) {
edge_close (&serial->port[i], NULL);
}
+ kfree (serial->port[i].private);
+ serial->port[i].private = NULL;
}
-
- /* free up any memory that we allocated */
- // FIXME
-
+ kfree (serial->private);
+ serial->private = NULL;
}
@@ -3054,22 +3055,10 @@
****************************************************************************/
int __init edgeport_init(void)
{
- usb_serial_register (&edgeport_4_device);
- usb_serial_register (&rapidport_4_device);
- usb_serial_register (&edgeport_4t_device);
- usb_serial_register (&edgeport_2_device);
- usb_serial_register (&edgeport_4i_device);
- usb_serial_register (&edgeport_2i_device);
- usb_serial_register (&edgeport_prl_device);
- usb_serial_register (&edgeport_421_device);
- usb_serial_register (&edgeport_21_device);
- usb_serial_register (&edgeport_8dual_device);
- usb_serial_register (&edgeport_8_device);
- usb_serial_register (&edgeport_2din_device);
- usb_serial_register (&edgeport_4din_device);
- usb_serial_register (&edgeport_16dual_device);
- usb_serial_register (&edgeport_compat_id_device);
- usb_serial_register (&edgeport_8i_device);
+ usb_serial_register (&edgeport_1port_device);
+ usb_serial_register (&edgeport_2port_device);
+ usb_serial_register (&edgeport_4port_device);
+ usb_serial_register (&edgeport_8port_device);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
@@ -3082,22 +3071,10 @@
****************************************************************************/
void __exit edgeport_exit (void)
{
- usb_serial_deregister (&edgeport_4_device);
- usb_serial_deregister (&rapidport_4_device);
- usb_serial_deregister (&edgeport_4t_device);
- usb_serial_deregister (&edgeport_2_device);
- usb_serial_deregister (&edgeport_4i_device);
- usb_serial_deregister (&edgeport_2i_device);
- usb_serial_deregister (&edgeport_prl_device);
- usb_serial_deregister (&edgeport_421_device);
- usb_serial_deregister (&edgeport_21_device);
- usb_serial_deregister (&edgeport_8dual_device);
- usb_serial_deregister (&edgeport_8_device);
- usb_serial_deregister (&edgeport_2din_device);
- usb_serial_deregister (&edgeport_4din_device);
- usb_serial_deregister (&edgeport_16dual_device);
- usb_serial_deregister (&edgeport_compat_id_device);
- usb_serial_deregister (&edgeport_8i_device);
+ usb_serial_deregister (&edgeport_1port_device);
+ usb_serial_deregister (&edgeport_2port_device);
+ usb_serial_deregister (&edgeport_4port_device);
+ usb_serial_deregister (&edgeport_8port_device);
}
module_init(edgeport_init);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)