aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-04-06 14:28:48 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-04-17 02:03:59 -0400
commit2df012001d36e56cd92dab0255cf4bce3f5b16bc (patch)
tree2257b013b811f00187fbbeb9f8ea223b6a9f2ac4 /net/bluetooth
parent5205185d461d5902325e457ca80bd421127b7308 (diff)
Bluetooth: hidp: handle kernel_sendmsg() errors correctly
We shouldn't push back the skbs if kernel_sendmsg() fails. Instead, we terminate the connection and drop the skb. Only on EAGAIN we push it back and return. l2cap doesn't return EAGAIN, yet, but this guarantees we're safe if it will at some time in the future. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hidp/core.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 481bbb8c7220..3f6ef0630a8e 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -639,13 +639,19 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
639static void hidp_process_intr_transmit(struct hidp_session *session) 639static void hidp_process_intr_transmit(struct hidp_session *session)
640{ 640{
641 struct sk_buff *skb; 641 struct sk_buff *skb;
642 int ret;
642 643
643 BT_DBG("session %p", session); 644 BT_DBG("session %p", session);
644 645
645 while ((skb = skb_dequeue(&session->intr_transmit))) { 646 while ((skb = skb_dequeue(&session->intr_transmit))) {
646 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) { 647 ret = hidp_send_frame(session->intr_sock, skb->data, skb->len);
648 if (ret == -EAGAIN) {
647 skb_queue_head(&session->intr_transmit, skb); 649 skb_queue_head(&session->intr_transmit, skb);
648 break; 650 break;
651 } else if (ret < 0) {
652 hidp_session_terminate(session);
653 kfree_skb(skb);
654 break;
649 } 655 }
650 656
651 hidp_set_timer(session); 657 hidp_set_timer(session);
@@ -656,13 +662,19 @@ static void hidp_process_intr_transmit(struct hidp_session *session)
656static void hidp_process_ctrl_transmit(struct hidp_session *session) 662static void hidp_process_ctrl_transmit(struct hidp_session *session)
657{ 663{
658 struct sk_buff *skb; 664 struct sk_buff *skb;
665 int ret;
659 666
660 BT_DBG("session %p", session); 667 BT_DBG("session %p", session);
661 668
662 while ((skb = skb_dequeue(&session->ctrl_transmit))) { 669 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
663 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) { 670 ret = hidp_send_frame(session->ctrl_sock, skb->data, skb->len);
671 if (ret == -EAGAIN) {
664 skb_queue_head(&session->ctrl_transmit, skb); 672 skb_queue_head(&session->ctrl_transmit, skb);
665 break; 673 break;
674 } else if (ret < 0) {
675 hidp_session_terminate(session);
676 kfree_skb(skb);
677 break;
666 } 678 }
667 679
668 hidp_set_timer(session); 680 hidp_set_timer(session);