Commit a6b5c5dc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tty/serial fixes from Greg KH:
 "Here are some small serial driver fixes, and a larger number of GSM
  line discipline fixes for 5.18-rc5.

  These include:

   - lots of tiny n_gsm fixes for issues to resolve a number of reported
     problems. Seems that people are starting to actually use this code
     again.

   - 8250 driver fixes for some devices

   - imx serial driver fix

   - amba-pl011 driver fix

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'tty-5.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (27 commits)
  tty: n_gsm: fix sometimes uninitialized warning in gsm_dlci_modem_output()
  serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device
  serial: 8250: Also set sticky MCR bits in console restoration
  tty: n_gsm: fix software flow control handling
  tty: n_gsm: fix invalid use of MSC in advanced option
  tty: n_gsm: fix broken virtual tty handling
  Revert "serial: sc16is7xx: Clear RS485 bits in the shutdown"
  tty: n_gsm: fix missing update of modem controls after DLCI open
  serial: 8250: Fix runtime PM for start_tx() for empty buffer
  serial: imx: fix overrun interrupts in DMA mode
  serial: amba-pl011: do not time out prematurely when draining tx fifo
  tty: n_gsm: fix incorrect UA handling
  tty: n_gsm: fix reset fifo race condition
  tty: n_gsm: fix missing tty wakeup in convergence layer type 2
  tty: n_gsm: fix wrong signal octets encoding in MSC
  tty: n_gsm: fix wrong command frame length field encoding
  tty: n_gsm: fix wrong command retry handling
  tty: n_gsm: fix missing explicit ldisc flush
  tty: n_gsm: fix wrong DLCI release order
  tty: n_gsm: fix insufficient txframe size
  ...
parents da1b4042 19317433
Loading
Loading
Loading
Loading
+276 −201
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ module_param(debug, int, 0600);
 */
#define MAX_MRU 1500
#define MAX_MTU 1500
/* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */
#define PROT_OVERHEAD 7
#define	GSM_NET_TX_TIMEOUT (HZ*10)

/*
@@ -219,7 +221,6 @@ struct gsm_mux {
	int encoding;
	u8 control;
	u8 fcs;
	u8 received_fcs;
	u8 *txframe;			/* TX framing buffer */

	/* Method for the receiver side */
@@ -231,6 +232,7 @@ struct gsm_mux {
	int initiator;			/* Did we initiate connection */
	bool dead;			/* Has the mux been shut down */
	struct gsm_dlci *dlci[NUM_DLCI];
	int old_c_iflag;		/* termios c_iflag value before attach */
	bool constipated;		/* Asked by remote to shut up */

	spinlock_t tx_lock;
@@ -271,10 +273,6 @@ static DEFINE_SPINLOCK(gsm_mux_lock);

static struct tty_driver *gsm_tty_driver;

/* Save dlci open address */
static int addr_open[256] = { 0 };
/* Save dlci open count */
static int addr_cnt;
/*
 *	This section of the driver logic implements the GSM encodings
 *	both the basic and the 'advanced'. Reliable transport is not
@@ -369,6 +367,7 @@ static const u8 gsm_fcs8[256] = {
#define GOOD_FCS	0xCF

static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len);
static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk);

/**
 *	gsm_fcs_add	-	update FCS
@@ -832,7 +831,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
			break;
		case 2:	/* Unstructed with modem bits.
		Always one byte as we never send inline break data */
			*dp++ = gsm_encode_modem(dlci);
			*dp++ = (gsm_encode_modem(dlci) << 1) | EA;
			break;
		}
		WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len);
@@ -916,6 +915,66 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
	return size;
}

/**
 *	gsm_dlci_modem_output	-	try and push modem status out of a DLCI
 *	@gsm: mux
 *	@dlci: the DLCI to pull modem status from
 *	@brk: break signal
 *
 *	Push an empty frame in to the transmit queue to update the modem status
 *	bits and to transmit an optional break.
 *
 *	Caller must hold the tx_lock of the mux.
 */

