return mgsl_get_text_ptr;
}
+/*
+ * tmp_buf is used as a temporary buffer by mgsl_write. We need to
+ * lock it in case the COPY_FROM_USER blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ioports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *tmp_buf;
+
static inline int mgsl_paranoia_check(struct mgsl_struct *info,
char *name, const char *routine)
{
if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
goto cleanup;
- if (!tty || !info->xmit_buf)
+ if (!tty || !info->xmit_buf || !tmp_buf)
goto cleanup;
if ( info->params.mode == MGSL_MODE_HDLC ||
{
struct mgsl_struct *info;
int retval, line;
+ unsigned long page;
unsigned long flags;
/* verify range of specified line number */
goto cleanup;
}
+ if (!tmp_buf) {
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+ if (tmp_buf)
+ free_page(page);
+ else
+ tmp_buf = (unsigned char *) page;
+ }
+
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
kfree(tmp);
}
+ if (tmp_buf) {
+ free_page((unsigned long) tmp_buf);
+ tmp_buf = NULL;
+ }
+
if (pci_registered)
pci_unregister_driver(&synclink_pci_driver);
}
* <15..8> ? RxFIFO IRQ Request Level
*
* Note: For async mode the receive FIFO level must be set
- * to 0 to avoid the situation where the FIFO contains fewer bytes
+ * to 0 to aviod the situation where the FIFO contains fewer bytes
* than the trigger level and no more data is expected.
*
* <7> 0 Exited Hunt IA (Interrupt Arm)
}
info->params.encoding = new_encoding;
- info->params.crc_type = new_crctype;
+ info->params.crc_type = new_crctype;;
/* if network interface up, reprogram hardware */
if (info->netcount)