aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_gsm.c
diff options
context:
space:
mode:
authorRuss Gorby <russ.gorby@intel.com>2012-08-13 08:44:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-16 15:03:30 -0400
commit5e44708f75b0f8712da715d6babb0c21089b2317 (patch)
treee5f4f2ecd25649b5d47589ba2cf919c4e92ed222 /drivers/tty/n_gsm.c
parent10c6c383e43565c9c6ec07ff8eb2825f8091bdf0 (diff)
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>
Diffstat (limited to 'drivers/tty/n_gsm.c')
-rw-r--r--drivers/tty/n_gsm.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 5f68f2a70c5c..0d93e51cb23d 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1205,6 +1205,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
1205 u8 *data, int clen) 1205 u8 *data, int clen)
1206{ 1206{
1207 u8 buf[1]; 1207 u8 buf[1];
1208 unsigned long flags;
1209
1208 switch (command) { 1210 switch (command) {
1209 case CMD_CLD: { 1211 case CMD_CLD: {
1210 struct gsm_dlci *dlci = gsm->dlci[0]; 1212 struct gsm_dlci *dlci = gsm->dlci[0];
@@ -1225,7 +1227,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
1225 gsm->constipated = 0; 1227 gsm->constipated = 0;
1226 gsm_control_reply(gsm, CMD_FCON, NULL, 0); 1228 gsm_control_reply(gsm, CMD_FCON, NULL, 0);
1227 /* Kick the link in case it is idling */ 1229 /* Kick the link in case it is idling */
1230 spin_lock_irqsave(&gsm->tx_lock, flags);
1228 gsm_data_kick(gsm); 1231 gsm_data_kick(gsm);
1232 spin_unlock_irqrestore(&gsm->tx_lock, flags);
1229 break; 1233 break;
1230 case CMD_FCOFF: 1234 case CMD_FCOFF:
1231 /* Modem wants us to STFU */ 1235 /* Modem wants us to STFU */
@@ -2392,12 +2396,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
2392 2396
2393 /* Queue poll */ 2397 /* Queue poll */
2394 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); 2398 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
2399 spin_lock_irqsave(&gsm->tx_lock, flags);
2395 gsm_data_kick(gsm); 2400 gsm_data_kick(gsm);
2396 if (gsm->tx_bytes < TX_THRESH_LO) { 2401 if (gsm->tx_bytes < TX_THRESH_LO) {
2397 spin_lock_irqsave(&gsm->tx_lock, flags);
2398 gsm_dlci_data_sweep(gsm); 2402 gsm_dlci_data_sweep(gsm);
2399 spin_unlock_irqrestore(&gsm->tx_lock, flags);
2400 } 2403 }
2404 spin_unlock_irqrestore(&gsm->tx_lock, flags);
2401} 2405}
2402 2406
2403/** 2407/**