static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci,
				 u8 brk)
{
	u8 *dp = NULL;
	struct gsm_msg *msg;
	int size = 0;

	/* for modem bits without break data */
	switch (dlci->adaption) {
	case 1: /* Unstructured */
		break;
	case 2: /* Unstructured with modem bits. */
		size++;
		if (brk > 0)
			size++;
		break;
	default:
		pr_err("%s: unsupported adaption %d\n", __func__,
		       dlci->adaption);
		return -EINVAL;
	}

	msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype);
	if (!msg) {
		pr_err("%s: gsm_data_alloc error", __func__);
		return -ENOMEM;
	}
	dp = msg->data;
	switch (dlci->adaption) {
	case 1: /* Unstructured */
		break;
	case 2: /* Unstructured with modem bits. */
		if (brk == 0) {
			*dp++ = (gsm_encode_modem(dlci) << 1) | EA;
		} else {
			*dp++ = gsm_encode_modem(dlci) << 1;
			*dp++ = (brk << 4) | 2 | EA; /* Length, Break, EA */
		}
		break;
	default:
		/* Handled above */
		break;
	}

	__gsm_data_queue(dlci, msg);
	return size;
}

/**
 *	gsm_dlci_data_sweep		-	look for data to send
 *	@gsm: the GSM mux
@@ -1093,7 +1152,6 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
{
	unsigned int addr = 0;
	unsigned int modem = 0;
	unsigned int brk = 0;
	struct gsm_dlci *dlci;
	int len = clen;
	int slen;
@@ -1123,17 +1181,8 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
			return;
	}
	len--;
	if (len > 0) {
		while (gsm_read_ea(&brk, *dp++) == 0) {
			len--;
			if (len == 0)
				return;
		}
		modem <<= 7;
		modem |= (brk & 0x7f);
	}
	tty = tty_port_tty_get(&dlci->port);
	gsm_process_modem(tty, dlci, modem, slen);
	gsm_process_modem(tty, dlci, modem, slen - len);
	if (tty) {
		tty_wakeup(tty);
		tty_kref_put(tty);
@@ -1193,7 +1242,6 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen)
}

static void gsm_dlci_begin_close(struct gsm_dlci *dlci);
static void gsm_dlci_close(struct gsm_dlci *dlci);

/**
 *	gsm_control_message	-	DLCI 0 control processing
@@ -1212,28 +1260,15 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
{
	u8 buf[1];
	unsigned long flags;
	struct gsm_dlci *dlci;
	int i;
	int address;

	switch (command) {
	case CMD_CLD: {
		if (addr_cnt > 0) {
			for (i = 0; i < addr_cnt; i++) {
				address = addr_open[i];
				dlci = gsm->dlci[address];
				gsm_dlci_close(dlci);
				addr_open[i] = 0;
			}
		}
		struct gsm_dlci *dlci = gsm->dlci[0];
		/* Modem wishes to close down */
		dlci = gsm->dlci[0];
		if (dlci) {
			dlci->dead = true;
			gsm->dead = true;
			gsm_dlci_close(dlci);
			addr_cnt = 0;
			gsm_response(gsm, 0, UA|PF);
			gsm_dlci_begin_close(dlci);
		}
		}
		break;
@@ -1326,11 +1361,12 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,

static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl)
{
	struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype);
	struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 2, gsm->ftype);
	if (msg == NULL)
		return;
	msg->data[0] = (ctrl->cmd << 1) | 2 | EA;	/* command */
	memcpy(msg->data + 1, ctrl->data, ctrl->len);
	msg->data[0] = (ctrl->cmd << 1) | CR | EA;	/* command */
	msg->data[1] = (ctrl->len << 1) | EA;
	memcpy(msg->data + 2, ctrl->data, ctrl->len);
	gsm_data_queue(gsm->dlci[0], msg);
}

@@ -1353,7 +1389,6 @@ static void gsm_control_retransmit(struct timer_list *t)
	spin_lock_irqsave(&gsm->control_lock, flags);
	ctrl = gsm->pending_cmd;
	if (ctrl) {
		gsm->cretries--;
		if (gsm->cretries == 0) {
			gsm->pending_cmd = NULL;
			ctrl->error = -ETIMEDOUT;
@@ -1362,6 +1397,7 @@ static void gsm_control_retransmit(struct timer_list *t)
			wake_up(&gsm->event);
			return;
		}
		gsm->cretries--;
		gsm_control_transmit(gsm, ctrl);
		mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100);
	}
