All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 35/47] Bluetooth: Enable Streaming Mode for L2CAP
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

Streaming Mode is helpful for the Bluetooth streaming based profiles, such
as A2DP. It doesn't have any error control or flow control.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/l2cap.c |   82 +++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 97172f7..7f835e7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1245,6 +1245,39 @@ static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb)
 	return err;
 }
 
+static int l2cap_streaming_send(struct sock *sk)
+{
+	struct sk_buff *skb, *tx_skb;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control;
+	int err;
+
+	while ((skb = sk->sk_send_head)) {
+		tx_skb = skb_clone(skb, GFP_ATOMIC);
+
+		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+		control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+
+		err = l2cap_do_send(sk, tx_skb);
+		if (err < 0) {
+			l2cap_send_disconn_req(pi->conn, sk);
+			return err;
+		}
+
+		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+
+		if (skb_queue_is_last(TX_QUEUE(sk), skb))
+			sk->sk_send_head = NULL;
+		else
+			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
+
+		skb = skb_dequeue(TX_QUEUE(sk));
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
 static int l2cap_ertm_send(struct sock *sk)
 {
 	struct sk_buff *skb, *tx_skb;
@@ -1383,7 +1416,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *ms
 	return skb;
 }
 
-static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
+static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
 {
 	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
 	struct sk_buff *skb;
@@ -1429,7 +1462,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
 
 	__skb_queue_head_init(&sar_queue);
 	control = L2CAP_SDU_START;
-	skb = l2cap_create_ertm_pdu(sk, msg, pi->max_pdu_size, control, len);
+	skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
 
@@ -1449,7 +1482,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
 			buflen = len;
 		}
 
-		skb = l2cap_create_ertm_pdu(sk, msg, buflen, control, 0);
+		skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
 		if (IS_ERR(skb)) {
 			skb_queue_purge(&sar_queue);
 			return PTR_ERR(skb);
@@ -1518,10 +1551,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 		break;
 
 	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
 		/* Entire SDU fits into one PDU */
 		if (len <= pi->max_pdu_size) {
 			control = L2CAP_SDU_UNSEGMENTED;
-			skb = l2cap_create_ertm_pdu(sk, msg, len, control, 0);
+			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
 			if (IS_ERR(skb)) {
 				err = PTR_ERR(skb);
 				goto done;
@@ -1536,7 +1570,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 				goto done;
 		}
 
-		err = l2cap_ertm_send(sk);
+		if (pi->mode == L2CAP_MODE_STREAMING)
+			err = l2cap_streaming_send(sk);
+		else
+			err = l2cap_ertm_send(sk);
+
 		if (!err)
 			err = len;
 		break;
@@ -2050,7 +2088,7 @@ static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
 {
 	u32 local_feat_mask = l2cap_feat_mask;
 	if (enable_ertm)
-		local_feat_mask |= L2CAP_FEAT_ERTM;
+		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
 
 	switch (mode) {
 	case L2CAP_MODE_ERTM:
@@ -2771,7 +2809,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
 		if (enable_ertm)
-			feat_mask |= L2CAP_FEAT_ERTM;
+			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
 		put_unaligned(cpu_to_le32(feat_mask), (__le32 *) rsp->data);
 		l2cap_send_cmd(conn, cmd->ident,
 					L2CAP_INFO_RSP, sizeof(buf), buf);
@@ -3096,7 +3134,9 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
+	struct l2cap_pinfo *pi;
 	u16 control, len;
+	u8 tx_seq;
 	int err;
 
 	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
@@ -3105,19 +3145,21 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		goto drop;
 	}
 
+	pi = l2cap_pi(sk);
+
 	BT_DBG("sk %p, len %d", sk, skb->len);
 
 	if (sk->sk_state != BT_CONNECTED)
 		goto drop;
 
-	switch (l2cap_pi(sk)->mode) {
+	switch (pi->mode) {
 	case L2CAP_MODE_BASIC:
 		/* If socket recv buffers overflows we drop data here
 		 * which is *bad* because L2CAP has to be reliable.
 		 * But we don't have any other choice. L2CAP doesn't
 		 * provide flow control mechanism. */
 
-		if (l2cap_pi(sk)->imtu < skb->len)
+		if (pi->imtu < skb->len)
 			goto drop;
 
 		if (!sock_queue_rcv_skb(sk, skb))
@@ -3149,6 +3191,28 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 			goto done;
 		break;
 
+	case L2CAP_MODE_STREAMING:
+		control = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+		len = skb->len;
+
+		if (__is_sar_start(control))
+			len -= 2;
+
+		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control))
+			goto drop;
+
+		tx_seq = __get_txseq(control);
+
+		if (pi->expected_tx_seq == tx_seq)
+			pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+		else
+			pi->expected_tx_seq = tx_seq + 1;
+
+		err = l2cap_sar_reassembly_sdu(sk, skb, control);
+
+		goto done;
+
 	default:
 		BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode);
 		break;
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 34/47] Bluetooth: Add support for Retransmission and Monitor Timers
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

L2CAP uses retransmission and monitor timers to inquiry the other side
about unacked I-frames. After sending each I-frame we (re)start the
retransmission timer. If it expires, we start a monitor timer that send a
S-frame with P bit set and wait for S-frame with F bit set. If monitor
timer expires, try again, at a maximum of L2CAP_DEFAULT_MAX_TX.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/bluetooth.h |    1 +
 include/net/bluetooth/l2cap.h     |   15 +++++-
 net/bluetooth/l2cap.c             |   86 +++++++++++++++++++++++++++++++++++--
 3 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 65a5cf8..b8b9a84 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -139,6 +139,7 @@ struct bt_skb_cb {
 	__u8 pkt_type;
 	__u8 incoming;
 	__u8 tx_seq;
+	__u8 retries;
 };
 #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
 
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index a1d8ec4..2cf7003 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -31,9 +31,9 @@
 #define L2CAP_DEFAULT_FLUSH_TO		0xffff
 #define L2CAP_DEFAULT_TX_WINDOW		63
 #define L2CAP_DEFAULT_NUM_TO_ACK        (L2CAP_DEFAULT_TX_WINDOW/5)
-#define L2CAP_DEFAULT_MAX_RECEIVE	1
-#define L2CAP_DEFAULT_RETRANS_TO	300    /* 300 milliseconds */
-#define L2CAP_DEFAULT_MONITOR_TO	1000   /* 1 second */
+#define L2CAP_DEFAULT_MAX_TX		3
+#define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
+#define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
 #define L2CAP_DEFAULT_MAX_PDU_SIZE	672
 
 #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
@@ -318,6 +318,7 @@ struct l2cap_pinfo {
 	__u8		req_seq;
 	__u8		expected_tx_seq;
 	__u8		unacked_frames;
+	__u8		retry_count;
 	__u8		num_to_ack;
 	__u16		sdu_len;
 	__u16		partial_sdu_len;
@@ -333,6 +334,8 @@ struct l2cap_pinfo {
 
 	__le16		sport;
 
+	struct timer_list	retrans_timer;
+	struct timer_list	monitor_timer;
 	struct sk_buff_head	tx_queue;
 	struct l2cap_conn	*conn;
 	struct sock		*next_c;
@@ -352,6 +355,12 @@ struct l2cap_pinfo {
 
 #define L2CAP_CONN_SAR_SDU         0x01
 #define L2CAP_CONN_UNDER_REJ       0x02
+#define L2CAP_CONN_WAIT_F          0x04
+
+#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
+		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
+#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \
+		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
 
 static inline int l2cap_tx_window_full(struct sock *sk)
 {
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 35e9f5b..97172f7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1178,6 +1178,39 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 	return 0;
 }
 
+static void l2cap_monitor_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+	u16 control;
+
+	if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
+		l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
+		return;
+	}
+
+	l2cap_pi(sk)->retry_count++;
+	__mod_monitor_timer();
+
+	control = L2CAP_CTRL_POLL;
+	control |= L2CAP_SUPER_RCV_READY;
+	l2cap_send_sframe(l2cap_pi(sk), control);
+}
+
+static void l2cap_retrans_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+	u16 control;
+
+	l2cap_pi(sk)->retry_count = 1;
+	__mod_monitor_timer();
+
+	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+
+	control = L2CAP_CTRL_POLL;
+	control |= L2CAP_SUPER_RCV_READY;
+	l2cap_send_sframe(l2cap_pi(sk), control);
+}
+
 static void l2cap_drop_acked_frames(struct sock *sk)
 {
 	struct sk_buff *skb;
@@ -1192,6 +1225,9 @@ static void l2cap_drop_acked_frames(struct sock *sk)
 		l2cap_pi(sk)->unacked_frames--;
 	}
 
+	if (!l2cap_pi(sk)->unacked_frames)
+		del_timer(&l2cap_pi(sk)->retrans_timer);
+
 	return;
 }
 
@@ -1216,19 +1252,32 @@ static int l2cap_ertm_send(struct sock *sk)
 	u16 control;
 	int err;
 
+	if (pi->conn_state & L2CAP_CONN_WAIT_F)
+		return 0;
+
 	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 
+		if (pi->remote_max_tx &&
+				bt_cb(skb)->retries == pi->remote_max_tx) {
+			l2cap_send_disconn_req(pi->conn, sk);
+			break;
+		}
+
+		bt_cb(skb)->retries++;
+
 		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
 		control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
 				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
+
 		err = l2cap_do_send(sk, tx_skb);
 		if (err < 0) {
 			l2cap_send_disconn_req(pi->conn, sk);
 			return err;
 		}
+		__mod_retrans_timer();
 
 		bt_cb(skb)->tx_seq = pi->next_tx_seq;
 		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
@@ -1365,6 +1414,8 @@ static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg
 		kfree_skb(skb);
 		return ERR_PTR(err);
 	}
+
+	bt_cb(skb)->retries = 0;
 	return skb;
 }
 
@@ -2058,7 +2109,7 @@ done:
 	case L2CAP_MODE_ERTM:
 		rfc.mode            = L2CAP_MODE_ERTM;
 		rfc.txwin_size      = L2CAP_DEFAULT_TX_WINDOW;
-		rfc.max_transmit    = L2CAP_DEFAULT_MAX_RECEIVE;
+		rfc.max_transmit    = L2CAP_DEFAULT_MAX_TX;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
 		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
@@ -2553,6 +2604,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		l2cap_pi(sk)->next_tx_seq = 0;
 		l2cap_pi(sk)->expected_ack_seq = 0;
 		l2cap_pi(sk)->unacked_frames = 0;
+
+		setup_timer(&l2cap_pi(sk)->retrans_timer,
+				l2cap_retrans_timeout, (unsigned long) sk);
+		setup_timer(&l2cap_pi(sk)->monitor_timer,
+				l2cap_monitor_timeout, (unsigned long) sk);
+
 		__skb_queue_head_init(TX_QUEUE(sk));
 		l2cap_chan_ready(sk);
 		goto unlock;
@@ -2662,6 +2719,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
 	skb_queue_purge(TX_QUEUE(sk));
+	del_timer(&l2cap_pi(sk)->retrans_timer);
+	del_timer(&l2cap_pi(sk)->monitor_timer);
 
 	l2cap_chan_del(sk, ECONNRESET);
 	bh_unlock_sock(sk);
@@ -2686,6 +2745,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 		return 0;
 
 	skb_queue_purge(TX_QUEUE(sk));
+	del_timer(&l2cap_pi(sk)->retrans_timer);
+	del_timer(&l2cap_pi(sk)->monitor_timer);
 
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
@@ -2991,9 +3052,26 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 
 	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
 	case L2CAP_SUPER_RCV_READY:
-		pi->expected_ack_seq = __get_reqseq(rx_control);
-		l2cap_drop_acked_frames(sk);
-		l2cap_ertm_send(sk);
+		if (rx_control & L2CAP_CTRL_POLL) {
+			u16 control = L2CAP_CTRL_FINAL;
+			control |= L2CAP_SUPER_RCV_READY;
+			l2cap_send_sframe(l2cap_pi(sk), control);
+		} else if (rx_control & L2CAP_CTRL_FINAL) {
+			if (!(pi->conn_state & L2CAP_CONN_WAIT_F))
+				break;
+
+			pi->conn_state &= ~L2CAP_CONN_WAIT_F;
+			del_timer(&pi->monitor_timer);
+
+			if (pi->unacked_frames > 0)
+				__mod_retrans_timer();
+		} else {
+			pi->expected_ack_seq = __get_reqseq(rx_control);
+			l2cap_drop_acked_frames(sk);
+			if (pi->unacked_frames > 0)
+				__mod_retrans_timer();
+			l2cap_ertm_send(sk);
+		}
 		break;
 
 	case L2CAP_SUPER_REJECT:
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 33/47] Bluetooth: Initial support for retransmission of packets with REJ frames
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

When receiving an I-frame with unexpected txSeq, receiver side start the
recovery procedure by sending a REJ S-frame to the transmitter side. So
the transmitter can re-send the lost I-frame.

This patch just adds a basic support for retransmission, it doesn't
mean that ERTM now has full support for packet retransmission.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/l2cap.h |    1 +
 net/bluetooth/l2cap.c         |   57 +++++++++++++++++++++++++++++++----------
 2 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0afde8d..a1d8ec4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -351,6 +351,7 @@ struct l2cap_pinfo {
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
 #define L2CAP_CONN_SAR_SDU         0x01
+#define L2CAP_CONN_UNDER_REJ       0x02
 
 static inline int l2cap_tx_window_full(struct sock *sk)
 {
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 167e025..35e9f5b 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2951,22 +2951,36 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 
 	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
-	if (tx_seq != pi->expected_tx_seq)
-		return -EINVAL;
+	if (tx_seq == pi->expected_tx_seq) {
+		if (pi->conn_state & L2CAP_CONN_UNDER_REJ)
+			pi->conn_state &= ~L2CAP_CONN_UNDER_REJ;
 
-	err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
-	if (err < 0)
-		return err;
+		err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
+		if (err < 0)
+			return err;
+
+		pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+		pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
+		if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
+			tx_control |= L2CAP_SUPER_RCV_READY;
+			tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+			goto send;
+		}
+	} else {
+		/* Unexpected txSeq. Send a REJ S-frame */
+		kfree_skb(skb);
+		if (!(pi->conn_state & L2CAP_CONN_UNDER_REJ)) {
+			tx_control |= L2CAP_SUPER_REJECT;
+			tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+			pi->conn_state |= L2CAP_CONN_UNDER_REJ;
 
-	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
-	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
-		tx_control |= L2CAP_CTRL_FRAME_TYPE;
-		tx_control |= L2CAP_SUPER_RCV_READY;
-		tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-		err = l2cap_send_sframe(pi, tx_control);
+			goto send;
+		}
 	}
-	return err;
+	return 0;
+
+send:
+	return l2cap_send_sframe(pi, tx_control);
 }
 
 static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
@@ -2982,8 +2996,18 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 		l2cap_ertm_send(sk);
 		break;
 
-	case L2CAP_SUPER_RCV_NOT_READY:
 	case L2CAP_SUPER_REJECT:
+		pi->expected_ack_seq = __get_reqseq(rx_control);
+		l2cap_drop_acked_frames(sk);
+
+		sk->sk_send_head = TX_QUEUE(sk)->next;
+		pi->next_tx_seq = pi->expected_ack_seq;
+
+		l2cap_ertm_send(sk);
+
+		break;
+
+	case L2CAP_SUPER_RCV_NOT_READY:
 	case L2CAP_SUPER_SELECT_REJECT:
 		break;
 	}
