aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2011-11-02 09:52:03 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-11-07 14:24:57 -0500
commit02b20f0bb661829cbd431e5deb2474e909e65cec (patch)
treede363e727b52bf1cdea266fd013b28ccec7a75e1 /net/bluetooth
parentec1cce24d5950e797f10650abf7890ead67c6e64 (diff)
Bluetooth: recalculate priorities when channels are starving
To avoid starvation the priority is recalculated so that the starving channels are promoted to HCI_PRIO_MAX - 1 (6). HCI_PRIO_MAX (7) is considered special, because it requires CAP_NET_ADMIN capability which can be used to provide more guaranties, so it is not used when promoting. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 19e44533fb01..4221fd5b1f4b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2170,6 +2170,53 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
2170 return chan; 2170 return chan;
2171} 2171}
2172 2172
2173static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
2174{
2175 struct hci_conn_hash *h = &hdev->conn_hash;
2176 struct hci_conn *conn;
2177 int num = 0;
2178
2179 BT_DBG("%s", hdev->name);
2180
2181 list_for_each_entry(conn, &h->list, list) {
2182 struct hci_chan_hash *ch;
2183 struct hci_chan *chan;
2184
2185 if (conn->type != type)
2186 continue;
2187
2188 if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
2189 continue;
2190
2191 num++;
2192
2193 ch = &conn->chan_hash;
2194 list_for_each_entry(chan, &ch->list, list) {
2195 struct sk_buff *skb;
2196
2197 if (chan->sent) {
2198 chan->sent = 0;
2199 continue;
2200 }
2201
2202 if (skb_queue_empty(&chan->data_q))
2203 continue;
2204
2205 skb = skb_peek(&chan->data_q);
2206 if (skb->priority >= HCI_PRIO_MAX - 1)
2207 continue;
2208
2209 skb->priority = HCI_PRIO_MAX - 1;
2210
2211 BT_DBG("chan %p skb %p promoted to %d", chan, skb,
2212 skb->priority);
2213 }
2214
2215 if (hci_conn_num(hdev, type) == num)
2216 break;
2217 }
2218}
2219
2173static inline void hci_sched_acl(struct hci_dev *hdev) 2220static inline void hci_sched_acl(struct hci_dev *hdev)
2174{ 2221{
2175 struct hci_chan *chan; 2222 struct hci_chan *chan;
@@ -2215,6 +2262,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
2215 chan->conn->sent++; 2262 chan->conn->sent++;
2216 } 2263 }
2217 } 2264 }
2265
2266 if (cnt != hdev->acl_cnt)
2267 hci_prio_recalculate(hdev, ACL_LINK);
2218} 2268}
2219 2269
2220/* Schedule SCO */ 2270/* Schedule SCO */
@@ -2268,7 +2318,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
2268{ 2318{
2269 struct hci_chan *chan; 2319 struct hci_chan *chan;
2270 struct sk_buff *skb; 2320 struct sk_buff *skb;
2271 int quote, cnt; 2321 int quote, cnt, tmp;
2272 2322
2273 BT_DBG("%s", hdev->name); 2323 BT_DBG("%s", hdev->name);
2274 2324
@@ -2284,6 +2334,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
2284 } 2334 }
2285 2335
2286 cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; 2336 cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
2337 tmp = cnt;
2287 while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) { 2338 while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
2288 u32 priority = (skb_peek(&chan->data_q))->priority; 2339 u32 priority = (skb_peek(&chan->data_q))->priority;
2289 while (quote-- && (skb = skb_peek(&chan->data_q))) { 2340 while (quote-- && (skb = skb_peek(&chan->data_q))) {
@@ -2309,6 +2360,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)
2309 hdev->le_cnt = cnt; 2360 hdev->le_cnt = cnt;
2310 else 2361 else
2311 hdev->acl_cnt = cnt; 2362 hdev->acl_cnt = cnt;
2363
2364 if (cnt != tmp)
2365 hci_prio_recalculate(hdev, LE_LINK);
2312} 2366}
2313 2367
2314static void hci_tx_task(unsigned long arg) 2368static void hci_tx_task(unsigned long arg)