diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 98ec7a3..368628f 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -193,7 +193,8 @@ struct rfcomm_dlc { void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb); void (*state_change)(struct rfcomm_dlc *d, int err); - void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig); + void (*modem_status)(struct rfcomm_dlc *d); + u8 remote_v24_sig; }; /* DLC and session flags */ diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index e4142ea..6a97f02 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1458,8 +1458,9 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb clear_bit(RFCOMM_TX_THROTTLED, &d->flags); rfcomm_dlc_lock(d); + d->remote_v24_sig = msc->v24_sig; if (d->modem_status) - d->modem_status(d, msc->v24_sig); + d->modem_status(d); rfcomm_dlc_unlock(d); rfcomm_send_msc(s, 0, dlci, msc->v24_sig); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index db27f3f..68023be 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -87,7 +87,7 @@ static DEFINE_RWLOCK(rfcomm_dev_lock); static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb); static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); -static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); +static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc); static void rfcomm_tty_wakeup(unsigned long arg); @@ -292,6 +292,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) dlc->owner = dev; dev->dlc = dlc; + + /* Update the modem_status, call under lock */ + rfcomm_dev_modem_status(dlc); rfcomm_dlc_unlock(dlc); /* It's safe to call __module_get() here because socket already @@ -619,9 +622,12 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) } } -static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) +/* This is called under dlc lock, so we can safely mess with dlc here */ +static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc) { struct rfcomm_dev *dev = dlc->owner; + u8 v24_sig = dlc->remote_v24_sig; + if (!dev) return;