@@ -3030,6 +3054,11 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (__is_sar_start(control))
 			len -= 2;
 
+		/*
+		 * We can just drop the corrupted I-frame here.
+		 * Receiver will miss it and start proper recovery
+		 * procedures and ask retransmission.
+		 */
 		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE)
 			goto drop;
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 32/47] Bluetooth: Add support for Segmentation and Reassembly of SDUs
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

ERTM should use Segmentation and Reassembly to break down a SDU in many
PDUs on sending data to the other side.

On sending packets we queue all 'segments' until end of segmentation and
just the add them to the queue for sending. On receiving we create a new
SKB with the SDU reassembled.

Initially based on a patch from Nathan Holstein <nathan@lampreynetworks.com>

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/l2cap.h |    9 ++-
 net/bluetooth/l2cap.c         |  170 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 162 insertions(+), 17 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 9bbfbe7..0afde8d 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -34,7 +34,7 @@
 #define L2CAP_DEFAULT_MAX_RECEIVE	1
 #define L2CAP_DEFAULT_RETRANS_TO	300    /* 300 milliseconds */
 #define L2CAP_DEFAULT_MONITOR_TO	1000   /* 1 second */
-#define L2CAP_DEFAULT_MAX_RX_APDU	0xfff7
+#define L2CAP_DEFAULT_MAX_PDU_SIZE	672
 
 #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
 #define L2CAP_INFO_TIMEOUT	(4000)  /*  4 seconds */
@@ -311,6 +311,7 @@ struct l2cap_pinfo {
 	__u8		conf_req[64];
 	__u8		conf_len;
 	__u8		conf_state;
+	__u8		conn_state;
 
 	__u8		next_tx_seq;
 	__u8		expected_ack_seq;
@@ -318,6 +319,9 @@ struct l2cap_pinfo {
 	__u8		expected_tx_seq;
 	__u8		unacked_frames;
 	__u8		num_to_ack;
+	__u16		sdu_len;
+	__u16		partial_sdu_len;
+	struct sk_buff	*sdu;
 
 	__u8		ident;
 
@@ -346,6 +350,8 @@ struct l2cap_pinfo {
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
+#define L2CAP_CONN_SAR_SDU         0x01
+
 static inline int l2cap_tx_window_full(struct sock *sk)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -363,6 +369,7 @@ static inline int l2cap_tx_window_full(struct sock *sk)
 #define __get_reqseq(ctrl) ((ctrl) & L2CAP_CTRL_REQSEQ) >> 8
 #define __is_iframe(ctrl) !((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 #define __is_sframe(ctrl) (ctrl) & L2CAP_CTRL_FRAME_TYPE
+#define __is_sar_start(ctrl) ((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START
 
 void l2cap_load(void);
 
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 45b8697..167e025 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1334,7 +1334,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *ms
 	return skb;
 }
 
-static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control)
+static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
 {
 	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
 	struct sk_buff *skb;
@@ -1343,6 +1343,9 @@ static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg
 
 	BT_DBG("sk %p len %d", sk, (int)len);
 
+	if (sdulen)
+		hlen += 2;
+
 	count = min_t(unsigned int, (conn->mtu - hlen), len);
 	skb = bt_skb_send_alloc(sk, count + hlen,
 			msg->msg_flags & MSG_DONTWAIT, &err);
@@ -1354,6 +1357,8 @@ static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg
 	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
 	put_unaligned_le16(control, skb_put(skb, 2));
+	if (sdulen)
+		put_unaligned_le16(sdulen, skb_put(skb, 2));
 
 	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
 	if (unlikely(err < 0)) {
@@ -1363,6 +1368,54 @@ static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg
 	return skb;
 }
 
+static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb;
+	struct sk_buff_head sar_queue;
+	u16 control;
+	size_t size = 0;
+
+	__skb_queue_head_init(&sar_queue);
+	control = L2CAP_SDU_START;
+	skb = l2cap_create_ertm_pdu(sk, msg, pi->max_pdu_size, control, len);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	__skb_queue_tail(&sar_queue, skb);
+	len -= pi->max_pdu_size;
+	size +=pi->max_pdu_size;
+	control = 0;
+
+	while (len > 0) {
+		size_t buflen;
+
+		if (len > pi->max_pdu_size) {
+			control |= L2CAP_SDU_CONTINUE;
+			buflen = pi->max_pdu_size;
+		} else {
+			control |= L2CAP_SDU_END;
+			buflen = len;
+		}
+
+		skb = l2cap_create_ertm_pdu(sk, msg, buflen, control, 0);
+		if (IS_ERR(skb)) {
+			skb_queue_purge(&sar_queue);
+			return PTR_ERR(skb);
+		}
+
+		__skb_queue_tail(&sar_queue, skb);
+		len -= buflen;
+		size += buflen;
+		control = 0;
+	}
+	skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
+	if (sk->sk_send_head == NULL)
+		sk->sk_send_head = sar_queue.next;
+
+	return size;
+}
+
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
@@ -1415,21 +1468,22 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 	case L2CAP_MODE_ERTM:
 		/* Entire SDU fits into one PDU */
-		if (len <= pi->omtu) {
+		if (len <= pi->max_pdu_size) {
 			control = L2CAP_SDU_UNSEGMENTED;
-			skb = l2cap_create_ertm_pdu(sk, msg, len, control);
+			skb = l2cap_create_ertm_pdu(sk, msg, len, control, 0);
 			if (IS_ERR(skb)) {
 				err = PTR_ERR(skb);
 				goto done;
 			}
+			__skb_queue_tail(TX_QUEUE(sk), skb);
+			if (sk->sk_send_head == NULL)
+				sk->sk_send_head = skb;
 		} else {
-			/* FIXME: Segmentation will be added later */
-			err = -EINVAL;
-			goto done;
+		/* Segment SDU into multiples PDUs */
+			err = l2cap_sar_segment_sdu(sk, msg, len);
+			if (err < 0)
+				goto done;
 		}
-		__skb_queue_tail(TX_QUEUE(sk), skb);
-		if (sk->sk_send_head == NULL)
-			sk->sk_send_head = skb;
 
 		err = l2cap_ertm_send(sk);
 		if (!err)
@@ -2007,7 +2061,7 @@ done:
 		rfc.max_transmit    = L2CAP_DEFAULT_MAX_RECEIVE;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU);
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -2019,7 +2073,7 @@ done:
 		rfc.max_transmit    = 0;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU);
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -2808,6 +2862,86 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
 	kfree_skb(skb);
 }
 
+static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *_skb;
+	int err = -EINVAL;
+
+	switch (control & L2CAP_CTRL_SAR) {
+	case L2CAP_SDU_UNSEGMENTED:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
+			kfree_skb(pi->sdu);
+			break;
+		}
+
+		err = sock_queue_rcv_skb(sk, skb);
+		if (!err)
+			return 0;
+
+		break;
+
+	case L2CAP_SDU_START:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
+			kfree_skb(pi->sdu);
+			break;
+		}
+
+		pi->sdu_len = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+
+		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
+		if (!pi->sdu) {
+			err = -ENOMEM;
+			break;
+		}
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->conn_state |= L2CAP_CONN_SAR_SDU;
+		pi->partial_sdu_len = skb->len;
+		err = 0;
+		break;
+
+	case L2CAP_SDU_CONTINUE:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			break;
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->partial_sdu_len += skb->len;
+		if (pi->partial_sdu_len > pi->sdu_len)
+			kfree_skb(pi->sdu);
+		else
+			err = 0;
+
+		break;
+
+	case L2CAP_SDU_END:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			break;
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
+		pi->partial_sdu_len += skb->len;
+
+		if (pi->partial_sdu_len == pi->sdu_len) {
+			_skb = skb_clone(pi->sdu, GFP_ATOMIC);
+			err = sock_queue_rcv_skb(sk, _skb);
+			if (err < 0)
+				kfree_skb(_skb);
+		}
+		kfree_skb(pi->sdu);
+		err = 0;
+
+		break;
+	}
+
+	kfree_skb(skb);
+	return err;
+}
+
 static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -2820,11 +2954,11 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 	if (tx_seq != pi->expected_tx_seq)
 		return -EINVAL;
 
-	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-	err = sock_queue_rcv_skb(sk, skb);
-	if (err)
+	err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
+	if (err < 0)
 		return err;
 
+	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
 	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
 	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
 		tx_control |= L2CAP_CTRL_FRAME_TYPE;
@@ -2860,7 +2994,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
-	u16 control;
+	u16 control, len;
 	int err;
 
 	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
@@ -2891,8 +3025,12 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 	case L2CAP_MODE_ERTM:
 		control = get_unaligned_le16(skb->data);
 		skb_pull(skb, 2);
+		len = skb->len;
 
-		if (l2cap_pi(sk)->imtu < skb->len)
+		if (__is_sar_start(control))
+			len -= 2;
+
+		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE)
 			goto drop;
 
 		if (__is_iframe(control))
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 31/47] Bluetooth: Add initial support for ERTM packets transfers
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

This patch adds support for ERTM transfers, without retransmission, with
txWindow up to 63 and with acknowledgement of packets received. Now the
packets are queued before call l2cap_do_send(), so packets couldn't be
sent at the time we call l2cap_sock_sendmsg(). They will be sent in
an asynchronous way on later calls of l2cap_ertm_send(). Besides if an
error occurs on calling l2cap_do_send() we disconnect the channel.

Initially based on a patch from Nathan Holstein <nathan@lampreynetworks.com>

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/bluetooth.h |    3 +-
 include/net/bluetooth/l2cap.h     |   54 +++++-
 net/bluetooth/l2cap.c             |  384 ++++++++++++++++++++++++++++++++-----
 3 files changed, 390 insertions(+), 51 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 968166a..65a5cf8 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -138,8 +138,9 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
 struct bt_skb_cb {
 	__u8 pkt_type;
 	__u8 incoming;
+	__u8 tx_seq;
 };
-#define bt_cb(skb) ((struct bt_skb_cb *)(skb->cb)) 
+#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
 
 static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
 {
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 6fc7698..9bbfbe7 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -29,7 +29,8 @@
 #define L2CAP_DEFAULT_MTU		672
 #define L2CAP_DEFAULT_MIN_MTU		48
 #define L2CAP_DEFAULT_FLUSH_TO		0xffff
-#define L2CAP_DEFAULT_TX_WINDOW		1
+#define L2CAP_DEFAULT_TX_WINDOW		63
+#define L2CAP_DEFAULT_NUM_TO_ACK        (L2CAP_DEFAULT_TX_WINDOW/5)
 #define L2CAP_DEFAULT_MAX_RECEIVE	1
 #define L2CAP_DEFAULT_RETRANS_TO	300    /* 300 milliseconds */
 #define L2CAP_DEFAULT_MONITOR_TO	1000   /* 1 second */
@@ -94,6 +95,31 @@ struct l2cap_conninfo {
 #define L2CAP_FCS_NONE		0x00
 #define L2CAP_FCS_CRC16		0x01
 
+/* L2CAP Control Field bit masks */
+#define L2CAP_CTRL_SAR               0xC000
+#define L2CAP_CTRL_REQSEQ            0x3F00
+#define L2CAP_CTRL_TXSEQ             0x007E
+#define L2CAP_CTRL_RETRANS           0x0080
+#define L2CAP_CTRL_FINAL             0x0080
+#define L2CAP_CTRL_POLL              0x0010
+#define L2CAP_CTRL_SUPERVISE         0x000C
+#define L2CAP_CTRL_FRAME_TYPE        0x0001 /* I- or S-Frame */
+
+#define L2CAP_CTRL_TXSEQ_SHIFT      1
+#define L2CAP_CTRL_REQSEQ_SHIFT     8
+
+/* L2CAP Supervisory Function */
+#define L2CAP_SUPER_RCV_READY           0x0000
+#define L2CAP_SUPER_REJECT              0x0004
+#define L2CAP_SUPER_RCV_NOT_READY       0x0008
+#define L2CAP_SUPER_SELECT_REJECT       0x000C
+
+/* L2CAP Segmentation and Reassembly */
+#define L2CAP_SDU_UNSEGMENTED       0x0000
+#define L2CAP_SDU_START             0x4000
+#define L2CAP_SDU_END               0x8000
+#define L2CAP_SDU_CONTINUE          0xC000
+
 /* L2CAP structures */
 struct l2cap_hdr {
 	__le16     len;
@@ -262,6 +288,7 @@ struct l2cap_conn {
 
 /* ----- L2CAP channel and socket info ----- */
 #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
+#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
 
 struct l2cap_pinfo {
 	struct bt_sock	bt;
@@ -285,6 +312,13 @@ struct l2cap_pinfo {
 	__u8		conf_len;
 	__u8		conf_state;
 
+	__u8		next_tx_seq;
+	__u8		expected_ack_seq;
+	__u8		req_seq;
+	__u8		expected_tx_seq;
+	__u8		unacked_frames;
+	__u8		num_to_ack;
+
 	__u8		ident;
 
 	__u8		remote_tx_win;
@@ -295,6 +329,7 @@ struct l2cap_pinfo {
 
 	__le16		sport;
 
+	struct sk_buff_head	tx_queue;
 	struct l2cap_conn	*conn;
 	struct sock		*next_c;
 	struct sock		*prev_c;
@@ -311,6 +346,23 @@ struct l2cap_pinfo {
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
+static inline int l2cap_tx_window_full(struct sock *sk)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int sub;
+
+	sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64;
+
+	if (sub < 0)
+		sub += 64;
+
+	return (sub == pi->remote_tx_win);
+}
+
+#define __get_txseq(ctrl) ((ctrl) & L2CAP_CTRL_TXSEQ) >> 1
+#define __get_reqseq(ctrl) ((ctrl) & L2CAP_CTRL_REQSEQ) >> 8
+#define __is_iframe(ctrl) !((ctrl) & L2CAP_CTRL_FRAME_TYPE)
+#define __is_sframe(ctrl) (ctrl) & L2CAP_CTRL_FRAME_TYPE
 
 void l2cap_load(void);
 
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index c1b5620..45b8697 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -333,6 +333,30 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16
 	return hci_send_acl(conn->hcon, skb, 0);
 }
 
+static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
+{
+	struct sk_buff *skb;
+	struct l2cap_hdr *lh;
+	struct l2cap_conn *conn = pi->conn;
+	int count;
+
+	BT_DBG("pi %p, control 0x%2.2x", pi, control);
+
+	count = min_t(unsigned int, conn->mtu, L2CAP_HDR_SIZE + 2);
+	control |= L2CAP_CTRL_FRAME_TYPE;
+
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->len = cpu_to_le16(2);
+	lh->cid = cpu_to_le16(pi->dcid);
+	put_unaligned_le16(control, skb_put(skb, 2));
+
+	return hci_send_acl(pi->conn->hcon, skb, 0);
+}
+
 static void l2cap_do_start(struct sock *sk)
 {
 	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -1154,39 +1178,80 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 	return 0;
 }
 
-static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
+static void l2cap_drop_acked_frames(struct sock *sk)
 {
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb, **frag;
-	int err, hlen, count, sent = 0;
-	struct l2cap_hdr *lh;
+	struct sk_buff *skb;
 
-	BT_DBG("sk %p len %d", sk, len);
+	while ((skb = skb_peek(TX_QUEUE(sk)))) {
+		if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
+			break;
 
-	/* First fragment (with L2CAP header) */
-	if (sk->sk_type == SOCK_DGRAM)
-		hlen = L2CAP_HDR_SIZE + 2;
-	else
-		hlen = L2CAP_HDR_SIZE;
+		skb = skb_dequeue(TX_QUEUE(sk));
+		kfree_skb(skb);
 
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
+		l2cap_pi(sk)->unacked_frames--;
+	}
 
-	skb = bt_skb_send_alloc(sk, hlen + count,
-			msg->msg_flags & MSG_DONTWAIT, &err);
-	if (!skb)
-		return err;
+	return;
+}
 
-	/* Create L2CAP header */
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int err;
+
+	BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
+
+	err = hci_send_acl(pi->conn->hcon, skb, 0);
+	if (err < 0)
+		kfree_skb(skb);
+
+	return err;
+}
+
+static int l2cap_ertm_send(struct sock *sk)
+{
+	struct sk_buff *skb, *tx_skb;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control;
+	int err;
+
+	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
+		tx_skb = skb_clone(skb, GFP_ATOMIC);
 
-	if (sk->sk_type == SOCK_DGRAM)
-		put_unaligned(l2cap_pi(sk)->psm, (__le16 *) skb_put(skb, 2));
+		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+		control |= (pi->req_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+
+		err = l2cap_do_send(sk, tx_skb);
+		if (err < 0) {
+			l2cap_send_disconn_req(pi->conn, sk);
+			return err;
+		}
+
+		bt_cb(skb)->tx_seq = pi->next_tx_seq;
+		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+
+		pi->unacked_frames++;
+
+		if (skb_queue_is_last(TX_QUEUE(sk), skb))
+			sk->sk_send_head = NULL;
+		else
+			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
+	}
+
+	return 0;
+}
+
+static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff **frag;
+	int err, sent = 0;
 
 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
-		err = -EFAULT;
-		goto fail;
+		return -EFAULT;
 	}
 
 	sent += count;
@@ -1199,33 +1264,112 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
 
 		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
 		if (!*frag)
-			goto fail;
-
-		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
-			err = -EFAULT;
-			goto fail;
-		}
+			return -EFAULT;
+		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
+			return -EFAULT;
 
 		sent += count;
 		len  -= count;
 
 		frag = &(*frag)->next;
 	}
-	err = hci_send_acl(conn->hcon, skb, 0);
-	if (err < 0)
-		goto fail;
 
 	return sent;
+}
 
-fail:
-	kfree_skb(skb);
-	return err;
+static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+	put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+	return skb;
+}
+
+static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+	return skb;
+}
+
+static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(-ENOMEM);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+	put_unaligned_le16(control, skb_put(skb, 2));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+	return skb;
 }
 
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
-	int err = 0;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb;
+	u16 control;
+	int err;
 
 	BT_DBG("sock %p, sk %p", sock, sk);
 