@@ -1402,7 +1438,7 @@ static struct gsm_control *gsm_control_send(struct gsm_mux *gsm,

	/* If DLCI0 is in ADM mode skip retries, it won't respond */
	if (gsm->dlci[0]->mode == DLCI_MODE_ADM)
		gsm->cretries = 1;
		gsm->cretries = 0;
	else
		gsm->cretries = gsm->n2;

@@ -1450,20 +1486,22 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control)

static void gsm_dlci_close(struct gsm_dlci *dlci)
{
	unsigned long flags;

	del_timer(&dlci->t1);
	if (debug & 8)
		pr_debug("DLCI %d goes closed.\n", dlci->addr);
	dlci->state = DLCI_CLOSED;
	if (dlci->addr != 0) {
		tty_port_tty_hangup(&dlci->port, false);
		spin_lock_irqsave(&dlci->lock, flags);
		kfifo_reset(&dlci->fifo);
		spin_unlock_irqrestore(&dlci->lock, flags);
		/* Ensure that gsmtty_open() can return. */
		tty_port_set_initialized(&dlci->port, 0);
		wake_up_interruptible(&dlci->port.open_wait);
	} else
		dlci->gsm->dead = true;
	/* Unregister gsmtty driver,report gsmtty dev remove uevent for user */
	tty_unregister_device(gsm_tty_driver, dlci->addr);
	wake_up(&dlci->gsm->event);
	/* A DLCI 0 close is a MUX termination so we need to kick that
	   back to userspace somehow */
@@ -1485,8 +1523,9 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
	dlci->state = DLCI_OPEN;
	if (debug & 8)
		pr_debug("DLCI %d goes open.\n", dlci->addr);
	/* Register gsmtty driver,report gsmtty dev add uevent for user */
	tty_register_device(gsm_tty_driver, dlci->addr, NULL);
	/* Send current modem state */
	if (dlci->addr)
		gsm_modem_update(dlci, 0);
	wake_up(&dlci->gsm->event);
}

@@ -1623,6 +1662,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
		tty = tty_port_tty_get(port);
		if (tty) {
			gsm_process_modem(tty, dlci, modem, slen);
			tty_wakeup(tty);
			tty_kref_put(tty);
		}
		fallthrough;
@@ -1793,19 +1833,7 @@ static void gsm_queue(struct gsm_mux *gsm)
	struct gsm_dlci *dlci;
	u8 cr;
	int address;
	int i, j, k, address_tmp;
	/* We have to sneak a look at the packet body to do the FCS.
	   A somewhat layering violation in the spec */

	if ((gsm->control & ~PF) == UI)
		gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
	if (gsm->encoding == 0) {
		/* WARNING: gsm->received_fcs is used for
		gsm->encoding = 0 only.
		In this case it contain the last piece of data
		required to generate final CRC */
		gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
	}
	if (gsm->fcs != GOOD_FCS) {
		gsm->bad_fcs++;
		if (debug & 4)
@@ -1836,11 +1864,6 @@ static void gsm_queue(struct gsm_mux *gsm)
		else {
			gsm_response(gsm, address, UA|PF);
			gsm_dlci_open(dlci);
			/* Save dlci open address */
			if (address) {
				addr_open[addr_cnt] = address;
				addr_cnt++;
			}
		}
		break;
	case DISC|PF:
@@ -1851,35 +1874,9 @@ static void gsm_queue(struct gsm_mux *gsm)
			return;
		}
		/* Real close complete */
		if (!address) {
			if (addr_cnt > 0) {
				for (i = 0; i < addr_cnt; i++) {
					address = addr_open[i];
					dlci = gsm->dlci[address];
					gsm_dlci_close(dlci);
					addr_open[i] = 0;
				}
			}
			dlci = gsm->dlci[0];
			gsm_dlci_close(dlci);
			addr_cnt = 0;
			gsm_response(gsm, 0, UA|PF);
		} else {
		gsm_response(gsm, address, UA|PF);
		gsm_dlci_close(dlci);
			/* clear dlci address */
			for (j = 0; j < addr_cnt; j++) {
				address_tmp = addr_open[j];
				if (address_tmp == address) {
					for (k = j; k < addr_cnt; k++)
						addr_open[k] = addr_open[k+1];
					addr_cnt--;
		break;
				}
			}
		}
		break;
	case UA:
	case UA|PF:
		if (cr == 0 || dlci == NULL)
			break;
