This patch enables L2CAP to use HCI channel feature. This can be
used to reflect L2CAP socket properties onto HCI channel.
Change-Id: Iac2b54a1b8204695162491d09161066d90495e06
Signed-off-by: Manoj Kumar Sharma <[email protected]>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap_core.c | 10 +++++++++-
2 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 9b242c6..f26a468 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -410,6 +410,7 @@ struct l2cap_chan {
struct sock *sk;
struct l2cap_conn *conn;
+ struct hci_chan *hchan;
__u8 state;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6f9c25b..e487731 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -300,6 +300,8 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
{
+ struct hci_chan *hchan;
+
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
chan->psm, chan->dcid);
@@ -342,6 +344,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ hchan = hci_chan_create(conn->hcon);
+ chan->hchan = hchan;
+
+
l2cap_chan_hold(chan);
list_add(&chan->list, &conn->chan_l);
@@ -396,6 +402,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
skb_queue_purge(&chan->tx_q);
+ hci_chan_del(chan->hchan);
+
if (chan->mode == L2CAP_MODE_ERTM) {
struct srej_list *l, *tmp;
@@ -596,7 +604,7 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
flags = ACL_START;
bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
- hci_send_acl(chan->conn->hchan, skb, flags);
+ hci_send_acl(chan->hchan, skb, flags);
}
static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
--
1.6.6.1
Hi Andrei,
On 7/24/12, Andrei Emeltchenko <[email protected]> wrote:
> Hi Manoj,
>
> On Tue, Jul 24, 2012 at 01:42:16PM +0530, Manoj Kumar Sharma wrote:
>> This patch enables L2CAP to use HCI channel feature. This can be
>> used to reflect L2CAP socket properties onto HCI channel.
>
> the description is not good. This looks like
> "Move HCI chan from l2cap_conn to l2cap_chan"
I have pushed new patch set with your comments incorporated. Please have a look.
>
>> Change-Id: Iac2b54a1b8204695162491d09161066d90495e06
>> Signed-off-by: Manoj Kumar Sharma <[email protected]>
>> ---
>> include/net/bluetooth/l2cap.h | 1 +
>> net/bluetooth/l2cap_core.c | 10 +++++++++-
>> 2 files changed, 10 insertions(+), 1 deletions(-)
>>
>> diff --git a/include/net/bluetooth/l2cap.h
>> b/include/net/bluetooth/l2cap.h
>> index 9b242c6..f26a468 100644
>> --- a/include/net/bluetooth/l2cap.h
>> +++ b/include/net/bluetooth/l2cap.h
>> @@ -410,6 +410,7 @@ struct l2cap_chan {
>> struct sock *sk;
>>
>> struct l2cap_conn *conn;
>> + struct hci_chan *hchan;
>>
>> __u8 state;
>>
>> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
>> index 6f9c25b..e487731 100644
>> --- a/net/bluetooth/l2cap_core.c
>> +++ b/net/bluetooth/l2cap_core.c
>> @@ -300,6 +300,8 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
>>
>> void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
>> {
>> + struct hci_chan *hchan;
>> +
>> BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
>> chan->psm, chan->dcid);
>>
>> @@ -342,6 +344,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct
>> l2cap_chan *chan)
>> chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
>> chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
>>
>> + hchan = hci_chan_create(conn->hcon);
>> + chan->hchan = hchan;
>> +
>> +
>
> extra new line
Removed extra line in new patch set.
>
>> l2cap_chan_hold(chan);
>>
>> list_add(&chan->list, &conn->chan_l);
>> @@ -396,6 +402,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan,
>> int err)
>>
>> skb_queue_purge(&chan->tx_q);
>>
>> + hci_chan_del(chan->hchan);
>> +
>> if (chan->mode == L2CAP_MODE_ERTM) {
>> struct srej_list *l, *tmp;
>>
>> @@ -596,7 +604,7 @@ static void l2cap_do_send(struct l2cap_chan *chan,
>> struct sk_buff *skb)
>> flags = ACL_START;
>>
>> bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
>> - hci_send_acl(chan->conn->hchan, skb, flags);
>> + hci_send_acl(chan->hchan, skb, flags);
>
> So what about hchan in l2cap_conn structure?
The hchan in l2cap_conn is used for sending L2CAP control signals.
Thus there is one hchan per L2CAP channel created and one already
available will be used only for control signals.
>
> Best regards
> Andrei Emeltchenko
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Best regards,
Manoj Sharma
Hi Manoj,
On Tue, Jul 24, 2012 at 01:42:16PM +0530, Manoj Kumar Sharma wrote:
> This patch enables L2CAP to use HCI channel feature. This can be
> used to reflect L2CAP socket properties onto HCI channel.
the description is not good. This looks like
"Move HCI chan from l2cap_conn to l2cap_chan"
> Change-Id: Iac2b54a1b8204695162491d09161066d90495e06
> Signed-off-by: Manoj Kumar Sharma <[email protected]>
> ---
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/l2cap_core.c | 10 +++++++++-
> 2 files changed, 10 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 9b242c6..f26a468 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -410,6 +410,7 @@ struct l2cap_chan {
> struct sock *sk;
>
> struct l2cap_conn *conn;
> + struct hci_chan *hchan;
>
> __u8 state;
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 6f9c25b..e487731 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -300,6 +300,8 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
>
> void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
> {
> + struct hci_chan *hchan;
> +
> BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
> chan->psm, chan->dcid);
>
> @@ -342,6 +344,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
> chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
> chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
>
> + hchan = hci_chan_create(conn->hcon);
> + chan->hchan = hchan;
> +
> +
extra new line
> l2cap_chan_hold(chan);
>
> list_add(&chan->list, &conn->chan_l);
> @@ -396,6 +402,8 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
>
> skb_queue_purge(&chan->tx_q);
>
> + hci_chan_del(chan->hchan);
> +
> if (chan->mode == L2CAP_MODE_ERTM) {
> struct srej_list *l, *tmp;
>
> @@ -596,7 +604,7 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
> flags = ACL_START;
>
> bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
> - hci_send_acl(chan->conn->hchan, skb, flags);
> + hci_send_acl(chan->hchan, skb, flags);
So what about hchan in l2cap_conn structure?
Best regards
Andrei Emeltchenko
This patch adds a socket option for reserving percentage
bandwidth. This can be useful in reserving bandwidth for AVDTP
channels.
Signed-off-by: Manoj Kumar Sharma <[email protected]>
---
include/net/bluetooth/bluetooth.h | 2 ++
include/net/bluetooth/hci_core.h | 2 ++
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/hci_conn.c | 30 ++++++++++++++++++++++++++++++
net/bluetooth/hci_core.c | 27 ++++++++++++++++++++++++++-
net/bluetooth/l2cap_core.c | 2 ++
net/bluetooth/l2cap_sock.c | 11 +++++++++++
7 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index a65910b..3d30fbb 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -118,6 +118,8 @@ int bt_err(const char *fmt, ...);
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
+#define BT_BANDWIDTH_RESERVE 14
+
/* Connection and socket states */
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index db1c5df..ceff6d6 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -346,6 +346,7 @@ struct hci_chan {
struct hci_conn *conn;
struct sk_buff_head data_q;
unsigned int sent;
+ unsigned int num_pkt_reserved;
};
extern struct list_head hci_dev_list;
@@ -567,6 +568,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
+int hci_chan_reserve_bandwidth(struct hci_chan *chan, __u8 percentage);
int hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f26a468..ec680f6 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -482,6 +482,7 @@ struct l2cap_chan {
__u32 remote_sdu_itime;
__u32 remote_acc_lat;
__u32 remote_flush_to;
+ __u8 bandwidth_reserved;
struct delayed_work chan_timer;
struct delayed_work retrans_timer;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5238b6b..a211c6c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -954,6 +954,36 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
return chan;
}
+int hci_chan_reserve_bandwidth(struct hci_chan *chan, __u8 percentage)
+{
+ struct hci_dev * hdev = chan->conn->hdev;
+ unsigned int num_pkts_requested = (hdev->acl_pkts * percentage + 50) / 100;
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *conn, *n;
+ unsigned int total_pkts_reserved = 0;
+ unsigned int req_pkts_reserved = 0;
+
+ BT_DBG("Packets reserved calculated %d", num_pkts_requested);
+
+ list_for_each_entry_safe(conn, n, &h->list, list) {
+ struct hci_chan *tmp, *ch;
+
+ list_for_each_entry_safe(tmp, ch, &conn->chan_list, list)
+ total_pkts_reserved += tmp->num_pkt_reserved;
+ }
+
+ req_pkts_reserved = total_pkts_reserved
+ + num_pkts_requested - chan->num_pkt_reserved;
+
+ if (req_pkts_reserved >= hdev->acl_pkts)
+ return -EBUSY;
+
+ chan->num_pkt_reserved = num_pkts_requested;
+
+ return 0;
+}
+EXPORT_SYMBOL(hci_chan_reserve_bandwidth);
+
int hci_chan_del(struct hci_chan *chan)
{
struct hci_conn *conn = chan->conn;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d6dc44c..bf365f1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2393,10 +2393,11 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct hci_chan *chan = NULL;
+ struct hci_chan *chan = NULL, *chan_reserved = NULL;
int num = 0, min = ~0, cur_prio = 0;
struct hci_conn *conn;
int cnt, q, conn_num = 0;
+ int num_pkt_reserved = 0;
BT_DBG("%s", hdev->name);
@@ -2419,6 +2420,11 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
if (skb_queue_empty(&tmp->data_q))
continue;
+ num_pkt_reserved += tmp->num_pkt_reserved;
+
+ if (tmp->num_pkt_reserved)
+ chan_reserved = tmp;
+
skb = skb_peek(&tmp->data_q);
if (skb->priority < cur_prio)
continue;
@@ -2464,6 +2470,25 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
q = cnt / num;
*quote = q ? q : 1;
+ if (num_pkt_reserved && chan_reserved &&
+ (chan_reserved->conn->sent < num_pkt_reserved)) {
+ if (!chan->num_pkt_reserved) {
+ int unreserved_credits_left = cnt - num_pkt_reserved;
+
+ if (*quote > unreserved_credits_left)
+ *quote = unreserved_credits_left > 0 ?
+ unreserved_credits_left : 0;
+
+ if (!*quote) {
+ /* Send the packet of reserved channel,
+ * since bandwidth is not available for sending
+ * any packets on other channel.
+ */
+ chan = chan_reserved;
+ *quote = q ? q : 1;
+ }
+ }
+ }
BT_DBG("chan %p quote %d", chan, *quote);
return chan;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e487731..97bc657 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -347,6 +347,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
hchan = hci_chan_create(conn->hcon);
chan->hchan = hchan;
+ if (hchan)
+ hci_chan_reserve_bandwidth(hchan, chan->bandwidth_reserved);
l2cap_chan_hold(chan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 04e7c17..458aca4 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -692,6 +692,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
chan->chan_policy = (u8) opt;
break;
+ case BT_BANDWIDTH_RESERVE:
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+ chan->bandwidth_reserved = opt;
+
+ if (chan->hchan)
+ hci_chan_reserve_bandwidth(chan->hchan, chan->bandwidth_reserved);
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
1.6.6.1