@@ -1237,16 +1381,67 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 		return -EOPNOTSUPP;
 
 	/* Check outgoing MTU */
-	if (sk->sk_type != SOCK_RAW && len > l2cap_pi(sk)->omtu)
+	if (sk->sk_type == SOCK_SEQPACKET && pi->mode == L2CAP_MODE_BASIC
+			&& len > pi->omtu)
 		return -EINVAL;
 
 	lock_sock(sk);
 
-	if (sk->sk_state == BT_CONNECTED)
-		err = l2cap_do_send(sk, msg, len);
-	else
+	if (sk->sk_state != BT_CONNECTED) {
 		err = -ENOTCONN;
+		goto done;
+	}
+
+	/* Connectionless channel */
+	if (sk->sk_type == SOCK_DGRAM) {
+		skb = l2cap_create_connless_pdu(sk, msg, len);
+		err = l2cap_do_send(sk, skb);
+		goto done;
+	}
 
+	switch (pi->mode) {
+	case L2CAP_MODE_BASIC:
+		/* Create a basic PDU */
+		skb = l2cap_create_basic_pdu(sk, msg, len);
+		if (IS_ERR(skb)) {
+			err = PTR_ERR(skb);
+			goto done;
+		}
+
+		err = l2cap_do_send(sk, skb);
+		if (!err)
+			err = len;
+		break;
+
+	case L2CAP_MODE_ERTM:
+		/* Entire SDU fits into one PDU */
+		if (len <= pi->omtu) {
+			control = L2CAP_SDU_UNSEGMENTED;
+			skb = l2cap_create_ertm_pdu(sk, msg, len, control);
+			if (IS_ERR(skb)) {
+				err = PTR_ERR(skb);
+				goto done;
+			}
+		} else {
+			/* FIXME: Segmentation will be added later */
+			err = -EINVAL;
+			goto done;
+		}
+		__skb_queue_tail(TX_QUEUE(sk), skb);
+		if (sk->sk_send_head == NULL)
+			sk->sk_send_head = skb;
+
+		err = l2cap_ertm_send(sk);
+		if (!err)
+			err = len;
+		break;
+
+	default:
+		BT_DBG("bad state %1.1x", pi->mode);
+		err = -EINVAL;
+	}
+
+done:
 	release_sock(sk);
 	return err;
 }
@@ -2301,6 +2496,10 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
 		sk->sk_state = BT_CONNECTED;
+		l2cap_pi(sk)->next_tx_seq = 0;
+		l2cap_pi(sk)->expected_ack_seq = 0;
+		l2cap_pi(sk)->unacked_frames = 0;
+		__skb_queue_head_init(TX_QUEUE(sk));
 		l2cap_chan_ready(sk);
 		goto unlock;
 	}
@@ -2375,6 +2574,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
 		sk->sk_state = BT_CONNECTED;
+		l2cap_pi(sk)->expected_tx_seq = 0;
+		l2cap_pi(sk)->num_to_ack = 0;
+		__skb_queue_head_init(TX_QUEUE(sk));
 		l2cap_chan_ready(sk);
 	}
 
@@ -2405,6 +2607,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
+	skb_queue_purge(TX_QUEUE(sk));
+
 	l2cap_chan_del(sk, ECONNRESET);
 	bh_unlock_sock(sk);
 
@@ -2427,6 +2631,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 	if (!sk)
 		return 0;
 
+	skb_queue_purge(TX_QUEUE(sk));
+
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
 
@@ -2602,9 +2808,60 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
 	kfree_skb(skb);
 }
 
+static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_txseq(rx_control);
+	u16 tx_control = 0;
+	int err = 0;
+
+	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+
+	if (tx_seq != pi->expected_tx_seq)
+		return -EINVAL;
+
+	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+	err = sock_queue_rcv_skb(sk, skb);
+	if (err)
+		return err;
+
+	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
+	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
+		tx_control |= L2CAP_CTRL_FRAME_TYPE;
+		tx_control |= L2CAP_SUPER_RCV_READY;
+		tx_control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+		err = l2cap_send_sframe(pi, tx_control);
+	}
+	return err;
+}
+
+static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+
+	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
+	case L2CAP_SUPER_RCV_READY:
+		pi->expected_ack_seq = __get_reqseq(rx_control);
+		l2cap_drop_acked_frames(sk);
+		l2cap_ertm_send(sk);
+		break;
+
+	case L2CAP_SUPER_RCV_NOT_READY:
+	case L2CAP_SUPER_REJECT:
+	case L2CAP_SUPER_SELECT_REJECT:
+		break;
+	}
+
+	return 0;
+}
+
 static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
+	u16 control;
+	int err;
 
 	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
 	if (!sk) {
@@ -2617,16 +2874,40 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 	if (sk->sk_state != BT_CONNECTED)
 		goto drop;
 
-	if (l2cap_pi(sk)->imtu < skb->len)
-		goto drop;
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		/* If socket recv buffers overflows we drop data here
+		 * which is *bad* because L2CAP has to be reliable.
+		 * But we don't have any other choice. L2CAP doesn't
+		 * provide flow control mechanism. */
 
-	/* If socket recv buffers overflows we drop data here
-	 * which is *bad* because L2CAP has to be reliable.
-	 * But we don't have any other choice. L2CAP doesn't
-	 * provide flow control mechanism. */
+		if (l2cap_pi(sk)->imtu < skb->len)
+			goto drop;
 
-	if (!sock_queue_rcv_skb(sk, skb))
-		goto done;
+		if (!sock_queue_rcv_skb(sk, skb))
+			goto done;
+		break;
+
+	case L2CAP_MODE_ERTM:
+		control = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+
+		if (l2cap_pi(sk)->imtu < skb->len)
+			goto drop;
+
+		if (__is_iframe(control))
+			err = l2cap_data_channel_iframe(sk, control, skb);
+		else
+			err = l2cap_data_channel_sframe(sk, control, skb);
+
+		if (!err)
+			goto done;
+		break;
+
+	default:
+		BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode);
+		break;
+	}
 
 drop:
 	kfree_skb(skb);
@@ -2676,6 +2957,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 	cid = __le16_to_cpu(lh->cid);
 	len = __le16_to_cpu(lh->len);
 
+	if (len != skb->len) {
+		kfree_skb(skb);
+		return;
+	}
+
 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
 
 	switch (cid) {
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 30/47] Bluetooth: Create separate l2cap_send_disconn_req() function
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

The code for sending a disconnect request was repeated several times
within L2CAP source code. So move this into its own function.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/l2cap.c |   46 ++++++++++++++++------------------------------
 1 files changed, 16 insertions(+), 30 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index af0fbf9..c1b5620 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -366,6 +366,16 @@ static void l2cap_do_start(struct sock *sk)
 	}
 }
 
+static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
+{
+	struct l2cap_disconn_req req;
+
+	req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+	l2cap_send_cmd(conn, l2cap_get_ident(conn),
+			L2CAP_DISCONN_REQ, sizeof(req), &req);
+}
+
 /* ---- L2CAP connections ---- */
 static void l2cap_conn_start(struct l2cap_conn *conn)
 {
@@ -650,15 +660,10 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
 	case BT_CONFIG:
 		if (sk->sk_type == SOCK_SEQPACKET) {
 			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-			struct l2cap_disconn_req req;
 
 			sk->sk_state = BT_DISCONN;
 			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
-			req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
-			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-			l2cap_send_cmd(conn, l2cap_get_ident(conn),
-					L2CAP_DISCONN_REQ, sizeof(req), &req);
+			l2cap_send_disconn_req(conn, sk);
 		} else
 			l2cap_chan_del(sk, reason);
 		break;
@@ -1786,13 +1791,8 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
 	case L2CAP_MODE_STREAMING:
 	case L2CAP_MODE_ERTM:
 		pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
-		if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask)) {
-			struct l2cap_disconn_req req;
-			req.dcid = cpu_to_le16(pi->dcid);
-			req.scid = cpu_to_le16(pi->scid);
-			l2cap_send_cmd(pi->conn, l2cap_get_ident(pi->conn),
-					L2CAP_DISCONN_REQ, sizeof(req), &req);
-		}
+		if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
+			l2cap_send_disconn_req(pi->conn, sk);
 		break;
 	default:
 		pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
@@ -2286,11 +2286,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	/* Complete config. */
 	len = l2cap_parse_conf_req(sk, rsp);
 	if (len < 0) {
-		struct l2cap_disconn_req req;
-		req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
-		req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-		l2cap_send_cmd(conn, l2cap_get_ident(conn),
-					L2CAP_DISCONN_REQ, sizeof(req), &req);
+		l2cap_send_disconn_req(conn, sk);
 		goto unlock;
 	}
 
@@ -2352,11 +2348,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 			len = l2cap_parse_conf_rsp(sk, rsp->data,
 							len, req, &result);
 			if (len < 0) {
-				struct l2cap_disconn_req req;
-				req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
-				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-				l2cap_send_cmd(conn, l2cap_get_ident(conn),
-					L2CAP_DISCONN_REQ, sizeof(req), &req);
+				l2cap_send_disconn_req(conn, sk);
 				goto done;
 			}
 
@@ -2372,13 +2364,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		sk->sk_state = BT_DISCONN;
 		sk->sk_err = ECONNRESET;
 		l2cap_sock_set_timer(sk, HZ * 5);
-		{
-			struct l2cap_disconn_req req;
-			req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
-			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-			l2cap_send_cmd(conn, l2cap_get_ident(conn),
-					L2CAP_DISCONN_REQ, sizeof(req), &req);
-		}
+		l2cap_send_disconn_req(conn, sk);
 		goto done;
 	}
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 29/47] Bluetooth: Add configuration support for ERTM and Streaming mode
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>

Add support to config_req and config_rsp to configure ERTM and Streaming
mode. If the remote device specifies ERTM or Streaming mode, then the
same mode is proposed. Otherwise ERTM or Basic mode is used. And in case
of a state 2 device, the remote device should propose the same mode. If
not, then the channel gets disconnected.

Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/l2cap.h |   28 ++++-
 net/bluetooth/l2cap.c         |  262 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 255 insertions(+), 35 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 06b072f..6fc7698 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -27,8 +27,9 @@
 
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU		672
+#define L2CAP_DEFAULT_MIN_MTU		48
 #define L2CAP_DEFAULT_FLUSH_TO		0xffff
-#define L2CAP_DEFAULT_RX_WINDOW		1
+#define L2CAP_DEFAULT_TX_WINDOW		1
 #define L2CAP_DEFAULT_MAX_RECEIVE	1
 #define L2CAP_DEFAULT_RETRANS_TO	300    /* 300 milliseconds */
 #define L2CAP_DEFAULT_MONITOR_TO	1000   /* 1 second */