@@ -1993,19 +1990,25 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
		break;
	case GSM_DATA:		/* Data */
		gsm->buf[gsm->count++] = c;
		if (gsm->count == gsm->len)
		if (gsm->count == gsm->len) {
			/* Calculate final FCS for UI frames over all data */
			if ((gsm->control & ~PF) != UIH) {
				gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf,
							     gsm->count);
			}
			gsm->state = GSM_FCS;
		}
		break;
	case GSM_FCS:		/* FCS follows the packet */
		gsm->received_fcs = c;
		gsm_queue(gsm);
		gsm->fcs = gsm_fcs_add(gsm->fcs, c);
		gsm->state = GSM_SSOF;
		break;
	case GSM_SSOF:
		if (c == GSM0_SOF) {
		gsm->state = GSM_SEARCH;
			break;
		}
		if (c == GSM0_SOF)
			gsm_queue(gsm);
		else
			gsm->bad_size++;
		break;
	default:
		pr_debug("%s: unhandled state: %d\n", __func__, gsm->state);
@@ -2023,12 +2026,35 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)

static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
{
	/* handle XON/XOFF */
	if ((c & ISO_IEC_646_MASK) == XON) {
		gsm->constipated = true;
		return;
	} else if ((c & ISO_IEC_646_MASK) == XOFF) {
		gsm->constipated = false;
		/* Kick the link in case it is idling */
		gsm_data_kick(gsm, NULL);
		return;
	}
	if (c == GSM1_SOF) {
		/* EOF is only valid in frame if we have got to the data state
		   and received at least one byte (the FCS) */
		if (gsm->state == GSM_DATA && gsm->count) {
			/* Extract the FCS */
		/* EOF is only valid in frame if we have got to the data state */
		if (gsm->state == GSM_DATA) {
			if (gsm->count < 1) {
				/* Missing FSC */
				gsm->malformed++;
				gsm->state = GSM_START;
				return;
			}
			/* Remove the FCS from data */
			gsm->count--;
			if ((gsm->control & ~PF) != UIH) {
				/* Calculate final FCS for UI frames over all
				 * data but FCS
				 */
				gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf,
							     gsm->count);
			}
			/* Add the FCS itself to test against GOOD_FCS */
			gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]);
			gsm->len = gsm->count;
			gsm_queue(gsm);
@@ -2037,6 +2063,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)
		}
		/* Any partial frame was a runt so go back to start */
		if (gsm->state != GSM_START) {
			if (gsm->state != GSM_SEARCH)
				gsm->malformed++;
			gsm->state = GSM_START;
		}
@@ -2106,74 +2133,43 @@ static void gsm_error(struct gsm_mux *gsm)
	gsm->io_error++;
}

static int gsm_disconnect(struct gsm_mux *gsm)
{
	struct gsm_dlci *dlci = gsm->dlci[0];
	struct gsm_control *gc;

	if (!dlci)
		return 0;

	/* In theory disconnecting DLCI 0 is sufficient but for some
	   modems this is apparently not the case. */
	gc = gsm_control_send(gsm, CMD_CLD, NULL, 0);
	if (gc)
		gsm_control_wait(gsm, gc);

	del_timer_sync(&gsm->t2_timer);
	/* Now we are sure T2 has stopped */

	gsm_dlci_begin_close(dlci);
	wait_event_interruptible(gsm->event,
				dlci->state == DLCI_CLOSED);

	if (signal_pending(current))
		return -EINTR;

	return 0;
}

/**
 *	gsm_cleanup_mux		-	generic GSM protocol cleanup
 *	@gsm: our mux
 *	@disc: disconnect link?
 *
 *	Clean up the bits of the mux which are the same for all framing
 *	protocols. Remove the mux from the mux table, stop all the timers
 *	and then shut down each device hanging up the channels as we go.
 */

