n_gsm: added interlocking for gsm_data_lock for certain code paths
There were some locking holes in the management of the MUX's message queue for 2 code paths: 1) gsmld_write_wakeup 2) receipt of CMD_FCON flow-control message In both cases gsm_data_kick is called w/o locking so it can collide with other other instances of gsm_data_kick (pulling messages tx_tail) or potentially other instances of __gsm_data_queu (adding messages to tx_head) Changed to take the tx_lock in these 2 cases Signed-off-by: Russ Gorby <russ.gorby@intel.com> Tested-by: Yin, Fengwei <fengwei.yin@intel.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Cc: Riding School <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
10c6c383e4
commit
5e44708f75
1 changed files with 6 additions and 2 deletions
|
@ -1205,6 +1205,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
|
||||||
u8 *data, int clen)
|
u8 *data, int clen)
|
||||||
{
|
{
|
||||||
u8 buf[1];
|
u8 buf[1];
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case CMD_CLD: {
|
case CMD_CLD: {
|
||||||
struct gsm_dlci *dlci = gsm->dlci[0];
|
struct gsm_dlci *dlci = gsm->dlci[0];
|
||||||
|
@ -1225,7 +1227,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
|
||||||
gsm->constipated = 0;
|
gsm->constipated = 0;
|
||||||
gsm_control_reply(gsm, CMD_FCON, NULL, 0);
|
gsm_control_reply(gsm, CMD_FCON, NULL, 0);
|
||||||
/* Kick the link in case it is idling */
|
/* Kick the link in case it is idling */
|
||||||
|
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||||
gsm_data_kick(gsm);
|
gsm_data_kick(gsm);
|
||||||
|
spin_unlock_irqrestore(&gsm->tx_lock, flags);
|
||||||
break;
|
break;
|
||||||
case CMD_FCOFF:
|
case CMD_FCOFF:
|
||||||
/* Modem wants us to STFU */
|
/* Modem wants us to STFU */
|
||||||
|
@ -2392,12 +2396,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
|
||||||
|
|
||||||
/* Queue poll */
|
/* Queue poll */
|
||||||
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
|
||||||
|
spin_lock_irqsave(&gsm->tx_lock, flags);
|
||||||
gsm_data_kick(gsm);
|
gsm_data_kick(gsm);
|
||||||
if (gsm->tx_bytes < TX_THRESH_LO) {
|
if (gsm->tx_bytes < TX_THRESH_LO) {
|
||||||
spin_lock_irqsave(&gsm->tx_lock, flags);
|
|
||||||
gsm_dlci_data_sweep(gsm);
|
gsm_dlci_data_sweep(gsm);
|
||||||
spin_unlock_irqrestore(&gsm->tx_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&gsm->tx_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue