From d57b0e8b8990419b7b7ae0dda5cc4452720b3c7c Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 11 Oct 2011 14:04:31 +0300 Subject: Bluetooth: convert flushable variable to flag in l2cap chan flushable variable inside l2cap_chan is a logical one and can be easily converted to flag. Added flags in l2cap_chan structure. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 61f1f623091..99782cb4f0b 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -446,7 +446,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; case BT_FLUSHABLE: - if (put_user(chan->flushable, (u32 __user *) optval)) + if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), + (u32 __user *) optval)) err = -EFAULT; break; @@ -655,7 +656,10 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch } } - chan->flushable = opt; + if (opt) + set_bit(FLAG_FLUSHABLE, &chan->flags); + else + clear_bit(FLAG_FLUSHABLE, &chan->flags); break; case BT_POWER: @@ -931,7 +935,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->sec_level = pchan->sec_level; chan->role_switch = pchan->role_switch; chan->force_reliable = pchan->force_reliable; - chan->flushable = pchan->flushable; + chan->flags = pchan->flags; chan->force_active = pchan->force_active; } else { @@ -962,7 +966,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->sec_level = BT_SECURITY_LOW; chan->role_switch = 0; chan->force_reliable = 0; - chan->flushable = BT_FLUSHABLE_OFF; + chan->flags = 0; chan->force_active = BT_POWER_FORCE_ACTIVE_ON; } -- cgit v1.2.3 From ecf61bdba845b5e77cf1d5e8620ef54abcfa50ef Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 11 Oct 2011 14:04:32 +0300 Subject: Bluetooth: convert force_reliable variable to flag in l2cap chan force_reliable variable inside l2cap_chan is a logical one and can be easily converted to flag Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 99782cb4f0b..405d736131e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -359,7 +359,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us if (chan->role_switch) opt |= L2CAP_LM_MASTER; - if (chan->force_reliable) + if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) opt |= L2CAP_LM_RELIABLE; if (put_user(opt, (u32 __user *) optval)) @@ -550,7 +550,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us chan->sec_level = BT_SECURITY_HIGH; chan->role_switch = (opt & L2CAP_LM_MASTER); - chan->force_reliable = (opt & L2CAP_LM_RELIABLE); + + if (opt & L2CAP_LM_RELIABLE) + set_bit(FLAG_FORCE_RELIABLE, &chan->flags); + else + clear_bit(FLAG_FORCE_RELIABLE, &chan->flags); break; default: @@ -934,7 +938,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->tx_win = pchan->tx_win; chan->sec_level = pchan->sec_level; chan->role_switch = pchan->role_switch; - chan->force_reliable = pchan->force_reliable; chan->flags = pchan->flags; chan->force_active = pchan->force_active; } else { @@ -965,7 +968,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; chan->sec_level = BT_SECURITY_LOW; chan->role_switch = 0; - chan->force_reliable = 0; chan->flags = 0; chan->force_active = BT_POWER_FORCE_ACTIVE_ON; -- cgit v1.2.3 From 15770b1ab9747de47604da3494e187056b120aff Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 11 Oct 2011 14:04:33 +0300 Subject: Bluetooth: convert force_active variable to flag in l2cap chan force_active variable inside l2cap_chan is a logical one and can be easily converted to flag Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 405d736131e..bf196c67ecb 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -459,7 +459,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; } - pwr.force_active = chan->force_active; + pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); len = min_t(unsigned int, len, sizeof(pwr)); if (copy_to_user(optval, (char *) &pwr, len)) @@ -680,7 +680,11 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch err = -EFAULT; break; } - chan->force_active = pwr.force_active; + + if (pwr.force_active) + set_bit(FLAG_FORCE_ACTIVE, &chan->flags); + else + clear_bit(FLAG_FORCE_ACTIVE, &chan->flags); break; default: @@ -939,7 +943,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->sec_level = pchan->sec_level; chan->role_switch = pchan->role_switch; chan->flags = pchan->flags; - chan->force_active = pchan->force_active; } else { switch (sk->sk_type) { @@ -969,8 +972,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->sec_level = BT_SECURITY_LOW; chan->role_switch = 0; chan->flags = 0; - chan->force_active = BT_POWER_FORCE_ACTIVE_ON; - + set_bit(FLAG_FORCE_ACTIVE, &chan->flags); } /* Default config options */ -- cgit v1.2.3 From 43bd0f32d5cf6593e420b26e2c1c41dc371a47d7 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 11 Oct 2011 14:04:34 +0300 Subject: Bluetooth: convert role_switch variable to flag in l2cap chan role_switch variable inside l2cap_chan is a logical one and can be easily converted to flag Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index bf196c67ecb..48ad8ba492a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -356,7 +356,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us break; } - if (chan->role_switch) + if (test_bit(FLAG_ROLE_SWITCH, &chan->flags)) opt |= L2CAP_LM_MASTER; if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) @@ -549,7 +549,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us if (opt & L2CAP_LM_SECURE) chan->sec_level = BT_SECURITY_HIGH; - chan->role_switch = (opt & L2CAP_LM_MASTER); + if (opt & L2CAP_LM_MASTER) + set_bit(FLAG_ROLE_SWITCH, &chan->flags); + else + clear_bit(FLAG_ROLE_SWITCH, &chan->flags); if (opt & L2CAP_LM_RELIABLE) set_bit(FLAG_FORCE_RELIABLE, &chan->flags); @@ -941,7 +944,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->max_tx = pchan->max_tx; chan->tx_win = pchan->tx_win; chan->sec_level = pchan->sec_level; - chan->role_switch = pchan->role_switch; chan->flags = pchan->flags; } else { @@ -970,7 +972,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->fcs = L2CAP_FCS_CRC16; chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; chan->sec_level = BT_SECURITY_LOW; - chan->role_switch = 0; chan->flags = 0; set_bit(FLAG_FORCE_ACTIVE, &chan->flags); } -- cgit v1.2.3 From 6327eb980d2ff0c96363b81cb0ce580165cb81b8 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 11 Oct 2011 13:37:42 +0300 Subject: Bluetooth: EWS: extended window size option support Adds support for extended window size (EWS) config option. We enable EWS feature in L2CAP Info RSP when hs enabled. EWS option is included in L2CAP Config Req if tx_win (which is set via socket) bigger then standard default value (63) && hs enabled && remote side supports EWS feature. Using EWS selects extended control field in L2CAP. Code partly based on Qualcomm and Atheros patches sent upstream a year ago. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 48ad8ba492a..836d12e66a3 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -331,7 +331,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; - opts.txwin_size = (__u16)chan->tx_win; + opts.txwin_size = chan->tx_win; len = min_t(unsigned int, len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) @@ -501,7 +501,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us opts.mode = chan->mode; opts.fcs = chan->fcs; opts.max_tx = chan->max_tx; - opts.txwin_size = (__u16)chan->tx_win; + opts.txwin_size = chan->tx_win; len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { @@ -509,7 +509,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us break; } - if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) { + if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) { err = -EINVAL; break; } @@ -533,7 +533,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us chan->omtu = opts.omtu; chan->fcs = opts.fcs; chan->max_tx = opts.max_tx; - chan->tx_win = (__u8)opts.txwin_size; + chan->tx_win = opts.txwin_size; break; case L2CAP_LM: -- cgit v1.2.3 From 5e59b791c3561e2fbb4aee17df3505ad25c16b7a Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 1 Nov 2011 10:58:57 +0200 Subject: Bluetooth: set skbuffer priority based on L2CAP socket priority This uses SO_PRIORITY to set the skbuffer priority field Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 836d12e66a3..646aefc4f1d 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -721,7 +721,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms return -ENOTCONN; } - err = l2cap_chan_send(chan, msg, len); + err = l2cap_chan_send(chan, msg, len, sk->sk_priority); release_sock(sk); return err; -- cgit v1.2.3 From 6b3c7104677a731cf6d3638e09d9d6c530b9bc25 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 2 Nov 2011 09:57:10 +0200 Subject: Bluetooth: Initialize tx_win_max for fixed channel tx_win_max is initialized during L2CAP configuration phase. For fixed channels (e.g. A2MP) we want to have it initialized when channel is created. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 646aefc4f1d..9ed6501d90f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -943,6 +943,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->fcs = pchan->fcs; chan->max_tx = pchan->max_tx; chan->tx_win = pchan->tx_win; + chan->tx_win_max = pchan->tx_win_max; chan->sec_level = pchan->sec_level; chan->flags = pchan->flags; } else { @@ -971,6 +972,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) chan->max_tx = L2CAP_DEFAULT_MAX_TX; chan->fcs = L2CAP_FCS_CRC16; chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; + chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; chan->sec_level = BT_SECURITY_LOW; chan->flags = 0; set_bit(FLAG_FORCE_ACTIVE, &chan->flags); -- cgit v1.2.3 From 2ea664822af6705574dfbbf8c77fc7d75a94e9b3 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Wed, 2 Nov 2011 16:18:30 -0700 Subject: Bluetooth: Add channel policy to getsockopt/setsockopt Each channel has a policy to require BR/EDR (the default), prefer BR/EDR, or prefer AMP. Check for valid policy value and L2CAP mode. Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Acked-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_sock.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'net/bluetooth/l2cap_sock.c') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9ed6501d90f..664762e89ec 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -467,6 +467,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch break; + case BT_CHANNEL_POLICY: + if (!enable_hs) { + err = -ENOPROTOOPT; + break; + } + + if (put_user(chan->chan_policy, (u32 __user *) optval)) + err = -EFAULT; + break; + default: err = -ENOPROTOOPT; break; @@ -690,6 +700,31 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch clear_bit(FLAG_FORCE_ACTIVE, &chan->flags); break; + case BT_CHANNEL_POLICY: + if (!enable_hs) { + err = -ENOPROTOOPT; + break; + } + + if (get_user(opt, (u32 __user *) optval)) { + err = -EFAULT; + break; + } + + if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) { + err = -EINVAL; + break; + } + + if (chan->mode != L2CAP_MODE_ERTM && + chan->mode != L2CAP_MODE_STREAMING) { + err = -EOPNOTSUPP; + break; + } + + chan->chan_policy = (u8) opt; + break; + default: err = -ENOPROTOOPT; break; -- cgit v1.2.3