static void gsm_cleanup_mux(struct gsm_mux *gsm)
static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
{
	int i;
	struct gsm_dlci *dlci = gsm->dlci[0];
	struct gsm_msg *txq, *ntxq;

	gsm->dead = true;
	mutex_lock(&gsm->mutex);

	spin_lock(&gsm_mux_lock);
	for (i = 0; i < MAX_MUX; i++) {
		if (gsm_mux[i] == gsm) {
			gsm_mux[i] = NULL;
			break;
	if (dlci) {
		if (disc && dlci->state != DLCI_CLOSED) {
			gsm_dlci_begin_close(dlci);
			wait_event(gsm->event, dlci->state == DLCI_CLOSED);
		}
		dlci->dead = true;
	}
	spin_unlock(&gsm_mux_lock);
	/* open failed before registering => nothing to do */
	if (i == MAX_MUX)
		return;

	/* Finish outstanding timers, making sure they are done */
	del_timer_sync(&gsm->t2_timer);
	/* Now we are sure T2 has stopped */
	if (dlci)
		dlci->dead = true;

	/* Free up any link layer users */
	mutex_lock(&gsm->mutex);
	for (i = 0; i < NUM_DLCI; i++)
	/* Free up any link layer users and finally the control channel */
	for (i = NUM_DLCI - 1; i >= 0; i--)
		if (gsm->dlci[i])
			gsm_dlci_release(gsm->dlci[i]);
	mutex_unlock(&gsm->mutex);
	/* Now wipe the queues */
	tty_ldisc_flush(gsm->tty);
	list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list)
		kfree(txq);
	INIT_LIST_HEAD(&gsm->tx_list);
@@ -2191,7 +2187,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
static int gsm_activate_mux(struct gsm_mux *gsm)
{
	struct gsm_dlci *dlci;
	int i = 0;

	timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
	init_waitqueue_head(&gsm->event);
@@ -2203,18 +2198,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
	else
		gsm->receive = gsm1_receive;

	spin_lock(&gsm_mux_lock);
	for (i = 0; i < MAX_MUX; i++) {
		if (gsm_mux[i] == NULL) {
			gsm->num = i;
			gsm_mux[i] = gsm;
			break;
		}
	}
	spin_unlock(&gsm_mux_lock);
	if (i == MAX_MUX)
		return -EBUSY;

	dlci = gsm_dlci_alloc(gsm, 0);
	if (dlci == NULL)
		return -ENOMEM;
@@ -2230,6 +2213,15 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
 */
static void gsm_free_mux(struct gsm_mux *gsm)
{
	int i;

	for (i = 0; i < MAX_MUX; i++) {
		if (gsm == gsm_mux[i]) {
			gsm_mux[i] = NULL;
			break;
		}
	}
	mutex_destroy(&gsm->mutex);
	kfree(gsm->txframe);
	kfree(gsm->buf);
	kfree(gsm);
@@ -2249,12 +2241,20 @@ static void gsm_free_muxr(struct kref *ref)

static inline void mux_get(struct gsm_mux *gsm)
{
	unsigned long flags;

	spin_lock_irqsave(&gsm_mux_lock, flags);
	kref_get(&gsm->ref);
	spin_unlock_irqrestore(&gsm_mux_lock, flags);
}

static inline void mux_put(struct gsm_mux *gsm)
{
	unsigned long flags;

	spin_lock_irqsave(&gsm_mux_lock, flags);
	kref_put(&gsm->ref, gsm_free_muxr);
	spin_unlock_irqrestore(&gsm_mux_lock, flags);
}

static inline unsigned int mux_num_to_base(struct gsm_mux *gsm)
@@ -2275,6 +2275,7 @@ static inline unsigned int mux_line_to_num(unsigned int line)

static struct gsm_mux *gsm_alloc_mux(void)
{
	int i;
	struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL);
	if (gsm == NULL)
		return NULL;
@@ -2283,7 +2284,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
		kfree(gsm);
		return NULL;
	}
	gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL);
	gsm->txframe = kmalloc(2 * (MAX_MTU + PROT_OVERHEAD - 1), GFP_KERNEL);
	if (gsm->txframe == NULL) {
		kfree(gsm->buf);
		kfree(gsm);
@@ -2304,6 +2305,26 @@ static struct gsm_mux *gsm_alloc_mux(void)
	gsm->mtu = 64;
	gsm->dead = true;	/* Avoid early tty opens */

	/* Store the instance to the mux array or abort if no space is
	 * available.
	 */
	spin_lock(&gsm_mux_lock);
	for (i = 0; i < MAX_MUX; i++) {
		if (!gsm_mux[i]) {
			gsm_mux[i] = gsm;
			gsm->num = i;
			break;
		}
	}
	spin_unlock(&gsm_mux_lock);
	if (i == MAX_MUX) {
		mutex_destroy(&gsm->mutex);
		kfree(gsm->txframe);
		kfree(gsm->buf);
		kfree(gsm);
		return NULL;
	}

	return gsm;
}

@@ -2339,7 +2360,7 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
	/* Check the MRU/MTU range looks sane */
	if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
		return -EINVAL;
	if (c->n2 < 3)
	if (c->n2 > 255)
		return -EINVAL;
	if (c->encapsulation > 1)	/* Basic, advanced, no I */
		return -EINVAL;
@@ -2370,19 +2391,11 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)

	/*
	 * Close down what is needed, restart and initiate the new
	 * configuration
	 * configuration. On the first time there is no DLCI[0]
	 * and closing or cleaning up is not necessary.
	 */

	if (gsm->initiator && (need_close || need_restart)) {
		int ret;

		ret = gsm_disconnect(gsm);

		if (ret)
			return ret;
	}
	if (need_restart)
		gsm_cleanup_mux(gsm);
	if (need_close || need_restart)
		gsm_cleanup_mux(gsm, true);

	gsm->initiator = c->initiator;
	gsm->mru = c->mru;
@@ -2450,13 +2463,15 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
	int ret, i;

	gsm->tty = tty_kref_get(tty);
	/* Turn off tty XON/XOFF handling to handle it explicitly. */
	gsm->old_c_iflag = tty->termios.c_iflag;
	tty->termios.c_iflag &= (IXON | IXOFF);
	ret =  gsm_activate_mux(gsm);
	if (ret != 0)
		tty_kref_put(gsm->tty);
	else {
		/* Don't register device 0 - this is the control channel and not
		   a usable tty interface */
		if (gsm->initiator) {
		base = mux_num_to_base(gsm); /* Base for this MUX */
		for (i = 1; i < NUM_DLCI; i++) {
			struct device *dev;
@@ -2471,7 +2486,6 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
			}
		}
	}
	}
	return ret;
}