@@ -272,6 +273,9 @@ struct l2cap_pinfo {
 	__u16		omtu;
 	__u16		flush_to;
 	__u8		mode;
+	__u8		num_conf_req;
+	__u8		num_conf_rsp;
+
 	__u8		fcs;
 	__u8		sec_level;
 	__u8		role_switch;
@@ -280,10 +284,15 @@ struct l2cap_pinfo {
 	__u8		conf_req[64];
 	__u8		conf_len;
 	__u8		conf_state;
-	__u8		conf_retry;
 
 	__u8		ident;
 
+	__u8		remote_tx_win;
+	__u8		remote_max_tx;
+	__u16		retrans_timeout;
+	__u16		monitor_timeout;
+	__u16		max_pdu_size;
+
 	__le16		sport;
 
 	struct l2cap_conn	*conn;
@@ -291,12 +300,17 @@ struct l2cap_pinfo {
 	struct sock		*prev_c;
 };
 
-#define L2CAP_CONF_REQ_SENT	0x01
-#define L2CAP_CONF_INPUT_DONE	0x02
-#define L2CAP_CONF_OUTPUT_DONE	0x04
-#define L2CAP_CONF_CONNECT_PEND	0x80
+#define L2CAP_CONF_REQ_SENT       0x01
+#define L2CAP_CONF_INPUT_DONE     0x02
+#define L2CAP_CONF_OUTPUT_DONE    0x04
+#define L2CAP_CONF_MTU_DONE       0x08
+#define L2CAP_CONF_MODE_DONE      0x10
+#define L2CAP_CONF_CONNECT_PEND   0x20
+#define L2CAP_CONF_STATE2_DEVICE  0x80
+
+#define L2CAP_CONF_MAX_CONF_REQ 2
+#define L2CAP_CONF_MAX_CONF_RSP 2
 
-#define L2CAP_CONF_MAX_RETRIES	2
 
 void l2cap_load(void);
 
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 7ce1a24..af0fbf9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -966,6 +966,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 	case L2CAP_MODE_BASIC:
 		break;
 	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
 		if (enable_ertm)
 			break;
 		/* fall through */
@@ -1029,6 +1030,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 	case L2CAP_MODE_BASIC:
 		break;
 	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
 		if (enable_ertm)
 			break;
 		/* fall through */
@@ -1739,15 +1741,65 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 	*ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
+static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
+{
+	u32 local_feat_mask = l2cap_feat_mask;
+	if (enable_ertm)
+		local_feat_mask |= L2CAP_FEAT_ERTM;
+
+	switch (mode) {
+	case L2CAP_MODE_ERTM:
+		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
+	case L2CAP_MODE_STREAMING:
+		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
+	default:
+		return 0x00;
+	}
+}
+
+static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
+{
+	switch (mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		if (l2cap_mode_supported(mode, remote_feat_mask))
+			return mode;
+		/* fall through */
+	default:
+		return L2CAP_MODE_BASIC;
+	}
+}
+
 static int l2cap_build_conf_req(struct sock *sk, void *data)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_conf_req *req = data;
-	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
+	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_ERTM };
 	void *ptr = req->data;
 
 	BT_DBG("sk %p", sk);
 
+	if (pi->num_conf_req || pi->num_conf_rsp)
+		goto done;
+
+	switch (pi->mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+		if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask)) {
+			struct l2cap_disconn_req req;
+			req.dcid = cpu_to_le16(pi->dcid);
+			req.scid = cpu_to_le16(pi->scid);
+			l2cap_send_cmd(pi->conn, l2cap_get_ident(pi->conn),
+					L2CAP_DISCONN_REQ, sizeof(req), &req);
+		}
+		break;
+	default:
+		pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+		break;
+	}
+
+done:
 	switch (pi->mode) {
 	case L2CAP_MODE_BASIC:
 		if (pi->imtu != L2CAP_DEFAULT_MTU)
@@ -1756,10 +1808,22 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
 
 	case L2CAP_MODE_ERTM:
 		rfc.mode            = L2CAP_MODE_ERTM;
-		rfc.txwin_size      = L2CAP_DEFAULT_RX_WINDOW;
+		rfc.txwin_size      = L2CAP_DEFAULT_TX_WINDOW;
 		rfc.max_transmit    = L2CAP_DEFAULT_MAX_RECEIVE;
-		rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
-		rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+		rfc.retrans_timeout = 0;
+		rfc.monitor_timeout = 0;
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU);
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+		break;
+
+	case L2CAP_MODE_STREAMING:
+		rfc.mode            = L2CAP_MODE_STREAMING;
+		rfc.txwin_size      = 0;
+		rfc.max_transmit    = 0;
+		rfc.retrans_timeout = 0;
+		rfc.monitor_timeout = 0;
 		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
@@ -1825,30 +1889,83 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
 		}
 	}
 
+	if (pi->num_conf_rsp || pi->num_conf_req)
+		goto done;
+
+	switch (pi->mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+		if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
+			return -ECONNREFUSED;
+		break;
+	default:
+		pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+		break;
+	}
+
+done:
+	if (pi->mode != rfc.mode) {
+		result = L2CAP_CONF_UNACCEPT;
+		rfc.mode = pi->mode;
+
+		if (pi->num_conf_rsp == 1)
+			return -ECONNREFUSED;
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+	}
+
+
 	if (result == L2CAP_CONF_SUCCESS) {
 		/* Configure output options and let the other side know
 		 * which ones we don't like. */
 
-		if (rfc.mode == L2CAP_MODE_BASIC) {
-			if (mtu < pi->omtu)
-				result = L2CAP_CONF_UNACCEPT;
-			else {
-				pi->omtu = mtu;
-				pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
-			}
+		if (mtu < L2CAP_DEFAULT_MIN_MTU)
+			result = L2CAP_CONF_UNACCEPT;
+		else {
+			pi->omtu = mtu;
+			pi->conf_state |= L2CAP_CONF_MTU_DONE;
+		}
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
 
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
-		} else {
+		switch (rfc.mode) {
+		case L2CAP_MODE_BASIC:
+			pi->fcs = L2CAP_FCS_NONE;
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+			break;
+
+		case L2CAP_MODE_ERTM:
+			pi->remote_tx_win = rfc.txwin_size;
+			pi->remote_max_tx = rfc.max_transmit;
+			pi->max_pdu_size = rfc.max_pdu_size;
+
+			rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+			rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+			break;
+
+		case L2CAP_MODE_STREAMING:
+			pi->remote_tx_win = rfc.txwin_size;
+			pi->max_pdu_size = rfc.max_pdu_size;
+
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+			break;
+
+		default:
 			result = L2CAP_CONF_UNACCEPT;
 
 			memset(&rfc, 0, sizeof(rfc));
-			rfc.mode = L2CAP_MODE_BASIC;
+			rfc.mode = pi->mode;
+		}
 
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
-		}
-	}
 
+		if (result == L2CAP_CONF_SUCCESS)
+			pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+	}
 	rsp->scid   = cpu_to_le16(pi->dcid);
 	rsp->result = cpu_to_le16(result);
 	rsp->flags  = cpu_to_le16(0x0000);
@@ -1856,6 +1973,73 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
 	return ptr - data;
 }
 
+static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_conf_req *req = data;
+	void *ptr = req->data;
+	int type, olen;
+	unsigned long val;
+	struct l2cap_conf_rfc rfc;
+
+	BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
+
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
+
+		switch (type) {
+		case L2CAP_CONF_MTU:
+			if (val < L2CAP_DEFAULT_MIN_MTU) {
+				*result = L2CAP_CONF_UNACCEPT;
+				pi->omtu = L2CAP_DEFAULT_MIN_MTU;
+			} else
+				pi->omtu = val;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+			break;
+
+		case L2CAP_CONF_FLUSH_TO:
+			pi->flush_to = val;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
+							2, pi->flush_to);
+			break;
+
+		case L2CAP_CONF_RFC:
+			if (olen == sizeof(rfc))
+				memcpy(&rfc, (void *)val, olen);
+
+			if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+							rfc.mode != pi->mode)
+				return -ECONNREFUSED;
+
+			pi->mode = rfc.mode;
+			pi->fcs = 0;
+
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+			break;
+		}
+	}
+
+	if (*result == L2CAP_CONF_SUCCESS) {
+		switch (rfc.mode) {
+		case L2CAP_MODE_ERTM:
+			pi->remote_tx_win   = rfc.txwin_size;
+			pi->retrans_timeout = rfc.retrans_timeout;
+			pi->monitor_timeout = rfc.monitor_timeout;
+			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
+			break;
+		case L2CAP_MODE_STREAMING:
+			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
+			break;
+		}
+	}
+
+	req->dcid   = cpu_to_le16(pi->dcid);
+	req->flags  = cpu_to_le16(0x0000);
+
+	return ptr - data;
+}
+
 static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
 {
 	struct l2cap_conf_rsp *rsp = data;
@@ -2042,6 +2226,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(sk, req), req);
+		l2cap_pi(sk)->num_conf_req++;
 		break;
 
 	case L2CAP_CR_PEND:
@@ -2100,10 +2285,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	/* Complete config. */
 	len = l2cap_parse_conf_req(sk, rsp);
-	if (len < 0)
+	if (len < 0) {
+		struct l2cap_disconn_req req;
+		req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+		req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+		l2cap_send_cmd(conn, l2cap_get_ident(conn),
+					L2CAP_DISCONN_REQ, sizeof(req), &req);
 		goto unlock;
+	}
 
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
+	l2cap_pi(sk)->num_conf_rsp++;
 
 	/* Reset config buffer. */
 	l2cap_pi(sk)->conf_len = 0;
@@ -2121,6 +2313,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		u8 buf[64];
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(sk, buf), buf);
+		l2cap_pi(sk)->num_conf_req++;
 	}
 
 unlock:
@@ -2150,16 +2343,29 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		break;
 
 	case L2CAP_CONF_UNACCEPT:
-		if (++l2cap_pi(sk)->conf_retry < L2CAP_CONF_MAX_RETRIES) {
-			char req[128];
-			/* It does not make sense to adjust L2CAP parameters
-			 * that are currently defined in the spec. We simply
-			 * resend config request that we sent earlier. It is
-			 * stupid, but it helps qualification testing which
-			 * expects at least some response from us. */
-			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-						l2cap_build_conf_req(sk, req), req);
-			goto done;
+		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
+			int len = cmd->len - sizeof(*rsp);
+			char req[64];
+
+			/* throw out any old stored conf requests */
+			result = L2CAP_CONF_SUCCESS;
+			len = l2cap_parse_conf_rsp(sk, rsp->data,
+							len, req, &result);
+			if (len < 0) {
+				struct l2cap_disconn_req req;
+				req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+				l2cap_send_cmd(conn, l2cap_get_ident(conn),
+					L2CAP_DISCONN_REQ, sizeof(req), &req);
+				goto done;
+			}
+
+			l2cap_send_cmd(conn, l2cap_get_ident(conn),
+						L2CAP_CONF_REQ, len, req);
+			l2cap_pi(sk)->num_conf_req++;
+			if (result != L2CAP_CONF_SUCCESS)
+				goto done;
+			break;
 		}
 
 	default:
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 28/47] Bluetooth: Add L2CAP RFC option if ERTM is enabled
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

When trying to establish a connection with Enhanced Retransmission mode
enabled, the RFC option needs to be added to the configuration.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/l2cap.c |   23 ++++++++++++++++++++---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 8a59e57..7ce1a24 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1743,12 +1743,29 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_conf_req *req = data;
+	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
 	void *ptr = req->data;
 
 	BT_DBG("sk %p", sk);
 
-	if (pi->imtu != L2CAP_DEFAULT_MTU)
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+	switch (pi->mode) {
+	case L2CAP_MODE_BASIC:
+		if (pi->imtu != L2CAP_DEFAULT_MTU)
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+		break;
+
+	case L2CAP_MODE_ERTM:
+		rfc.mode            = L2CAP_MODE_ERTM;
+		rfc.txwin_size      = L2CAP_DEFAULT_RX_WINDOW;
+		rfc.max_transmit    = L2CAP_DEFAULT_MAX_RECEIVE;
+		rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+		rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_RX_APDU);
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+		break;
+	}
 
 	/* FIXME: Need actual value of the flush timeout */
 	//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
@@ -1828,7 +1845,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
 			rfc.mode = L2CAP_MODE_BASIC;
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-						sizeof(rfc), (unsigned long) &rfc);
+					sizeof(rfc), (unsigned long) &rfc);
 		}
 	}
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 27/47] Bluetooth: Allow setting of L2CAP ERTM via socket option
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