@@ -2490,11 +2504,10 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
	int i;

	WARN_ON(tty != gsm->tty);
	if (gsm->initiator) {
	for (i = 1; i < NUM_DLCI; i++)
		tty_unregister_device(gsm_tty_driver, base + i);
	}
	gsm_cleanup_mux(gsm);
	/* Restore tty XON/XOFF handling. */
	gsm->tty->termios.c_iflag = gsm->old_c_iflag;
	tty_kref_put(gsm->tty);
	gsm->tty = NULL;
}
@@ -2559,6 +2572,12 @@ static void gsmld_close(struct tty_struct *tty)
{
	struct gsm_mux *gsm = tty->disc_data;

	/* The ldisc locks and closes the port before calling our close. This
	 * means we have no way to do a proper disconnect. We will not bother
	 * to do one.
	 */
	gsm_cleanup_mux(gsm, false);

	gsmld_detach_gsm(tty, gsm);

	gsmld_flush_buffer(tty);
@@ -2597,7 +2616,7 @@ static int gsmld_open(struct tty_struct *tty)

	ret = gsmld_attach_gsm(tty, gsm);
	if (ret != 0) {
		gsm_cleanup_mux(gsm);
		gsm_cleanup_mux(gsm, false);
		mux_put(gsm);
	}
	return ret;
@@ -2954,26 +2973,78 @@ static struct tty_ldisc_ops tty_ldisc_packet = {

#define TX_SIZE		512

static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk)
/**
 *	gsm_modem_upd_via_data	-	send modem bits via convergence layer
 *	@dlci: channel
 *	@brk: break signal
 *
 *	Send an empty frame to signal mobile state changes and to transmit the
 *	break signal for adaption 2.
 */

static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk)
{
	u8 modembits[5];
	struct gsm_mux *gsm = dlci->gsm;
	unsigned long flags;

	if (dlci->state != DLCI_OPEN || dlci->adaption != 2)
		return;

	spin_lock_irqsave(&gsm->tx_lock, flags);
	gsm_dlci_modem_output(gsm, dlci, brk);
	spin_unlock_irqrestore(&gsm->tx_lock, flags);
}

/**
 *	gsm_modem_upd_via_msc	-	send modem bits via control frame
 *	@dlci: channel
 *	@brk: break signal
 */

static int gsm_modem_upd_via_msc(struct gsm_dlci *dlci, u8 brk)
{
	u8 modembits[3];
	struct gsm_control *ctrl;
	int len = 2;

	if (brk)
		len++;
	if (dlci->gsm->encoding != 0)
		return 0;

	modembits[0] = len << 1 | EA;		/* Data bytes */
	modembits[1] = dlci->addr << 2 | 3;	/* DLCI, EA, 1 */
	modembits[2] = gsm_encode_modem(dlci) << 1 | EA;
	if (brk)
		modembits[3] = brk << 4 | 2 | EA;	/* Valid, EA */
	ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1);
	modembits[0] = (dlci->addr << 2) | 2 | EA;  /* DLCI, Valid, EA */
	if (!brk) {
		modembits[1] = (gsm_encode_modem(dlci) << 1) | EA;
	} else {
		modembits[1] = gsm_encode_modem(dlci) << 1;
		modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */
		len++;
	}
	ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len);
	if (ctrl == NULL)
		return -ENOMEM;
	return gsm_control_wait(dlci->gsm, ctrl);
}

/**
 *	gsm_modem_update	-	send modem status line state
 *	@dlci: channel
 *	@brk: break signal
 */

static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk)
{
	if (dlci->adaption == 2) {
		/* Send convergence layer type 2 empty data frame. */
		gsm_modem_upd_via_data(dlci, brk);
		return 0;
	} else if (dlci->gsm->encoding == 0) {
		/* Send as MSC control message. */
		return gsm_modem_upd_via_msc(dlci, brk);
	}

	/* Modem status lines are not supported. */
	return -EPROTONOSUPPORT;
}

static int gsm_carrier_raised(struct tty_port *port)
{
	struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
@@ -3006,7 +3077,7 @@ static void gsm_dtr_rts(struct tty_port *port, int onoff)
		modem_tx &= ~(TIOCM_DTR | TIOCM_RTS);
	if (modem_tx != dlci->modem_tx) {
		dlci->modem_tx = modem_tx;
		gsmtty_modem_update(dlci, 0);
		gsm_modem_update(dlci, 0);
	}
}

@@ -3155,13 +3226,17 @@ static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty)
static void gsmtty_flush_buffer(struct tty_struct *tty)
{
	struct gsm_dlci *dlci = tty->driver_data;
	unsigned long flags;

	if (dlci->state == DLCI_CLOSED)
		return;
	/* Caution needed: If we implement reliable transport classes
	   then the data being transmitted can't simply be junked once
	   it has first hit the stack. Until then we can just blow it
	   away */
	spin_lock_irqsave(&dlci->lock, flags);
	kfifo_reset(&dlci->fifo);
	spin_unlock_irqrestore(&dlci->lock, flags);
	/* Need to unhook this DLCI from the transmit queue logic */
}

@@ -3193,7 +3268,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty,

	if (modem_tx != dlci->modem_tx) {
		dlci->modem_tx = modem_tx;
		return gsmtty_modem_update(dlci, 0);
		return gsm_modem_update(dlci, 0);
	}
	return 0;
}
@@ -3254,7 +3329,7 @@ static void gsmtty_throttle(struct tty_struct *tty)
		dlci->modem_tx &= ~TIOCM_RTS;
	dlci->throttled = true;
	/* Send an MSC with RTS cleared */
	gsmtty_modem_update(dlci, 0);
	gsm_modem_update(dlci, 0);
}