To enable Enhanced Retransmission mode it needs to be set via a socket
option. A different mode can be set on a socket, but on listen() and
connect() the mode is checked and ERTM is only allowed if it is enabled
via the module parameter.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/l2cap.h |    8 +++++---
 net/bluetooth/l2cap.c         |   37 +++++++++++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index e919fca..06b072f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -190,7 +190,7 @@ struct l2cap_conf_rfc {
 #define L2CAP_MODE_RETRANS	0x01
 #define L2CAP_MODE_FLOWCTL	0x02
 #define L2CAP_MODE_ERTM		0x03
-#define L2CAP_MODE_STREAM	0x04
+#define L2CAP_MODE_STREAMING	0x04
 
 struct l2cap_disconn_req {
 	__le16     dcid;
@@ -271,9 +271,11 @@ struct l2cap_pinfo {
 	__u16		imtu;
 	__u16		omtu;
 	__u16		flush_to;
-	__u8            sec_level;
+	__u8		mode;
+	__u8		fcs;
+	__u8		sec_level;
 	__u8		role_switch;
-	__u8            force_reliable;
+	__u8		force_reliable;
 
 	__u8		conf_req[64];
 	__u8		conf_len;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 810a3c1..8a59e57 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -717,12 +717,16 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 
 		pi->imtu = l2cap_pi(parent)->imtu;
 		pi->omtu = l2cap_pi(parent)->omtu;
+		pi->mode = l2cap_pi(parent)->mode;
+		pi->fcs  = l2cap_pi(parent)->fcs;
 		pi->sec_level = l2cap_pi(parent)->sec_level;
 		pi->role_switch = l2cap_pi(parent)->role_switch;
 		pi->force_reliable = l2cap_pi(parent)->force_reliable;
 	} else {
 		pi->imtu = L2CAP_DEFAULT_MTU;
 		pi->omtu = 0;
+		pi->mode = L2CAP_MODE_BASIC;
+		pi->fcs  = L2CAP_FCS_CRC16;
 		pi->sec_level = BT_SECURITY_LOW;
 		pi->role_switch = 0;
 		pi->force_reliable = 0;
@@ -958,6 +962,18 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 		goto done;
 	}
 
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+		if (enable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
 	switch (sk->sk_state) {
 	case BT_CONNECT:
 	case BT_CONNECT2:
@@ -1009,6 +1025,18 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 		goto done;
 	}
 
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+		if (enable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
 	if (!l2cap_pi(sk)->psm) {
 		bdaddr_t *src = &bt_sk(sk)->src;
 		u16 psm;
@@ -1259,7 +1287,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 		opts.imtu     = l2cap_pi(sk)->imtu;
 		opts.omtu     = l2cap_pi(sk)->omtu;
 		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = L2CAP_MODE_BASIC;
+		opts.mode     = l2cap_pi(sk)->mode;
 
 		len = min_t(unsigned int, sizeof(opts), optlen);
 		if (copy_from_user((char *) &opts, optval, len)) {
@@ -1267,8 +1295,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 			break;
 		}
 
-		l2cap_pi(sk)->imtu  = opts.imtu;
-		l2cap_pi(sk)->omtu  = opts.omtu;
+		l2cap_pi(sk)->imtu = opts.imtu;
+		l2cap_pi(sk)->omtu = opts.omtu;
+		l2cap_pi(sk)->mode = opts.mode;
 		break;
 
 	case L2CAP_LM:
@@ -1381,7 +1410,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 		opts.imtu     = l2cap_pi(sk)->imtu;
 		opts.omtu     = l2cap_pi(sk)->omtu;
 		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = L2CAP_MODE_BASIC;
+		opts.mode     = l2cap_pi(sk)->mode;
 
 		len = min_t(unsigned int, len, sizeof(opts));
 		if (copy_to_user(optval, (char *) &opts, len))
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 26/47] Bluetooth: Add module option to enable L2CAP ERTM support
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

Since the Enhanced Retransmission mode for L2CAP is still under heavy
development disable it by default and provide a module option to enable
it manually for testing.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/l2cap.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index bd0a4c1..810a3c1 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -50,7 +50,9 @@
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
-#define VERSION "2.13"
+#define VERSION "2.14"
+
+static int enable_ertm = 0;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
 static u8 l2cap_fixed_chan[8] = { 0x02, };
@@ -2205,10 +2207,13 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
 
 	if (type == L2CAP_IT_FEAT_MASK) {
 		u8 buf[8];
+		u32 feat_mask = l2cap_feat_mask;
 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
-		put_unaligned(cpu_to_le32(l2cap_feat_mask), (__le32 *) rsp->data);
+		if (enable_ertm)
+			feat_mask |= L2CAP_FEAT_ERTM;
+		put_unaligned(cpu_to_le32(feat_mask), (__le32 *) rsp->data);
 		l2cap_send_cmd(conn, cmd->ident,
 					L2CAP_INFO_RSP, sizeof(buf), buf);
 	} else if (type == L2CAP_IT_FIXED_CHAN) {
@@ -2828,6 +2833,9 @@ EXPORT_SYMBOL(l2cap_load);
 module_init(l2cap_init);
 module_exit(l2cap_exit);
 
+module_param(enable_ertm, bool, 0644);
+MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
+
 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
 MODULE_VERSION(VERSION);
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 25/47] Bluetooth: Coding style cleanup from previous rfcomm_init bug fix
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The rfcomm_init bug fix went into the kernel premature before it got fully
reviewed and acknowledged by the Bluetooth maintainer. So fix up the coding
style now.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/rfcomm/core.c |   28 +++++++++++++++-------------
 1 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 94b3388..26af485 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2080,7 +2080,7 @@ static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL);
 /* ---- Initialization ---- */
 static int __init rfcomm_init(void)
 {
-	int ret;
+	int err;
 
 	l2cap_load();
 
@@ -2088,33 +2088,35 @@ static int __init rfcomm_init(void)
 
 	rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
 	if (IS_ERR(rfcomm_thread)) {
-		ret = PTR_ERR(rfcomm_thread);
-		goto out_thread;
+		err = PTR_ERR(rfcomm_thread);
+		goto unregister;
 	}
 
 	if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
 		BT_ERR("Failed to create RFCOMM info file");
 
-	ret = rfcomm_init_ttys();
-	if (ret)
-		goto out_tty;
+	err = rfcomm_init_ttys();
+	if (err < 0)
+		goto stop;
 
-	ret = rfcomm_init_sockets();
-	if (ret)
-		goto out_sock;
+	err = rfcomm_init_sockets();
+	if (err < 0)
+		goto cleanup;
 
 	BT_INFO("RFCOMM ver %s", VERSION);
 
 	return 0;
 
-out_sock:
+cleanup:
 	rfcomm_cleanup_ttys();
-out_tty:
+
+stop:
 	kthread_stop(rfcomm_thread);
-out_thread:
+
+unregister:
 	hci_unregister_cb(&rfcomm_cb);
 
-	return ret;
+	return err;
 }
 
 static void __exit rfcomm_exit(void)
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 24/47] Bluetooth: Convert hdev->req_lock to a mutex
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Thomas Gleixner <tglx@linutronix.de>

hdev->req_lock is used as mutex so make it a mutex.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci_core.h |    6 +++---
 net/bluetooth/hci_core.c         |    2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 25b8a03..7b640ae 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -117,7 +117,7 @@ struct hci_dev {
 	struct sk_buff		*sent_cmd;
 	struct sk_buff		*reassembly[3];
 
-	struct semaphore	req_lock;
+	struct mutex		req_lock;
 	wait_queue_head_t	req_wait_q;
 	__u32			req_status;
 	__u32			req_result;
@@ -704,8 +704,8 @@ struct hci_sec_filter {
 #define HCI_REQ_PEND	  1
 #define HCI_REQ_CANCELED  2
 
-#define hci_req_lock(d)		down(&d->req_lock)
-#define hci_req_unlock(d)	up(&d->req_lock)
+#define hci_req_lock(d)		mutex_lock(&d->req_lock)
+#define hci_req_unlock(d)	mutex_unlock(&d->req_lock)
 
 void hci_req_complete(struct hci_dev *hdev, int result);
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 406ad07..e1da8f6 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -911,7 +911,7 @@ int hci_register_dev(struct hci_dev *hdev)
 		hdev->reassembly[i] = NULL;
 
 	init_waitqueue_head(&hdev->req_wait_q);
-	init_MUTEX(&hdev->req_lock);
+	mutex_init(&hdev->req_lock);
 
 	inquiry_cache_init(hdev);
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 22/47] Bluetooth: Fix incorrect alignment in Marvell BT-over-SDIO driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Bing Zhao <bzhao@marvell.com>

The driver uses "u32" for alignment check and calculation which
works only on 32-bit system. It will crash the 64-bit system.
Replace "u32" with "unsigned long" to fix this issue.

Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_sdio.c |   12 +++++++-----
 drivers/bluetooth/btmrvl_sdio.h |    3 ++-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 224af53..1cfa8b4 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -481,12 +481,14 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 		goto exit;
 	}
 
-	if ((u32) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
-		skb_put(skb, (u32) skb->data & (BTSDIO_DMA_ALIGN - 1));
-		skb_pull(skb, (u32) skb->data & (BTSDIO_DMA_ALIGN - 1));
+	if ((unsigned long) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
+		skb_put(skb, (unsigned long) skb->data &
+					(BTSDIO_DMA_ALIGN - 1));
+		skb_pull(skb, (unsigned long) skb->data &
+					(BTSDIO_DMA_ALIGN - 1));
 	}
 
-	payload = skb->tail;
+	payload = skb->data;
 
 	ret = sdio_readsb(card->func, payload, card->ioport,
 			  buf_block_len * blksz);
@@ -773,7 +775,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
 	}
 
 	buf = payload;
-	if ((u32) payload & (BTSDIO_DMA_ALIGN - 1)) {
+	if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1)) {
 		tmpbufsz = ALIGN_SZ(nb, BTSDIO_DMA_ALIGN);
 		tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
 		memset(tmpbuf, 0, tmpbufsz);
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 2dd284e..27329f1 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -104,4 +104,5 @@ struct btmrvl_sdio_device {
 
 /* Macros for Data Alignment : address */
 #define ALIGN_ADDR(p, a)	\
-	((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
+	((((unsigned long)(p)) + (((unsigned long)(a)) - 1)) & \
+					~(((unsigned long)(a)) - 1))
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 23/47] Bluetooth: Add missing kmalloc NULL tests to Marvell driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

From: Julia Lawall <julia@diku.dk>

Check that the result of kmalloc is not NULL before dereferencing it.
The patch also replaces kmalloc + memset by kzalloc.

The semantic match that finds this problem is as follows:
(http://coccinelle.lip6.fr/)

// <smpl>
@@
expression *x;
identifier f;
constant char *C;
@@

x = \(kmalloc\|kcalloc\|kzalloc\)(...);
... when != x == NULL
    when != x != NULL
    when != (x || ...)
(
kfree(x)
|
f(...,C,...,x,...)
|
*f(...,x,...)
|
*x->f
)
// </smpl>

Signed-off-by: Julia Lawall <julia@diku.dk>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_sdio.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 1cfa8b4..5b33b85 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -777,8 +777,9 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
 	buf = payload;
 	if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1)) {
 		tmpbufsz = ALIGN_SZ(nb, BTSDIO_DMA_ALIGN);
-		tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
-		memset(tmpbuf, 0, tmpbufsz);
+		tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL);
+		if (!tmpbuf)
+			return -ENOMEM;
 		buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN);
 		memcpy(buf, payload, nb);
 	}
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 21/47] Bluetooth: Remove Enter/Leave debug statements from Marvell driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell Bluetooth driver is full of Enter/Leave debug statements and
all of them are really pointless and only clutter the code. Seems to be
some left-overs when they ported the driver from Windows. For the Linux
driver lets remove these.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_main.c |  107 +++---------------------------
 drivers/bluetooth/btmrvl_sdio.c |  135 ++++-----------------------------------
 2 files changed, 23 insertions(+), 219 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index bbc4446..e605563 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -32,8 +32,6 @@
  */
 void btmrvl_interrupt(struct btmrvl_private *priv)
 {
-	BT_DBG("Enter");
-
 	priv->adapter->ps_state = PS_AWAKE;
 
 	priv->adapter->wakeup_tries = 0;
@@ -41,8 +39,6 @@ void btmrvl_interrupt(struct btmrvl_private *priv)
 	priv->adapter->int_count++;
 
 	wake_up_interruptible(&priv->main_thread.wait_q);
-
-	BT_DBG("Leave");
 }
 EXPORT_SYMBOL_GPL(btmrvl_interrupt);
 
@@ -52,8 +48,6 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 	struct hci_ev_cmd_complete *ec;
 	u16 opcode, ocf;
 
-	BT_DBG("Enter");
-
 	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
 		ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
 		opcode = __le16_to_cpu(ec->opcode);
@@ -65,8 +59,6 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 			wake_up_interruptible(&priv->adapter->cmd_wait_q);
 		}
 	}
-
-	BT_DBG("Leave");
 }
 EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt);
 
@@ -76,8 +68,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 	struct btmrvl_event *event;
 	u8 ret = 0;
 
-	BT_DBG("Enter");
-
 	event = (struct btmrvl_event *) skb->data;
 	if (event->ec != 0xff) {
 		BT_DBG("Not Marvell Event=%x", event->ec);
@@ -151,8 +141,6 @@ exit:
 	if (!ret)
 		kfree_skb(skb);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 EXPORT_SYMBOL_GPL(btmrvl_process_event);
@@ -161,15 +149,12 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 {
 	struct sk_buff *skb;
 	struct btmrvl_cmd *cmd;
-	u8 ret = 0;
-
-	BT_DBG("Enter");
+	int ret = 0;
 
 	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
 	if (skb == NULL) {
 		BT_ERR("No free skb");
-		ret = -ENOMEM;
-		goto exit;
+		return -ENOMEM;
 	}
 
 	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
@@ -200,9 +185,6 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 
 	BT_DBG("module cfg Command done");
 
-exit:
-	BT_DBG("Leave");
-
 	return ret;
 }
 EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
@@ -211,15 +193,12 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 {
 	struct sk_buff *skb;
 	struct btmrvl_cmd *cmd;
-	u8 ret = 0;
-
-	BT_DBG("Enter");
+	int ret = 0;
 
 	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
 	if (skb == NULL) {
 		BT_ERR("No free skb");
-		ret = -ENOMEM;
-		goto exit;
+		return -ENOMEM;
 	}
 
 	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
@@ -244,9 +223,6 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 						priv->adapter->wakeup_tries);
 	}
 
-exit:
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -254,9 +230,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 {
 	struct sk_buff *skb = NULL;
 	struct btmrvl_cmd *cmd;
-	u8 ret = 0;
-
-	BT_DBG("Enter");
+	int ret = 0;
 
 	if (priv->btmrvl_dev.hscfgcmd) {
 		priv->btmrvl_dev.hscfgcmd = 0;
@@ -264,8 +238,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 		skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
 		if (skb == NULL) {
 			BT_ERR("No free skb");
-			ret = -ENOMEM;
-			goto exit;
+			return -ENOMEM;
 		}
 
 		cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
@@ -289,8 +262,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 		skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
 		if (skb == NULL) {
 			BT_ERR("No free skb");
-			ret = -ENOMEM;
-			goto exit;
+			return -ENOMEM;
 		}
 
 		cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
@@ -321,27 +293,19 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 		}
 	}
 
-exit:
-	BT_DBG("Leave");
-
 	return ret;
 }
 
 static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 {
-	u8 ret = 0;
+	int ret = 0;
 
-	BT_DBG("Enter");
-
-	if (!skb || !skb->data) {
-		BT_DBG("Leave");
+	if (!skb || !skb->data)
 		return -EINVAL;
-	}
 
 	if (!skb->len || ((skb->len + BTM_HEADER_LEN) > BTM_UPLD_SIZE)) {
 		BT_ERR("Tx Error: Bad skb length %d : %d",
 						skb->len, BTM_UPLD_SIZE);
-		BT_DBG("Leave");
 		return -EINVAL;
 	}
 
@@ -353,7 +317,6 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 			BT_ERR("Tx Error: realloc_headroom failed %d",
 				BTM_HEADER_LEN);
 			skb = tmp;
-			BT_DBG("Leave");
 			return -EINVAL;
 		}
 
@@ -375,52 +338,35 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 	if (priv->hw_host_to_card)
 		ret = priv->hw_host_to_card(priv, skb->data, skb->len);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
 static void btmrvl_init_adapter(struct btmrvl_private *priv)
 {
-	BT_DBG("Enter");
-
 	skb_queue_head_init(&priv->adapter->tx_queue);
 
 	priv->adapter->ps_state = PS_AWAKE;
 
 	init_waitqueue_head(&priv->adapter->cmd_wait_q);
-
-	BT_DBG("Leave");
 }
 
 static void btmrvl_free_adapter(struct btmrvl_private *priv)
 {
-	BT_DBG("Enter");
-
 	skb_queue_purge(&priv->adapter->tx_queue);
 
 	kfree(priv->adapter);
 
 	priv->adapter = NULL;
-
-	BT_DBG("Leave");
 }
 
 static int btmrvl_ioctl(struct hci_dev *hdev,
 				unsigned int cmd, unsigned long arg)
 {
-	BT_DBG("Enter");
-
-	BT_DBG("Leave");
-
 	return -ENOIOCTLCMD;
 }
 
 static void btmrvl_destruct(struct hci_dev *hdev)
 {
-	BT_DBG("Enter");
-
-	BT_DBG("Leave");
 }
 
 static int btmrvl_send_frame(struct sk_buff *skb)
@@ -428,11 +374,10 @@ static int btmrvl_send_frame(struct sk_buff *skb)
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
 	struct btmrvl_private *priv = NULL;
 
-	BT_DBG("Enter: type=%d, len=%d", skb->pkt_type, skb->len);
+	BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
 
 	if (!hdev || !hdev->driver_data) {
 		BT_ERR("Frame for unknown HCI device");
-		BT_DBG("Leave");
 		return -ENODEV;
 	}
 
@@ -441,7 +386,6 @@ static int btmrvl_send_frame(struct sk_buff *skb)
 		BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
 		print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
 							skb->data, skb->len);
-		BT_DBG("Leave");
 		return -EBUSY;
 	}
 
@@ -463,8 +407,6 @@ static int btmrvl_send_frame(struct sk_buff *skb)
 
 	wake_up_interruptible(&priv->main_thread.wait_q);
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
@@ -472,12 +414,8 @@ static int btmrvl_flush(struct hci_dev *hdev)
 {
 	struct btmrvl_private *priv = hdev->driver_data;
 
-	BT_DBG("Enter");
-
 	skb_queue_purge(&priv->adapter->tx_queue);
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
@@ -485,28 +423,18 @@ static int btmrvl_close(struct hci_dev *hdev)
 {
 	struct btmrvl_private *priv = hdev->driver_data;
 
-	BT_DBG("Enter");
-
-	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
-		BT_DBG("Leave");
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
-	}
 
 	skb_queue_purge(&priv->adapter->tx_queue);
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
 static int btmrvl_open(struct hci_dev *hdev)
 {
-	BT_DBG("Enter");
-
 	set_bit(HCI_RUNNING, &hdev->flags);
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
@@ -523,8 +451,6 @@ static int btmrvl_service_main_thread(void *data)
 	struct sk_buff *skb;
 	ulong flags;
 
-	BT_DBG("Enter");
-
 	init_waitqueue_entry(&wait, current);
 
 	current->flags |= PF_NOFREEZE;
@@ -582,8 +508,6 @@ static int btmrvl_service_main_thread(void *data)
 		}
 	}
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
@@ -593,8 +517,6 @@ struct btmrvl_private *btmrvl_add_card(void *card)
 	struct btmrvl_private *priv;
 	int ret;
 
-	BT_DBG("Enter");
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		BT_ERR("Can not allocate priv");
@@ -649,7 +571,6 @@ struct btmrvl_private *btmrvl_add_card(void *card)
 	btmrvl_debugfs_init(hdev);
 #endif
 
-	BT_DBG("Leave");
 	return priv;
 
 err_hci_register_dev:
@@ -665,8 +586,6 @@ err_adapter:
 	kfree(priv);
 
 err_priv:
-	BT_DBG("Leave");
-
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(btmrvl_add_card);
@@ -675,8 +594,6 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
 {
 	struct hci_dev *hdev;
 
-	BT_DBG("Enter");
-
 	hdev = priv->btmrvl_dev.hcidev;
 
 	wake_up_interruptible(&priv->adapter->cmd_wait_q);
@@ -697,8 +614,6 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
 
 	kfree(priv);
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(btmrvl_remove_card);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 7638f62..224af53 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -67,23 +67,17 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
 	u8 reg;
 	int ret;
 
-	BT_DBG("Enter");
-
 	reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret);
 	if (!ret)
 		card->rx_unit = reg;
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
 static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
 {
-	int ret;
 	u8 fws0, fws1;
-
-	BT_DBG("Enter");
+	int ret;
 
 	*dat = 0;
 
@@ -92,31 +86,23 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
 	if (!ret)
 		fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
 
-	if (ret) {
-		BT_DBG("Leave");
+	if (ret)
 		return -EIO;
-	}
 
 	*dat = (((u16) fws1) << 8) | fws0;
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
 static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
 {
-	int ret;
 	u8 reg;
-
-	BT_DBG("Enter");
+	int ret;
 
 	reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret);
 	if (!ret)
 		*dat = (u16) reg << card->rx_unit;
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -125,64 +111,48 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
 {
 	int ret;
 
-	BT_DBG("Enter");
-
 	sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret);
 	if (ret) {
 		BT_ERR("Unable to enable the host interrupt!");
 		ret = -EIO;
 	}
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
 static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
 								u8 mask)
 {
-	int ret;
 	u8 host_int_mask;
-
-	BT_DBG("Enter");
+	int ret;
 
 	host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret);
-	if (ret) {
-		ret = -EIO;
-		goto done;
-	}
+	if (ret)
+		return -EIO;
 
 	host_int_mask &= ~mask;
 
 	sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret);
 	if (ret < 0) {
 		BT_ERR("Unable to disable the host interrupt!");
-		ret = -EIO;
-		goto done;
+		return -EIO;
 	}
 
-	ret = 0;
-
-done:
-	BT_DBG("Leave");
-
-	return ret;
+	return 0;
 }
 
 static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
 {
 	unsigned int tries;
-	int ret;
 	u8 status;
-
-	BT_DBG("Enter");
+	int ret;
 
 	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
 		status = sdio_readb(card->func, CARD_STATUS_REG, &ret);
 		if (ret)
 			goto failed;
 		if ((status & bits) == bits)
-			goto done;
+			return ret;
 
 		udelay(1);
 	}
@@ -192,9 +162,6 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
 failed:
 	BT_ERR("FAILED! ret=%d", ret);
 
-done:
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -205,8 +172,6 @@ static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
 	u16 firmwarestat;
 	unsigned int tries;
 
-	BT_DBG("Enter");
-
 	 /* Wait for firmware to become ready */
 	for (tries = 0; tries < pollnum; tries++) {
 		if (btmrvl_sdio_read_fw_status(card, &firmwarestat) < 0)
@@ -220,8 +185,6 @@ static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
 		}
 	}
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -235,8 +198,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 	u8 *helperbuf;
 	u32 tx_len;
 
-	BT_DBG("Enter");
-
 	ret = request_firmware(&fw_helper, card->helper,
 						&card->func->dev);
 	if ((ret < 0) || !fw_helper) {
@@ -326,8 +287,6 @@ done:
 	if (fw_helper)
 		release_firmware(fw_helper);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -343,8 +302,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 	u16 len;
 	int txlen = 0, tx_blocks = 0, count = 0;
 
-	BT_DBG("Enter");
-
 	ret = request_firmware(&fw_firmware, card->firmware,
 							&card->func->dev);
 	if ((ret < 0) || !fw_firmware) {
@@ -479,8 +436,6 @@ done:
 	if (fw_firmware)
 		release_firmware(fw_firmware);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -494,8 +449,6 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 
-	BT_DBG("Enter");
-
 	if (!card || !card->func) {
 		BT_ERR("card or function is NULL!");
 		ret = -EINVAL;
@@ -596,8 +549,6 @@ exit:
 			kfree_skb(skb);
 	}
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -607,8 +558,6 @@ static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
 	u8 sdio_ireg = 0;
 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 
-	BT_DBG("Enter");
-
 	*ireg = 0;
 
 	sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
@@ -653,8 +602,6 @@ static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
 	ret = 0;
 
 done:
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -665,8 +612,6 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
 	struct btmrvl_sdio_card *card;
 	u8 ireg = 0;
 
-	BT_DBG("Enter");
-
 	card = sdio_get_drvdata(func);
 	if (card && card->priv) {
 		priv = card->priv;
@@ -679,8 +624,6 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
 
 		btmrvl_interrupt(priv);
 	}
-
-	BT_DBG("Leave");
 }
 
 static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
@@ -689,8 +632,6 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 	u8 reg;
 	int ret = 0;
 
-	BT_DBG("Enter");
-
 	if (!card || !card->func) {
 		BT_ERR("Error: card or function is NULL!");
 		ret = -EINVAL;
@@ -752,7 +693,6 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 
 	sdio_release_host(func);
 
-	BT_DBG("Leave");
 	return 0;
 
 release_irq:
@@ -765,14 +705,11 @@ release_host:
 	sdio_release_host(func);
 
 failed:
-	BT_DBG("Leave");
 	return ret;
 }
 
 static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
 {
-	BT_DBG("Enter");
-
 	if (card && card->func) {
 		sdio_claim_host(card->func);
 		sdio_release_irq(card->func);
@@ -781,8 +718,6 @@ static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
 		sdio_set_drvdata(card->func, NULL);
 	}
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
@@ -790,12 +725,8 @@ static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
 {
 	int ret;
 
-	BT_DBG("Enter");
-
-	if (!card || !card->func) {
-		BT_DBG("Leave");
+	if (!card || !card->func)
 		return -EINVAL;
-	}
 
 	sdio_claim_host(card->func);
 
@@ -805,8 +736,6 @@ static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
 
 	sdio_release_host(card->func);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -814,12 +743,8 @@ static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
 {
 	int ret;
 
-	BT_DBG("Enter");
-
-	if (!card || !card->func) {
-		BT_DBG("Leave");
+	if (!card || !card->func)
 		return -EINVAL;
-	}
 
 	sdio_claim_host(card->func);
 
@@ -827,8 +752,6 @@ static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
 
 	sdio_release_host(card->func);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -844,11 +767,8 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
 	void *tmpbuf = NULL;
 	int tmpbufsz;
 
-	BT_DBG("Enter");
-
 	if (!card || !card->func) {
 		BT_ERR("card or function is NULL!");
-		BT_DBG("Leave");
 		return -EINVAL;
 	}
 
@@ -886,8 +806,6 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
 exit:
 	sdio_release_host(card->func);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -895,11 +813,8 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
 {
 	int ret = 0;
 
-	BT_DBG("Enter");
-
 	if (!card || !card->func) {
 		BT_ERR("card or function is NULL!");
-		BT_DBG("Leave");
 		return -EINVAL;
 	}
 	sdio_claim_host(card->func);
@@ -931,8 +846,6 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
 done:
 	sdio_release_host(card->func);
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -941,11 +854,8 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
 	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 	int ret = 0;
 
-	BT_DBG("Enter");
-
 	if (!card || !card->func) {
 		BT_ERR("card or function is NULL!");
-		BT_DBG("Leave");
 		return -EINVAL;
 	}
 
@@ -957,8 +867,6 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
 
 	BT_DBG("wake up firmware");
 
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -969,8 +877,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 	struct btmrvl_private *priv = NULL;
 	struct btmrvl_sdio_card *card = NULL;
 
-	BT_DBG("Enter");
-
 	BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
 			id->vendor, id->device, id->class, func->num);
 
@@ -1022,8 +928,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 
 	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
 
-	BT_DBG("Leave");
-
 	return 0;
 
 disable_host_int:
@@ -1033,8 +937,6 @@ unreg_dev:
 free_card:
 	kfree(card);
 done:
-	BT_DBG("Leave");
-
 	return ret;
 }
 
@@ -1042,8 +944,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
 {
 	struct btmrvl_sdio_card *card;
 
-	BT_DBG("Enter");
-
 	if (func) {
 		card = sdio_get_drvdata(func);
 		if (card) {
@@ -1061,8 +961,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
 			kfree(card);
 		}
 	}
-
-	BT_DBG("Leave");
 }
 
 static struct sdio_driver bt_mrvl_sdio = {
@@ -1074,32 +972,23 @@ static struct sdio_driver bt_mrvl_sdio = {
 
 static int btmrvl_sdio_init_module(void)
 {
-	BT_DBG("Enter");
-
 	if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
 		BT_ERR("SDIO Driver Registration Failed");
-		BT_DBG("Leave");
 		return -ENODEV;
 	}
 
 	/* Clear the flag in case user removes the card. */
 	user_rmmod = 0;
 
-	BT_DBG("Leave");
-
 	return 0;
 }
 
 static void btmrvl_sdio_exit_module(void)
 {
-	BT_DBG("Enter");
-
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 
 	sdio_unregister_driver(&bt_mrvl_sdio);
-
-	BT_DBG("Leave");
 }
 
 module_init(btmrvl_sdio_init_module);
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 20/47] Bluetooth: Fix last few compiler warning within Marvell core driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

After fixing the driver to use skb_put properly for their HCI commands
only a few compiler warnings are left. Add proper casting for them.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_main.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index f5a3dc5..bbc4446 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -172,7 +172,7 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 		goto exit;
 	}
 
-	cmd = skb_put(skb, sizeof(*cmd));
+	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
 	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ));
 	cmd->length = 1;
 	cmd->data[0] = subcmd;
@@ -222,7 +222,7 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 		goto exit;
 	}
 
-	cmd = skb_put(skb, sizeof(*cmd));
+	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
 	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE));
 	cmd->length = 0;
 
@@ -268,7 +268,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 			goto exit;
 		}
 
-		cmd = skb_put(skb, sizeof(*cmd));
+		cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
 		cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG));
 		cmd->length = 2;
 		cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
@@ -293,7 +293,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 			goto exit;
 		}
 
-		cmd = skb_put(skb, sizeof(*cmd));
+		cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
 		cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE));
 		cmd->length = 1;
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 19/47] Bluetooth: Fix Marvell driver to use skb_put and hci_opcode_pack
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell driver has some weird quirks on how to construct proper SKBs
with Bluetooth HCI commands. Fix it to use skb_put properly and also
use hci_opcode_pack instead of self-crafted macro.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_main.c |   22 ++++++++--------------
 1 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 61168ec..f5a3dc5 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -172,14 +172,13 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 		goto exit;
 	}
 
-	cmd = (struct btmrvl_cmd *) skb->tail;
-	cmd->ocf_ogf = cpu_to_le16((OGF << 10) | BT_CMD_MODULE_CFG_REQ);
+	cmd = skb_put(skb, sizeof(*cmd));
+	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ));
 	cmd->length = 1;
 	cmd->data[0] = subcmd;
 
 	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
-	skb_put(skb, sizeof(*cmd));
 	skb->dev = (void *) priv->btmrvl_dev.hcidev;
 	skb_queue_head(&priv->adapter->tx_queue, skb);
 
@@ -223,13 +222,12 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 		goto exit;
 	}
 
-	cmd = (struct btmrvl_cmd *) skb->tail;
-	cmd->ocf_ogf = cpu_to_le16((OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE);
+	cmd = skb_put(skb, sizeof(*cmd));
+	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE));
 	cmd->length = 0;
 
 	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
-	skb_put(skb, sizeof(*cmd));
 	skb->dev = (void *) priv->btmrvl_dev.hcidev;
 	skb_queue_head(&priv->adapter->tx_queue, skb);
 
@@ -270,16 +268,14 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 			goto exit;
 		}
 
-		cmd = (struct btmrvl_cmd *) skb->tail;
-		cmd->ocf_ogf = cpu_to_le16((OGF << 10) |
-						BT_CMD_HOST_SLEEP_CONFIG);
+		cmd = skb_put(skb, sizeof(*cmd));
+		cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG));
 		cmd->length = 2;
 		cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
 		cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
 
 		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
-		skb_put(skb, sizeof(*cmd));
 		skb->dev = (void *) priv->btmrvl_dev.hcidev;
 		skb_queue_head(&priv->adapter->tx_queue, skb);
 
@@ -297,9 +293,8 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 			goto exit;
 		}
 
-		cmd = (struct btmrvl_cmd *) skb->tail;
-		cmd->ocf_ogf = cpu_to_le16((OGF << 10) |
-						BT_CMD_AUTO_SLEEP_MODE);
+		cmd = skb_put(skb, sizeof(*cmd));
+		cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE));
 		cmd->length = 1;
 
 		if (priv->btmrvl_dev.psmode)
@@ -309,7 +304,6 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 
 		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
-		skb_put(skb, sizeof(*cmd));
 		skb->dev = (void *) priv->btmrvl_dev.hcidev;
 		skb_queue_head(&priv->adapter->tx_queue, skb);
 
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 17/47] Bluetooth: Fix module description strings for Marvell driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

Make the module description entries for the core and also the Marvell
SDIO driver match common practive inside the Bluetooth subsystem.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_main.c |    2 +-
 drivers/bluetooth/btmrvl_sdio.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index db4fdb1..61168ec 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -710,6 +710,6 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
 EXPORT_SYMBOL_GPL(btmrvl_remove_card);
 
 MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell Bluetooth Driver ver" VERSION);
+MODULE_DESCRIPTION("Marvell Bluetooth driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 867ebe4..0dea23e 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1109,6 +1109,6 @@ module_init(btmrvl_sdio_init_module);
 module_exit(btmrvl_sdio_exit_module);
 
 MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell BT-over-SDIO Driver v" VERSION);
+MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL v2");
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 18/47] Bluetooth: Remove private device name of Marvell SDIO driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

For some reason the btmrvl_device struct has a name field that the SDIO
fills in, but then never ever uses again. That is totally pointless and
so just remove it.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_drv.h  |    2 --
 drivers/bluetooth/btmrvl_sdio.c |    3 ---
 2 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 5da3be4..411c7a7 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -24,7 +24,6 @@
 #include <net/bluetooth/bluetooth.h>
 
 #define BTM_HEADER_LEN			4
-#define BTM_DEV_NAME_LEN		32
 #define BTM_UPLD_SIZE			2312
 
 /* Time to wait until Host Sleep state change in millisecond */
@@ -39,7 +38,6 @@ struct btmrvl_thread {
 };
 
 struct btmrvl_device {
-	char name[BTM_DEV_NAME_LEN];
 	void *card;
 	struct hci_dev *hcidev;
 
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 0dea23e..7638f62 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1020,9 +1020,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 	priv->hw_host_to_card = btmrvl_sdio_host_to_card;
 	priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
 
-	strncpy(priv->btmrvl_dev.name, "btmrvl_sdio0",
-			sizeof(priv->btmrvl_dev.name));
-
 	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
 
 	BT_DBG("Leave");
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 16/47] Bluetooth: Fix complicated assignment of firmware for Marvell devices
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell Bluetooth SDIO driver has a really complicated concept on how
firmware names are assigned to specific device ids. Fix that by doing a
proper structure and assign it to the module device table.

And while at it fix various coding style weirdness that is still present
in this driver.

Signed-off-by: Marcel Holtman <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_sdio.c |   90 ++++++++++++++++----------------------
 drivers/bluetooth/btmrvl_sdio.h |    1 -
 2 files changed, 38 insertions(+), 53 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 8f13e7b..867ebe4 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -31,10 +31,6 @@
 
 #define VERSION "1.0"
 