static void gsmtty_unthrottle(struct tty_struct *tty)
@@ -3266,7 +3341,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty)
		dlci->modem_tx |= TIOCM_RTS;
	dlci->throttled = false;
	/* Send an MSC with RTS set */
	gsmtty_modem_update(dlci, 0);
	gsm_modem_update(dlci, 0);
}

static int gsmtty_break_ctl(struct tty_struct *tty, int state)
@@ -3284,7 +3359,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
		if (encode > 0x0F)
			encode = 0x0F;	/* Best effort */
	}
	return gsmtty_modem_update(dlci, encode);
	return gsm_modem_update(dlci, encode);
}

static void gsmtty_cleanup(struct tty_struct *tty)
+4 −4
Original line number Diff line number Diff line
@@ -2667,7 +2667,7 @@ enum pci_board_num_t {
	pbn_panacom2,
	pbn_panacom4,
	pbn_plx_romulus,
	pbn_endrun_2_4000000,
	pbn_endrun_2_3906250,
	pbn_oxsemi,
	pbn_oxsemi_1_3906250,
	pbn_oxsemi_2_3906250,
@@ -3195,10 +3195,10 @@ static struct pciserial_board pci_boards[] = {
	* signal now many ports are available
	* 2 port 952 Uart support
	*/
	[pbn_endrun_2_4000000] = {
	[pbn_endrun_2_3906250] = {
		.flags		= FL_BASE0,
		.num_ports	= 2,
		.base_baud	= 4000000,
		.base_baud	= 3906250,
		.uart_offset	= 0x200,
		.first_offset	= 0x1000,
	},
@@ -4115,7 +4115,7 @@ static const struct pci_device_id serial_pci_tbl[] = {
	*/
	{	PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
		pbn_endrun_2_4000000 },
		pbn_endrun_2_3906250 },
	/*
	 * Quatech cards. These actually have configurable clocks but for
	 * now we just use the default.
+3 −3
Original line number Diff line number Diff line
@@ -1675,11 +1675,11 @@ static void serial8250_start_tx(struct uart_port *port)
	struct uart_8250_port *up = up_to_u8250p(port);
	struct uart_8250_em485 *em485 = up->em485;

	serial8250_rpm_get_tx(up);

	if (!port->x_char && uart_circ_empty(&port->state->xmit))
		return;

	serial8250_rpm_get_tx(up);

	if (em485 &&
	    em485->active_timer == &em485->start_tx_timer)
		return;
@@ -3329,7 +3329,7 @@ static void serial8250_console_restore(struct uart_8250_port *up)

	serial8250_set_divisor(port, baud, quot, frac);
	serial_port_out(port, UART_LCR, up->lcr);
	serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
	serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
}

/*
+7 −2
Original line number Diff line number Diff line
@@ -1255,13 +1255,18 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)

static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
{
	/*
	 * To be on the safe side only time out after twice as many iterations
	 * as fifo size.
	 */
	const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2;
	struct uart_port *port = &uap->port;
	int i = 0;
	u32 cr;

	/* Wait until hardware tx queue is empty */
	while (!pl011_tx_empty(port)) {
		if (i == port->fifosize) {
		if (i > MAX_TX_DRAIN_ITERS) {
			dev_warn(port->dev,
				 "timeout while draining hardware tx queue\n");
			break;
@@ -2052,7 +2057,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
	 * with the given baud rate. We use this as the poll interval when we
	 * wait for the tx queue to empty.
	 */
	uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud;
	uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud);

	pl011_setup_status_masks(port, termios);

+1 −1
Original line number Diff line number Diff line
@@ -1448,7 +1448,7 @@ static int imx_uart_startup(struct uart_port *port)
	imx_uart_writel(sport, ucr1, UCR1);

	ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR);
	if (!sport->dma_is_enabled)
	if (!dma_is_inited)
		ucr4 |= UCR4_OREN;
	if (sport->inverted_rx)
		ucr4 |= UCR4_INVR;
Loading