-#ifndef SDIO_DEVICE_ID_MARVELL_8688BT
-#define SDIO_DEVICE_ID_MARVELL_8688BT		0x9105
-#endif
-
 /* The btmrvl_sdio_remove() callback function is called
  * when user removes this module from kernel space or ejects
  * the card from the slot. The driver handles these 2 cases
@@ -51,21 +47,21 @@
  */
 static u8 user_rmmod;
 
-static const struct sdio_device_id btmrvl_sdio_ids[] = {
-	{SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8688BT)},
-	{0, 0, 0, 0}
+static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
+	.helper		= "sd8688_helper.bin",
+	.firmware	= "sd8688.bin",
 };
 
-MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
+static const struct sdio_device_id btmrvl_sdio_ids[] = {
+	/* Marvell SD8688 Bluetooth device */
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
+			.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
 
-static struct btmrvl_sdio_device btmrvl_sdio_devices[] = {
-	{
-		.dev_id = SDIO_DEVICE_ID_MARVELL_8688BT,
-		.helper = "sd8688_helper.bin",
-		.firmware = "sd8688.bin",
-	},
+	{ }	/* Terminating entry */
 };
 
+MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
+
 static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
 {
 	u8 reg;
@@ -125,7 +121,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
 }
 
 static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
-						u8 mask)
+								u8 mask)
 {
 	int ret;
 
@@ -143,7 +139,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
 }
 
 static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
-						u8 mask)
+								u8 mask)
 {
 	int ret;
 	u8 host_int_mask;
@@ -203,7 +199,7 @@ done:
 }
 
 static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
-						int pollnum)
+								int pollnum)
 {
 	int ret = -ETIMEDOUT;
 	u16 firmwarestat;
@@ -242,10 +238,10 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 	BT_DBG("Enter");
 
 	ret = request_firmware(&fw_helper, card->helper,
-				&card->func->dev);
+						&card->func->dev);
 	if ((ret < 0) || !fw_helper) {
 		BT_ERR("request_firmware(helper) failed, error code = %d",
-			ret);
+									ret);
 		ret = -ENOENT;
 		goto done;
 	}
@@ -254,7 +250,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 	helperlen = fw_helper->size;
 
 	BT_DBG("Downloading helper image (%d bytes), block size %d bytes",
-		helperlen, SDIO_BLOCK_SIZE);
+						helperlen, SDIO_BLOCK_SIZE);
 
 	tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
 
@@ -301,10 +297,8 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 				tx_len);
 
 		/* Now send the data */
-		ret = sdio_writesb(card->func, card->ioport,
-				   helperbuf,
-				   FIRMWARE_TRANSFER_NBLOCK *
-				   SDIO_BLOCK_SIZE);
+		ret = sdio_writesb(card->func, card->ioport, helperbuf,
+				FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE);
 		if (ret < 0) {
 			BT_ERR("IO error during helper download @ %d",
 				hlprblknow);
@@ -319,7 +313,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 	memset(helperbuf, 0x0, SDIO_BLOCK_SIZE);
 
 	ret = sdio_writesb(card->func, card->ioport, helperbuf,
-			 SDIO_BLOCK_SIZE);
+							SDIO_BLOCK_SIZE);
 	if (ret < 0) {
 		BT_ERR("IO error in writing helper image EOF block");
 		goto done;
@@ -352,10 +346,10 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 	BT_DBG("Enter");
 
 	ret = request_firmware(&fw_firmware, card->firmware,
-				&card->func->dev);
+							&card->func->dev);
 	if ((ret < 0) || !fw_firmware) {
 		BT_ERR("request_firmware(firmware) failed, error code = %d",
-			ret);
+									ret);
 		ret = -ENOENT;
 		goto done;
 	}
@@ -383,10 +377,10 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 	offset = 0;
 	do {
 		ret = btmrvl_sdio_poll_card_status(card,
-					    CARD_IO_READY | DN_LD_CARD_RDY);
+					CARD_IO_READY | DN_LD_CARD_RDY);
 		if (ret < 0) {
 			BT_ERR("FW download with helper poll status"
-				" timeout @ %d", offset);
+						" timeout @ %d", offset);
 			goto done;
 		}
 
@@ -427,7 +421,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 			break;
 		else if (len > BTM_UPLD_SIZE) {
 			BT_ERR("FW download failure @%d, invalid length %d",
-				offset, len);
+								offset, len);
 			ret = -EINVAL;
 			goto done;
 		}
@@ -465,9 +459,9 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 
 		if (ret < 0) {
 			BT_ERR("FW download, writesb(%d) failed @%d",
-				count, offset);
+							count, offset);
 			sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
-					&ret);
+									&ret);
 			if (ret)
 				BT_ERR("writeb failed (CFG)");
 		}
@@ -520,7 +514,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	buf_block_len = (buf_len + blksz - 1) / blksz;
 
 	if (buf_len <= SDIO_HEADER_LEN
-	    || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+			|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
 		BT_ERR("invalid packet length: %d", buf_len);
 		ret = -EINVAL;
 		goto exit;
@@ -528,7 +522,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 
 	/* Allocate buffer */
 	skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
-				GFP_ATOMIC);
+								GFP_ATOMIC);
 	if (skb == NULL) {
 		BT_ERR("No free skb");
 		goto exit;
@@ -588,7 +582,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	default:
 		BT_ERR("Unknow packet type:%d", type);
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
-					blksz * buf_block_len);
+						blksz * buf_block_len);
 
 		kfree_skb(skb);
 		skb = NULL;
@@ -691,9 +685,9 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
 
 static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 {
-	int ret = 0, i;
-	u8 reg;
 	struct sdio_func *func;
+	u8 reg;
+	int ret = 0;
 
 	BT_DBG("Enter");
 
@@ -705,20 +699,6 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 
 	func = card->func;
 
-	for (i = 0; i < ARRAY_SIZE(btmrvl_sdio_devices); i++) {
-		if (func->device == btmrvl_sdio_devices[i].dev_id)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(btmrvl_sdio_devices)) {
-		BT_ERR("Error: unknown device id 0x%x", func->device);
-		ret = -EINVAL;
-		goto failed;
-	}
-
-	card->helper = btmrvl_sdio_devices[i].helper;
-	card->firmware = btmrvl_sdio_devices[i].firmware;
-
 	sdio_claim_host(func);
 
 	ret = sdio_enable_func(func);
@@ -983,7 +963,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
 }
 
 static int btmrvl_sdio_probe(struct sdio_func *func,
-			     const struct sdio_device_id *id)
+					const struct sdio_device_id *id)
 {
 	int ret = 0;
 	struct btmrvl_private *priv = NULL;
@@ -1002,6 +982,12 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 
 	card->func = func;
 
+	if (id->driver_data) {
+		struct btmrvl_sdio_device *data = (void *) id->driver_data;
+		card->helper   = data->helper;
+		card->firmware = data->firmware;
+	}
+
 	if (btmrvl_sdio_register_dev(card) < 0) {
 		BT_ERR("Failed to register BT device!");
 		ret = -ENODEV;
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 6beb340..2dd284e 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -90,7 +90,6 @@ struct btmrvl_sdio_card {
 };
 
 struct btmrvl_sdio_device {
-	unsigned short dev_id;
 	const char *helper;
 	const char *firmware;
 };
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 15/47] Bluetooth: Some coding style cleanup for Marvell core driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell core Bluetooth driver has various weird casting and unneeded
braces in its code that makes it hard to read. Remove all of these to
make the code a little bit simpler.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_main.c |   97 ++++++++++++++++++---------------------
 1 files changed, 45 insertions(+), 52 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index b4f4445..db4fdb1 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -48,19 +48,18 @@ EXPORT_SYMBOL_GPL(btmrvl_interrupt);
 
 void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 {
-	struct hci_event_hdr *hdr = (struct hci_event_hdr *)skb->data;
+	struct hci_event_hdr *hdr = (void *) skb->data;
 	struct hci_ev_cmd_complete *ec;
 	u16 opcode, ocf;
 
 	BT_DBG("Enter");
 
 	if (hdr->evt == HCI_EV_CMD_COMPLETE) {
-		ec = (struct hci_ev_cmd_complete *)(skb->data +
-						    HCI_EVENT_HDR_SIZE);
+		ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
 		opcode = __le16_to_cpu(ec->opcode);
 		ocf = hci_opcode_ocf(opcode);
-		if ((ocf == BT_CMD_MODULE_CFG_REQ) &&
-		    (priv->btmrvl_dev.sendcmdflag)) {
+		if (ocf == BT_CMD_MODULE_CFG_REQ &&
+					priv->btmrvl_dev.sendcmdflag) {
 			priv->btmrvl_dev.sendcmdflag = false;
 			priv->adapter->cmd_complete = true;
 			wake_up_interruptible(&priv->adapter->cmd_wait_q);
@@ -74,8 +73,8 @@ EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt);
 int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 {
 	struct btmrvl_adapter *adapter = priv->adapter;
-	u8 ret = 0;
 	struct btmrvl_event *event;
+	u8 ret = 0;
 
 	BT_DBG("Enter");
 
@@ -103,7 +102,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 	case BT_CMD_HOST_SLEEP_CONFIG:
 		if (!event->data[3])
 			BT_DBG("gpio=%x, gap=%x", event->data[1],
-				event->data[2]);
+							event->data[2]);
 		else
 			BT_DBG("HSCFG command failed");
 		break;
@@ -121,12 +120,12 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
 		break;
 
 	case BT_CMD_MODULE_CFG_REQ:
-		if ((priv->btmrvl_dev.sendcmdflag) &&
-			(event->data[1] == MODULE_BRINGUP_REQ)) {
+		if (priv->btmrvl_dev.sendcmdflag &&
+				event->data[1] == MODULE_BRINGUP_REQ) {
 			BT_DBG("EVENT:%s", (event->data[2]) ?
 				"Bring-up failed" : "Bring-up succeed");
-		} else if ((priv->btmrvl_dev.sendcmdflag) &&
-			(event->data[1] == MODULE_SHUTDOWN_REQ)) {
+		} else if (priv->btmrvl_dev.sendcmdflag &&
+				event->data[1] == MODULE_SHUTDOWN_REQ) {
 			BT_DBG("EVENT:%s", (event->data[2]) ?
 				"Shutdown failed" : "Shutdown succeed");
 		} else {
@@ -160,9 +159,9 @@ EXPORT_SYMBOL_GPL(btmrvl_process_event);
 
 int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 {
-	struct sk_buff *skb = NULL;
-	u8 ret = 0;
+	struct sk_buff *skb;
 	struct btmrvl_cmd *cmd;
+	u8 ret = 0;
 
 	BT_DBG("Enter");
 
@@ -181,7 +180,7 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
 	skb_put(skb, sizeof(*cmd));
-	skb->dev = (void *)priv->btmrvl_dev.hcidev;
+	skb->dev = (void *) priv->btmrvl_dev.hcidev;
 	skb_queue_head(&priv->adapter->tx_queue, skb);
 
 	priv->btmrvl_dev.sendcmdflag = true;
@@ -192,13 +191,12 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 
 	wake_up_interruptible(&priv->main_thread.wait_q);
 
-	if (!wait_event_interruptible_timeout(
-			priv->adapter->cmd_wait_q,
-			priv->adapter->cmd_complete,
-			msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
+	if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
+				priv->adapter->cmd_complete,
+				msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
 		ret = -ETIMEDOUT;
 		BT_ERR("module_cfg_cmd(%x): timeout: %d",
-			subcmd, priv->btmrvl_dev.sendcmdflag);
+					subcmd, priv->btmrvl_dev.sendcmdflag);
 	}
 
 	BT_DBG("module cfg Command done");
@@ -212,9 +210,9 @@ EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
 
 static int btmrvl_enable_hs(struct btmrvl_private *priv)
 {
-	struct sk_buff *skb = NULL;
-	u8 ret = 0;
+	struct sk_buff *skb;
 	struct btmrvl_cmd *cmd;
+	u8 ret = 0;
 
 	BT_DBG("Enter");
 
@@ -232,22 +230,20 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
 	skb_put(skb, sizeof(*cmd));
-	skb->dev = (void *)priv->btmrvl_dev.hcidev;
+	skb->dev = (void *) priv->btmrvl_dev.hcidev;
 	skb_queue_head(&priv->adapter->tx_queue, skb);
 
 	BT_DBG("Queue hs enable Command");
 
 	wake_up_interruptible(&priv->main_thread.wait_q);
 
-	if (!wait_event_interruptible_timeout(
-			priv->adapter->cmd_wait_q,
+	if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
 			priv->adapter->hs_state,
 			msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) {
 		ret = -ETIMEDOUT;
-		BT_ERR("timeout: %d, %d,%d",
-			priv->adapter->hs_state,
-			priv->adapter->ps_state,
-			priv->adapter->wakeup_tries);
+		BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state,
+						priv->adapter->ps_state,
+						priv->adapter->wakeup_tries);
 	}
 
 exit:
@@ -259,8 +255,8 @@ exit:
 int btmrvl_prepare_command(struct btmrvl_private *priv)
 {
 	struct sk_buff *skb = NULL;
-	u8 ret = 0;
 	struct btmrvl_cmd *cmd;
+	u8 ret = 0;
 
 	BT_DBG("Enter");
 
@@ -284,11 +280,11 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
 		skb_put(skb, sizeof(*cmd));
-		skb->dev = (void *)priv->btmrvl_dev.hcidev;
+		skb->dev = (void *) priv->btmrvl_dev.hcidev;
 		skb_queue_head(&priv->adapter->tx_queue, skb);
 
 		BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x",
-		       cmd->data[0], cmd->data[1]);
+						cmd->data[0], cmd->data[1]);
 	}
 
 	if (priv->btmrvl_dev.pscmd) {
@@ -314,7 +310,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
 		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
 
 		skb_put(skb, sizeof(*cmd));
-		skb->dev = (void *)priv->btmrvl_dev.hcidev;
+		skb->dev = (void *) priv->btmrvl_dev.hcidev;
 		skb_queue_head(&priv->adapter->tx_queue, skb);
 
 		BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
@@ -350,7 +346,7 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
 
 	if (!skb->len || ((skb->len + BTM_HEADER_LEN) > BTM_UPLD_SIZE)) {
 		BT_ERR("Tx Error: Bad skb length %d : %d",
-			skb->len, BTM_UPLD_SIZE);
+						skb->len, BTM_UPLD_SIZE);
 		BT_DBG("Leave");
 		return -EINVAL;
 	}
@@ -416,8 +412,8 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv)
 	BT_DBG("Leave");
 }
 
-static int
-btmrvl_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+static int btmrvl_ioctl(struct hci_dev *hdev,
+				unsigned int cmd, unsigned long arg)
 {
 	BT_DBG("Enter");
 
@@ -435,7 +431,7 @@ static void btmrvl_destruct(struct hci_dev *hdev)
 
 static int btmrvl_send_frame(struct sk_buff *skb)
 {
-	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
 	struct btmrvl_private *priv = NULL;
 
 	BT_DBG("Enter: type=%d, len=%d", skb->pkt_type, skb->len);
@@ -446,11 +442,11 @@ static int btmrvl_send_frame(struct sk_buff *skb)
 		return -ENODEV;
 	}
 
-	priv = (struct btmrvl_private *)hdev->driver_data;
+	priv = (struct btmrvl_private *) hdev->driver_data;
 	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
 		BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
 		print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
-					skb->data, skb->len);
+							skb->data, skb->len);
 		BT_DBG("Leave");
 		return -EBUSY;
 	}
@@ -480,8 +476,7 @@ static int btmrvl_send_frame(struct sk_buff *skb)
 
 static int btmrvl_flush(struct hci_dev *hdev)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) hdev->driver_data;
+	struct btmrvl_private *priv = hdev->driver_data;
 
 	BT_DBG("Enter");
 
@@ -494,8 +489,7 @@ static int btmrvl_flush(struct hci_dev *hdev)
 
 static int btmrvl_close(struct hci_dev *hdev)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) hdev->driver_data;
+	struct btmrvl_private *priv = hdev->driver_data;
 
 	BT_DBG("Enter");
 
@@ -547,9 +541,9 @@ static int btmrvl_service_main_thread(void *data)
 		set_current_state(TASK_INTERRUPTIBLE);
 
 		if (adapter->wakeup_tries ||
-		    ((!adapter->int_count) &&
-		     (!priv->btmrvl_dev.tx_dnld_rdy ||
-		      skb_queue_empty(&adapter->tx_queue)))) {
+				((!adapter->int_count) &&
+				(!priv->btmrvl_dev.tx_dnld_rdy ||
+				skb_queue_empty(&adapter->tx_queue)))) {
 			BT_DBG("main_thread is sleeping...");
 			schedule();
 		}
@@ -568,8 +562,8 @@ static int btmrvl_service_main_thread(void *data)
 		spin_lock_irqsave(&priv->driver_lock, flags);
 		if (adapter->int_count) {
 			adapter->int_count = 0;
-		} else if ((adapter->ps_state == PS_SLEEP) &&
-			   !skb_queue_empty(&adapter->tx_queue)) {
+		} else if (adapter->ps_state == PS_SLEEP &&
+					!skb_queue_empty(&adapter->tx_queue)) {
 			spin_unlock_irqrestore(&priv->driver_lock, flags);
 			adapter->wakeup_tries++;
 			priv->hw_wakeup_firmware(priv);
@@ -588,8 +582,7 @@ static int btmrvl_service_main_thread(void *data)
 			if (btmrvl_tx_pkt(priv, skb))
 				priv->btmrvl_dev.hcidev->stat.err_tx++;
 			else
-				priv->btmrvl_dev.hcidev->stat.byte_tx
-					+= skb->len;
+				priv->btmrvl_dev.hcidev->stat.byte_tx += skb->len;
 
 			kfree_skb(skb);
 		}
@@ -603,7 +596,7 @@ static int btmrvl_service_main_thread(void *data)
 struct btmrvl_private *btmrvl_add_card(void *card)
 {
 	struct hci_dev *hdev = NULL;
-	struct btmrvl_private *priv = NULL;
+	struct btmrvl_private *priv;
 	int ret;
 
 	BT_DBG("Enter");
@@ -634,7 +627,7 @@ struct btmrvl_private *btmrvl_add_card(void *card)
 
 	init_waitqueue_head(&priv->main_thread.wait_q);
 	priv->main_thread.task = kthread_run(btmrvl_service_main_thread,
-		&priv->main_thread, "btmrvl_main_service");
+				&priv->main_thread, "btmrvl_main_service");
 
 	priv->btmrvl_dev.hcidev = hdev;
 	priv->btmrvl_dev.card = card;
@@ -717,6 +710,6 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
 EXPORT_SYMBOL_GPL(btmrvl_remove_card);
 
 MODULE_AUTHOR("Marvell International Ltd.");
-MODULE_DESCRIPTION("Marvell Bluetooth Driver v" VERSION);
+MODULE_DESCRIPTION("Marvell Bluetooth Driver ver" VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL v2");
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 14/47] Bluetooth: Remove pointless casts from Marvell debugfs support
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell Bluetooth driver has debugfs support and they are casting
like there is no tomorrow. Remove all of them and magically the code
becomes more readable.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_debugfs.c |  249 +++++++++++++++---------------------
 1 files changed, 106 insertions(+), 143 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 747bb0c..4617bd1 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -51,20 +51,15 @@ static int btmrvl_open_generic(struct inode *inode, struct file *file)
 }
 
 static ssize_t btmrvl_hscfgcmd_write(struct file *file,
-					const char __user *ubuf,
-					size_t count,
-					loff_t *ppos)
+			const char __user *ubuf, size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-
-	long result, ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 10, &result);
@@ -79,38 +74,35 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
 	return count;
 }
 
-static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user * userbuf,
-				    size_t count, loff_t *ppos)
+static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->btmrvl_dev.hscfgcmd);
+						priv->btmrvl_dev.hscfgcmd);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_hscfgcmd_fops = {
-	.read = btmrvl_hscfgcmd_read,
-	.write = btmrvl_hscfgcmd_write,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_hscfgcmd_read,
+	.write	= btmrvl_hscfgcmd_write,
+	.open	= btmrvl_open_generic,
 };
 
 static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
-				   size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	long result, ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 10, &result);
@@ -120,38 +112,35 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
 	return count;
 }
 
-static ssize_t btmrvl_psmode_read(struct file *file, char __user * userbuf,
-				  size_t count, loff_t *ppos)
+static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->btmrvl_dev.psmode);
+						priv->btmrvl_dev.psmode);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_psmode_fops = {
-	.read = btmrvl_psmode_read,
-	.write = btmrvl_psmode_write,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_psmode_read,
+	.write	= btmrvl_psmode_write,
+	.open	= btmrvl_open_generic,
 };
 
 static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
-				  size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	long result, ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 10, &result);
@@ -167,13 +156,12 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
 
 }
 
-static ssize_t btmrvl_pscmd_read(struct file *file, char __user * userbuf,
-				 size_t count, loff_t *ppos)
+static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd);
 
@@ -187,17 +175,15 @@ static const struct file_operations btmrvl_pscmd_fops = {
 };
 
 static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
-				    size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	long result, ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 16, &result);
@@ -207,38 +193,35 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
 	return count;
 }
 
-static ssize_t btmrvl_gpiogap_read(struct file *file, char __user * userbuf,
-				   size_t count, loff_t *ppos)
+static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "0x%x\n",
-			priv->btmrvl_dev.gpio_gap);
+						priv->btmrvl_dev.gpio_gap);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_gpiogap_fops = {
-	.read = btmrvl_gpiogap_read,
-	.write = btmrvl_gpiogap_write,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_gpiogap_read,
+	.write	= btmrvl_gpiogap_write,
+	.open	= btmrvl_open_generic,
 };
 
 static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
-				  size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	long result, ret;
+	struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 10, &result);
@@ -252,13 +235,12 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
 	return count;
 }
 
-static ssize_t btmrvl_hscmd_read(struct file *file, char __user * userbuf,
-				 size_t count, loff_t *ppos)
+static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd);
 
@@ -266,23 +248,21 @@ static ssize_t btmrvl_hscmd_read(struct file *file, char __user * userbuf,
 }
 
 static const struct file_operations btmrvl_hscmd_fops = {
-	.read = btmrvl_hscmd_read,
-	.write = btmrvl_hscmd_write,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_hscmd_read,
+	.write	= btmrvl_hscmd_write,
+	.open	= btmrvl_open_generic,
 };
 
 static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
-				   size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	long result, ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	long result, ret;
 
 	memset(buf, 0, sizeof(buf));
 
-	if (copy_from_user(&buf, ubuf,
-				min_t(size_t, sizeof(buf) - 1, count)))
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
 	ret = strict_strtol(buf, 10, &result);
@@ -293,32 +273,29 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
 }
 
 static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf,
-				  size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
-	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->btmrvl_dev.hsmode);
+	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hsmode);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_hsmode_fops = {
-	.read = btmrvl_hsmode_read,
-	.write = btmrvl_hsmode_write,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_hsmode_read,
+	.write	= btmrvl_hsmode_write,
+	.open	= btmrvl_open_generic,
 };
 
-static ssize_t btmrvl_curpsmode_read(struct file *file, char __user * userbuf,
-				     size_t count, loff_t *ppos)
+static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->psmode);
 
@@ -326,71 +303,65 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user * userbuf,
 }
 
 static const struct file_operations btmrvl_curpsmode_fops = {
-	.read = btmrvl_curpsmode_read,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_curpsmode_read,
+	.open	= btmrvl_open_generic,
 };
 
 static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
-				   size_t count, loff_t *ppos)
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
-	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->adapter->ps_state);
+	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->ps_state);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_psstate_fops = {
-	.read = btmrvl_psstate_read,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_psstate_read,
+	.open	= btmrvl_open_generic,
 };
 
-static ssize_t btmrvl_hsstate_read(struct file *file, char __user * userbuf,
-				   size_t count, loff_t *ppos)
+static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
-	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->adapter->hs_state);
+	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->hs_state);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_hsstate_fops = {
-	.read = btmrvl_hsstate_read,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_hsstate_read,
+	.open	= btmrvl_open_generic,
 };
 
-static ssize_t btmrvl_txdnldready_read(struct file *file, char __user * userbuf,
-				       size_t count, loff_t *ppos)
+static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) file->private_data;
-	int ret;
+	struct btmrvl_private *priv = file->private_data;
 	char buf[16];
+	int ret;
 
 	ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
-			priv->btmrvl_dev.tx_dnld_rdy);
+					priv->btmrvl_dev.tx_dnld_rdy);
 
 	return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 }
 
 static const struct file_operations btmrvl_txdnldready_fops = {
-	.read = btmrvl_txdnldready_read,
-	.open = btmrvl_open_generic,
+	.read	= btmrvl_txdnldready_read,
+	.open	= btmrvl_open_generic,
 };
 
 void btmrvl_debugfs_init(struct hci_dev *hdev)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) hdev->driver_data;
+	struct btmrvl_private *priv = hdev->driver_data;
 	struct btmrvl_debugfs_data *dbg;
 
 	dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
@@ -406,22 +377,16 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
 	dbg->config_dir = debugfs_create_dir("config", dbg->root_dir);
 
 	dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
-					  hdev->driver_data,
-					  &btmrvl_psmode_fops);
-	dbg->pscmd =
-	    debugfs_create_file("pscmd", 0644, dbg->config_dir,
+				hdev->driver_data, &btmrvl_psmode_fops);
+	dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,
 				hdev->driver_data, &btmrvl_pscmd_fops);
-	dbg->gpiogap =
-	    debugfs_create_file("gpiogap", 0644, dbg->config_dir,
+	dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,
 				hdev->driver_data, &btmrvl_gpiogap_fops);
-	dbg->hsmode =
-	    debugfs_create_file("hsmode", 0644, dbg->config_dir,
+	dbg->hsmode =  debugfs_create_file("hsmode", 0644, dbg->config_dir,
 				hdev->driver_data, &btmrvl_hsmode_fops);
-	dbg->hscmd =
-	    debugfs_create_file("hscmd", 0644, dbg->config_dir,
+	dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,
 				hdev->driver_data, &btmrvl_hscmd_fops);
-	dbg->hscfgcmd =
-	    debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
+	dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
 				hdev->driver_data, &btmrvl_hscfgcmd_fops);
 
 	dbg->status_dir = debugfs_create_dir("status", dbg->root_dir);
@@ -429,21 +394,19 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
 						dbg->status_dir,
 						hdev->driver_data,
 						&btmrvl_curpsmode_fops);
-	dbg->psstate =
-	    debugfs_create_file("psstate", 0444, dbg->status_dir,
+	dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,
 				hdev->driver_data, &btmrvl_psstate_fops);
-	dbg->hsstate =
-	    debugfs_create_file("hsstate", 0444, dbg->status_dir,
+	dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,
 				hdev->driver_data, &btmrvl_hsstate_fops);
-	dbg->txdnldready =
-	    debugfs_create_file("txdnldready", 0444, dbg->status_dir,
-				hdev->driver_data, &btmrvl_txdnldready_fops);
+	dbg->txdnldready = debugfs_create_file("txdnldready", 0444,
+						dbg->status_dir,
+						hdev->driver_data,
+						&btmrvl_txdnldready_fops);
 }
 
 void btmrvl_debugfs_remove(struct hci_dev *hdev)
 {
-	struct btmrvl_private *priv =
-				(struct btmrvl_private *) hdev->driver_data;
+	struct btmrvl_private *priv = hdev->driver_data;
 	struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
 
 	if (!dbg)
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 13/47] Bluetooth: Remove pointless ifdef protection for Marvell header files
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

Both header files of the Marvell Bluetooth driver are private anyway and
if the driver happens to include them twice or they create a circular
dependency then the driver needs fixing. So just remove both pointless
ifdefs.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/btmrvl_drv.h  |    5 -----
 drivers/bluetooth/btmrvl_sdio.h |    5 -----
 2 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 7a12f68..5da3be4 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -19,9 +19,6 @@
  *
  */
 
-#ifndef _BTMRVL_DRV_H_
-#define _BTMRVL_DRV_H_
-
 #include <linux/kthread.h>
 #include <linux/bitops.h>
 #include <net/bluetooth/bluetooth.h>
@@ -142,5 +139,3 @@ int btmrvl_prepare_command(struct btmrvl_private *priv);
 void btmrvl_debugfs_init(struct hci_dev *hdev);
 void btmrvl_debugfs_remove(struct hci_dev *hdev);
 #endif
-
-#endif /* _BTMRVL_DRV_H_ */
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 08bef33..6beb340 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -19,9 +19,6 @@
  *
  **/
 
-#ifndef _BTMRVL_SDIO_H_
-#define _BTMRVL_SDIO_H_
-
 #define SDIO_HEADER_LEN			4
 
 /* SD block size can not bigger than 64 due to buf size limit in firmware */
@@ -109,5 +106,3 @@ struct btmrvl_sdio_device {
 /* Macros for Data Alignment : address */
 #define ALIGN_ADDR(p, a)	\
 	((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
-
-#endif /* _BTMRVL_SDIO_H_ */
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 12/47] Bluetooth: Fix compilation of Marvell driver without debugfs
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Makefile entry for the Marvell driver is broken when it comes to
handling the optional DEBUG_FS correctly. That must have been the reason
why they were using select in Kconfig in the first place. Fix this and
make it really optional.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/Makefile |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 75f70e0..b3f57d2 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -15,10 +15,12 @@ obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
 obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
 obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
 
-btmrvl-objs			:= btmrvl_main.o btmrvl_debugfs.o
 obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
 obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
 
+btmrvl-y			:= btmrvl_main.o
+btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
+
 hci_uart-y				:= hci_ldisc.o
 hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
 hci_uart-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o
-- 
1.6.2.5


^ permalink raw reply related

* [PATCH 11/47] Bluetooth: Fix Kconfig for Marvell Bluetooth driver
From: Marcel Holtmann @ 2009-08-30  8:50 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <cover.1251621661.git.marcel@holtmann.org>

The Marvell driver selects DEBUG_FS and FW_LOADER for its core driver
and that is pointless. Don't select DEBUG_FS since it is either enabled
or not and it is not for the driver to enable it. Also FW_LOADER is
only used within the SDIO driver and so just have that one select the
FW_LOADER option.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
 drivers/bluetooth/Kconfig |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 5f04014..652367a 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -172,8 +172,6 @@ config BT_HCIVHCI
 
 config BT_MRVL
 	tristate "Marvell Bluetooth driver support"
-	select FW_LOADER
-	select DEBUG_FS
 	help
 	  The core driver to support Marvell Bluetooth devices.
 
@@ -186,6 +184,7 @@ config BT_MRVL
 config BT_MRVL_SDIO
 	tristate "Marvell BT-over-SDIO driver"
 	depends on BT_MRVL && MMC
+	select FW_LOADER
 	help
 	  The driver for Marvell Bluetooth chipsets with SDIO interface.
 
-- 
1.6.2.5


^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.