* [PATCH 52/64] Bluetooth: Completes the I-frame tx_seq check logic on RECV
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: João Paulo Rechi Vita <jprvita@profusion.mobi>
Add checks for invalid tx_seq and fixes the duplicated tx_seq check.
Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 40 ++++++++++++++++++++++++++++++++++++----
1 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index cfd6724..481cec2 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3302,7 +3302,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
}
}
-static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
+static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
{
struct sk_buff *next_skb;
@@ -3312,13 +3312,16 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_
next_skb = skb_peek(SREJ_QUEUE(sk));
if (!next_skb) {
__skb_queue_tail(SREJ_QUEUE(sk), skb);
- return;
+ return 0;
}
do {
+ if (bt_cb(next_skb)->tx_seq == tx_seq)
+ return -EINVAL;
+
if (bt_cb(next_skb)->tx_seq > tx_seq) {
__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
- return;
+ return 0;
}
if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
@@ -3327,6 +3330,8 @@ static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_
} while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
__skb_queue_tail(SREJ_QUEUE(sk), skb);
+
+ return 0;
}
static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
@@ -3579,6 +3584,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
u8 tx_seq = __get_txseq(rx_control);
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
+ u8 tx_seq_offset, expected_tx_seq_offset;
int num_to_ack = (pi->tx_win/6) + 1;
int err = 0;
@@ -3598,6 +3604,16 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
if (tx_seq == pi->expected_tx_seq)
goto expected;
+ tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+ if (tx_seq_offset < 0)
+ tx_seq_offset += 64;
+
+ /* invalid tx_seq */
+ if (tx_seq_offset >= pi->tx_win) {
+ l2cap_send_disconn_req(pi->conn, sk);
+ goto drop;
+ }
+
if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
struct srej_list *first;
@@ -3617,7 +3633,10 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
}
} else {
struct srej_list *l;
- l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
+
+ /* duplicated tx_seq */
+ if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
+ goto drop;
list_for_each_entry(l, SREJ_LIST(sk), list) {
if (l->tx_seq == tx_seq) {
@@ -3628,6 +3647,15 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
l2cap_send_srejframe(sk, tx_seq);
}
} else {
+ expected_tx_seq_offset =
+ (pi->expected_tx_seq - pi->buffer_seq) % 64;
+ if (expected_tx_seq_offset < 0)
+ expected_tx_seq_offset += 64;
+
+ /* duplicated tx_seq */
+ if (tx_seq_offset < expected_tx_seq_offset)
+ goto drop;
+
pi->conn_state |= L2CAP_CONN_SREJ_SENT;
INIT_LIST_HEAD(SREJ_LIST(sk));
@@ -3676,6 +3704,10 @@ expected:
l2cap_send_ack(pi);
return 0;
+
+drop:
+ kfree_skb(skb);
+ return 0;
}
static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
--
1.6.6.1
^ permalink raw reply related
* [PATCH 53/64] Bluetooth: Implement Local Busy Condition handling
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
Supports Local Busy condition handling through a waitqueue that wake ups
each 200ms and try to push the packets to the upper layer. If it can
push all the queue then it leaves the Local Busy state.
The patch modifies the behaviour of l2cap_ertm_reassembly_sdu() to
support retry of the push operation.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/l2cap.h | 6 ++
net/bluetooth/l2cap.c | 187 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 172 insertions(+), 21 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 8942c2f..d0185cc 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -35,6 +35,7 @@
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 672
#define L2CAP_DEFAULT_ACK_TO 200
+#define L2CAP_LOCAL_BUSY_TRIES 12
#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
@@ -294,6 +295,7 @@ struct l2cap_conn {
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue)
+#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue)
#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list)
struct srej_list {
@@ -356,6 +358,8 @@ struct l2cap_pinfo {
struct timer_list ack_timer;
struct sk_buff_head tx_queue;
struct sk_buff_head srej_queue;
+ struct sk_buff_head busy_queue;
+ struct work_struct busy_work;
struct srej_list srej_l;
struct l2cap_conn *conn;
struct sock *next_c;
@@ -383,6 +387,8 @@ struct l2cap_pinfo {
#define L2CAP_CONN_LOCAL_BUSY 0x0040
#define L2CAP_CONN_REJ_ACT 0x0080
#define L2CAP_CONN_SEND_FBIT 0x0100
+#define L2CAP_CONN_RNR_SENT 0x0200
+#define L2CAP_CONN_SAR_RETRY 0x0400
#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 481cec2..103e4b5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -68,10 +68,14 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
static const struct proto_ops l2cap_sock_ops;
+static struct workqueue_struct *_busy_wq;
+
static struct bt_sock_list l2cap_sk_list = {
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
};
+static void l2cap_busy_work(struct work_struct *work);
+
static void __l2cap_sock_close(struct sock *sk, int reason);
static void l2cap_sock_close(struct sock *sk);
static void l2cap_sock_kill(struct sock *sk);
@@ -386,9 +390,10 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
{
- if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY)
+ if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
control |= L2CAP_SUPER_RCV_NOT_READY;
- else
+ pi->conn_state |= L2CAP_CONN_RNR_SENT;
+ } else
control |= L2CAP_SUPER_RCV_READY;
control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -816,6 +821,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
skb_queue_head_init(TX_QUEUE(sk));
skb_queue_head_init(SREJ_QUEUE(sk));
+ skb_queue_head_init(BUSY_QUEUE(sk));
INIT_LIST_HEAD(SREJ_LIST(sk));
}
@@ -1439,6 +1445,7 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi)
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
control |= L2CAP_SUPER_RCV_NOT_READY;
+ pi->conn_state |= L2CAP_CONN_RNR_SENT;
l2cap_send_sframe(pi, control);
return;
} else if (l2cap_ertm_send(sk) == 0) {
@@ -2279,6 +2286,9 @@ static inline void l2cap_ertm_init(struct sock *sk)
l2cap_ack_timeout, (unsigned long) sk);
__skb_queue_head_init(SREJ_QUEUE(sk));
+ __skb_queue_head_init(BUSY_QUEUE(sk));
+
+ INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
}
static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
@@ -3046,6 +3056,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
skb_queue_purge(SREJ_QUEUE(sk));
+ skb_queue_purge(BUSY_QUEUE(sk));
del_timer(&l2cap_pi(sk)->retrans_timer);
del_timer(&l2cap_pi(sk)->monitor_timer);
del_timer(&l2cap_pi(sk)->ack_timer);
@@ -3077,6 +3088,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
skb_queue_purge(SREJ_QUEUE(sk));
+ skb_queue_purge(BUSY_QUEUE(sk));
del_timer(&l2cap_pi(sk)->retrans_timer);
del_timer(&l2cap_pi(sk)->monitor_timer);
del_timer(&l2cap_pi(sk)->ack_timer);
@@ -3287,6 +3299,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
l2cap_send_sframe(pi, control);
+ pi->conn_state |= L2CAP_CONN_RNR_SENT;
pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
}
@@ -3338,7 +3351,7 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct sk_buff *_skb;
- int err = 0;
+ int err;
switch (control & L2CAP_CTRL_SAR) {
case L2CAP_SDU_UNSEGMENTED:
@@ -3356,16 +3369,18 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
goto drop;
pi->sdu_len = get_unaligned_le16(skb->data);
- skb_pull(skb, 2);
if (pi->sdu_len > pi->imtu)
goto disconnect;
pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
- if (!pi->sdu) {
- err = -ENOMEM;
- break;
- }
+ if (!pi->sdu)
+ return -ENOMEM;
+
+ /* pull sdu_len bytes only after alloc, because of Local Busy
+ * condition we have to be sure that this will be executed
+ * only once, i.e., when alloc does not fail */
+ skb_pull(skb, 2);
memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
@@ -3395,28 +3410,40 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
if (!pi->sdu)
goto disconnect;
- memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+ if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
+ memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
- pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
- pi->partial_sdu_len += skb->len;
+ pi->partial_sdu_len += skb->len;
- if (pi->partial_sdu_len > pi->imtu)
- goto drop;
+ if (pi->partial_sdu_len > pi->imtu)
+ goto drop;
- if (pi->partial_sdu_len != pi->sdu_len)
- goto drop;
+ if (pi->partial_sdu_len != pi->sdu_len)
+ goto drop;
+ }
_skb = skb_clone(pi->sdu, GFP_ATOMIC);
+ if (!_skb) {
+ pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+ return -ENOMEM;
+ }
+
err = sock_queue_rcv_skb(sk, _skb);
- if (err < 0)
+ if (err < 0) {
kfree_skb(_skb);
+ pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+ return err;
+ }
+
+ pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
+ pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
kfree_skb(pi->sdu);
break;
}
kfree_skb(skb);
- return err;
+ return 0;
drop:
kfree_skb(pi->sdu);
@@ -3428,6 +3455,115 @@ disconnect:
return 0;
}
+static void l2cap_busy_work(struct work_struct *work)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct l2cap_pinfo *pi =
+ container_of(work, struct l2cap_pinfo, busy_work);
+ struct sock *sk = (struct sock *)pi;
+ int n_tries = 0, timeo = HZ/5, err;
+ struct sk_buff *skb;
+ u16 control;
+
+ lock_sock(sk);
+
+ add_wait_queue(sk->sk_sleep, &wait);
+ while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
+ err = -EBUSY;
+ l2cap_send_disconn_req(pi->conn, sk);
+ goto done;
+ }
+
+ if (!timeo)
+ timeo = HZ/5;
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ goto done;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+
+ err = sock_error(sk);
+ if (err)
+ goto done;
+
+ while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
+ control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
+ err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+ if (err < 0) {
+ skb_queue_head(BUSY_QUEUE(sk), skb);
+ break;
+ }
+
+ pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+ }
+
+ if (!skb)
+ break;
+ }
+
+ if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
+ goto done;
+
+ control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+ control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+ l2cap_send_sframe(pi, control);
+ l2cap_pi(sk)->retry_count = 1;
+
+ del_timer(&pi->retrans_timer);
+ __mod_monitor_timer();
+
+ l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+
+done:
+ pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
+ pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sk_sleep, &wait);
+
+ release_sock(sk);
+}
+
+static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
+{
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ int sctrl, err;
+
+ if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+ bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
+ __skb_queue_tail(BUSY_QUEUE(sk), skb);
+ return -EBUSY;
+ }
+
+ err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+ if (err >= 0) {
+ pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+ return err;
+ }
+
+ /* Busy Condition */
+ pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
+ bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
+ __skb_queue_tail(BUSY_QUEUE(sk), skb);
+
+ sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+ sctrl |= L2CAP_SUPER_RCV_NOT_READY;
+ l2cap_send_sframe(pi, sctrl);
+
+ pi->conn_state |= L2CAP_CONN_RNR_SENT;
+
+ queue_work(_busy_wq, &pi->busy_work);
+
+ return err;
+}
+
static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -3614,6 +3750,9 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
goto drop;
}
+ if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
+ goto drop;
+
if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
struct srej_list *first;
@@ -3662,6 +3801,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
pi->buffer_seq_srej = pi->buffer_seq;
__skb_queue_head_init(SREJ_QUEUE(sk));
+ __skb_queue_head_init(BUSY_QUEUE(sk));
l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
pi->conn_state |= L2CAP_CONN_SEND_PBIT;
@@ -3691,11 +3831,9 @@ expected:
}
}
- pi->buffer_seq = (pi->buffer_seq + 1) % 64;
-
- err = l2cap_ertm_reassembly_sdu(sk, skb, rx_control);
+ err = l2cap_push_rx_skb(sk, skb, rx_control);
if (err < 0)
- return err;
+ return 0;
__mod_ack_timer();
@@ -4406,6 +4544,10 @@ static int __init l2cap_init(void)
if (err < 0)
return err;
+ _busy_wq = create_singlethread_workqueue("l2cap");
+ if (!_busy_wq)
+ goto error;
+
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
if (err < 0) {
BT_ERR("L2CAP socket registration failed");
@@ -4440,6 +4582,9 @@ static void __exit l2cap_exit(void)
{
debugfs_remove(l2cap_debugfs);
+ flush_workqueue(_busy_wq);
+ destroy_workqueue(_busy_wq);
+
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
BT_ERR("L2CAP socket unregistration failed");
--
1.6.6.1
^ permalink raw reply related
* [PATCH 54/64] Bluetooth: Add wait_queue to wait ack of all sent packets
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
To guarantee that all packets we sent were received we need to wait for
theirs ack before shutdown the socket.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 103e4b5..9d514f9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1242,6 +1242,37 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
return 0;
}
+static int __l2cap_wait_ack(struct sock *sk)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int err = 0;
+ int timeo = HZ/5;
+
+ add_wait_queue(sk->sk_sleep, &wait);
+ while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (!timeo)
+ timeo = HZ/5;
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ break;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+
+ err = sock_error(sk);
+ if (err)
+ break;
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sk_sleep, &wait);
+ return err;
+}
+
static void l2cap_monitor_timeout(unsigned long arg)
{
struct sock *sk = (void *) arg;
@@ -2059,6 +2090,9 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
lock_sock(sk);
if (!sk->sk_shutdown) {
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+ err = __l2cap_wait_ack(sk);
+
sk->sk_shutdown = SHUTDOWN_MASK;
l2cap_sock_clear_timer(sk);
__l2cap_sock_close(sk, 0);
--
1.6.6.1
^ permalink raw reply related
* [PATCH 55/64] Bluetooth: Fix race condition on l2cap_ertm_send()
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
l2cap_ertm_send() can be called both from user context and bottom half
context. The socket locks for that contexts are different, the user
context uses a mutex(which can sleep) and the second one uses a
spinlock_bh. That creates a race condition when we have interruptions on
both contexts at the same time.
The better way to solve this is to add a new spinlock to lock
l2cap_ertm_send() and the vars it access. The other solution was to defer
l2cap_ertm_send() with a workqueue, but we the sending process already
has one defer on the hci layer. It's not a good idea add another one.
The patch refactor the code to create l2cap_retransmit_frames(), then we
encapulate the lock of l2cap_ertm_send() for some call. It also changes
l2cap_retransmit_frame() to l2cap_retransmit_one_frame() to avoid
confusion
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap.c | 99 +++++++++++++++++++++++++++--------------
2 files changed, 67 insertions(+), 33 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d0185cc..7c695bf 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -353,6 +353,7 @@ struct l2cap_pinfo {
__le16 sport;
+ spinlock_t send_lock;
struct timer_list retrans_timer;
struct timer_list monitor_timer;
struct timer_list ack_timer;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9d514f9..fe663e9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1368,7 +1368,7 @@ static int l2cap_streaming_send(struct sock *sk)
return 0;
}
-static void l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
+static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct sk_buff *skb, *tx_skb;
@@ -1467,10 +1467,29 @@ static int l2cap_ertm_send(struct sock *sk)
return nsent;
}
+static int l2cap_retransmit_frames(struct sock *sk)
+{
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ int ret;
+
+ spin_lock_bh(&pi->send_lock);
+
+ if (!skb_queue_empty(TX_QUEUE(sk)))
+ sk->sk_send_head = TX_QUEUE(sk)->next;
+
+ pi->next_tx_seq = pi->expected_ack_seq;
+ ret = l2cap_ertm_send(sk);
+
+ spin_unlock_bh(&pi->send_lock);
+
+ return ret;
+}
+
static void l2cap_send_ack(struct l2cap_pinfo *pi)
{
struct sock *sk = (struct sock *)pi;
u16 control = 0;
+ int nframes;
control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -1479,10 +1498,17 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi)
pi->conn_state |= L2CAP_CONN_RNR_SENT;
l2cap_send_sframe(pi, control);
return;
- } else if (l2cap_ertm_send(sk) == 0) {
- control |= L2CAP_SUPER_RCV_READY;
- l2cap_send_sframe(pi, control);
}
+
+ spin_lock_bh(&pi->send_lock);
+ nframes = l2cap_ertm_send(sk);
+ spin_unlock_bh(&pi->send_lock);
+
+ if (nframes > 0)
+ return;
+
+ control |= L2CAP_SUPER_RCV_READY;
+ l2cap_send_sframe(pi, control);
}
static void l2cap_send_srejtail(struct sock *sk)
@@ -1673,8 +1699,10 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
size += buflen;
}
skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
+ spin_lock_bh(&pi->send_lock);
if (sk->sk_send_head == NULL)
sk->sk_send_head = sar_queue.next;
+ spin_unlock_bh(&pi->send_lock);
return size;
}
@@ -1745,8 +1773,15 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
goto done;
}
__skb_queue_tail(TX_QUEUE(sk), skb);
+
+ if (pi->mode == L2CAP_MODE_ERTM)
+ spin_lock_bh(&pi->send_lock);
+
if (sk->sk_send_head == NULL)
sk->sk_send_head = skb;
+
+ if (pi->mode == L2CAP_MODE_ERTM)
+ spin_unlock_bh(&pi->send_lock);
} else {
/* Segment SDU into multiples PDUs */
err = l2cap_sar_segment_sdu(sk, msg, len);
@@ -1754,10 +1789,13 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
goto done;
}
- if (pi->mode == L2CAP_MODE_STREAMING)
+ if (pi->mode == L2CAP_MODE_STREAMING) {
err = l2cap_streaming_send(sk);
- else
+ } else {
+ spin_lock_bh(&pi->send_lock);
err = l2cap_ertm_send(sk);
+ spin_unlock_bh(&pi->send_lock);
+ }
if (err >= 0)
err = len;
@@ -2321,6 +2359,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
__skb_queue_head_init(SREJ_QUEUE(sk));
__skb_queue_head_init(BUSY_QUEUE(sk));
+ spin_lock_init(&l2cap_pi(sk)->send_lock);
INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
}
@@ -3340,7 +3379,9 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
__mod_retrans_timer();
+ spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
+ spin_unlock_bh(&pi->send_lock);
if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
pi->frames_sent == 0) {
@@ -3857,12 +3898,8 @@ expected:
if (rx_control & L2CAP_CTRL_FINAL) {
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else {
- if (!skb_queue_empty(TX_QUEUE(sk)))
- sk->sk_send_head = TX_QUEUE(sk)->next;
- pi->next_tx_seq = pi->expected_ack_seq;
- l2cap_ertm_send(sk);
- }
+ else
+ l2cap_retransmit_frames(sk);
}
err = l2cap_push_rx_skb(sk, skb, rx_control);
@@ -3907,12 +3944,8 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else {
- if (!skb_queue_empty(TX_QUEUE(sk)))
- sk->sk_send_head = TX_QUEUE(sk)->next;
- pi->next_tx_seq = pi->expected_ack_seq;
- l2cap_ertm_send(sk);
- }
+ else
+ l2cap_retransmit_frames(sk);
} else {
if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
@@ -3920,10 +3953,13 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
__mod_retrans_timer();
pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
- if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
+ if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
l2cap_send_ack(pi);
- else
+ } else {
+ spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
+ spin_unlock_bh(&pi->send_lock);
+ }
}
}
@@ -3940,17 +3976,10 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
if (rx_control & L2CAP_CTRL_FINAL) {
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
- else {
- if (!skb_queue_empty(TX_QUEUE(sk)))
- sk->sk_send_head = TX_QUEUE(sk)->next;
- pi->next_tx_seq = pi->expected_ack_seq;
- l2cap_ertm_send(sk);
- }
+ else
+ l2cap_retransmit_frames(sk);
} else {
- if (!skb_queue_empty(TX_QUEUE(sk)))
- sk->sk_send_head = TX_QUEUE(sk)->next;
- pi->next_tx_seq = pi->expected_ack_seq;
- l2cap_ertm_send(sk);
+ l2cap_retransmit_frames(sk);
if (pi->conn_state & L2CAP_CONN_WAIT_F)
pi->conn_state |= L2CAP_CONN_REJ_ACT;
@@ -3966,8 +3995,12 @@ static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
if (rx_control & L2CAP_CTRL_POLL) {
pi->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(sk);
- l2cap_retransmit_frame(sk, tx_seq);
+ l2cap_retransmit_one_frame(sk, tx_seq);
+
+ spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
+ spin_unlock_bh(&pi->send_lock);
+
if (pi->conn_state & L2CAP_CONN_WAIT_F) {
pi->srej_save_reqseq = tx_seq;
pi->conn_state |= L2CAP_CONN_SREJ_ACT;
@@ -3977,9 +4010,9 @@ static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
pi->srej_save_reqseq == tx_seq)
pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
else
- l2cap_retransmit_frame(sk, tx_seq);
+ l2cap_retransmit_one_frame(sk, tx_seq);
} else {
- l2cap_retransmit_frame(sk, tx_seq);
+ l2cap_retransmit_one_frame(sk, tx_seq);
if (pi->conn_state & L2CAP_CONN_WAIT_F) {
pi->srej_save_reqseq = tx_seq;
pi->conn_state |= L2CAP_CONN_SREJ_ACT;
--
1.6.6.1
^ permalink raw reply related
* [PATCH 56/64] Bluetooth: Prevents buffer overflow on l2cap_ertm_reassembly_sdu()
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
The checks should be done before the the memcpy to avoid buffer
overflow.
Reported-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index fe663e9..9ef01c3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3470,12 +3470,12 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
if (!pi->sdu)
goto disconnect;
- 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)
goto drop;
+ memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
break;
case L2CAP_SDU_END:
@@ -3486,8 +3486,6 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
goto disconnect;
if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
- memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
pi->partial_sdu_len += skb->len;
if (pi->partial_sdu_len > pi->imtu)
@@ -3495,6 +3493,8 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
if (pi->partial_sdu_len != pi->sdu_len)
goto drop;
+
+ memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
}
_skb = skb_clone(pi->sdu, GFP_ATOMIC);
--
1.6.6.1
^ permalink raw reply related
* [PATCH 57/64] Bluetooth: Fix spec error in the RemoteBusy Logic
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
On the receipt of an RR(P=1) under RemoteBusy set to TRUE(on the RECV
state table) we have to call sendIorRRorRNR(F=1) and just after set
RemoteBusy to False. This leads to a freeze in the sending process since
it's not allowed send data with RemoteBusy set to true and no one
call SendPending-I-Frames after set RemoteBusy to false(The last action
for that event).
Actually sendIorRRorRNR() calls SendPending-I-Frames but at that moment
RemoteBusy is still True and we cannot send any frame, after, no one
calls SendPending-I-Frames again and the sending process stops.
The solution here is to set RemoteBusy to false inside
SendPending-I-Frames just before call SendPending-I-Frames. That will
make SendPending-I-Frames able to send frames. This solution is similar
to what RR(P=0)(F=0) on the RECV table and RR(P=1) on the SREJ_SENT
table do.
Actually doesn't make any sense call SendPending-I-Frames if we can send
any frame, i. e., RemoteBusy is True.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9ef01c3..ba49f9a 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3379,6 +3379,8 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
__mod_retrans_timer();
+ pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+
spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
spin_unlock_bh(&pi->send_lock);
@@ -3936,7 +3938,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
l2cap_send_srejtail(sk);
} else {
l2cap_send_i_or_rr_or_rnr(sk);
- pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
}
} else if (rx_control & L2CAP_CTRL_FINAL) {
--
1.6.6.1
^ permalink raw reply related
* [PATCH 58/64] Bluetooth: Create per controller workqueue
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
Instead of having a global workqueue for all controllers, it makes
more sense to have a workqueue per controller.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_core.c | 14 ++++++++++++++
net/bluetooth/hci_sysfs.c | 16 +++-------------
3 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4511df2..e42f6ed 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -107,6 +107,8 @@ struct hci_dev {
unsigned long acl_last_tx;
unsigned long sco_last_tx;
+ struct workqueue_struct *workqueue;
+
struct tasklet_struct cmd_task;
struct tasklet_struct rx_task;
struct tasklet_struct tx_task;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 904f1e8..5e83f8e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -37,6 +37,7 @@
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/skbuff.h>
+#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/rfkill.h>
@@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev)
write_unlock_bh(&hci_dev_list_lock);
+ hdev->workqueue = create_singlethread_workqueue(hdev->name);
+ if (!hdev->workqueue)
+ goto nomem;
+
hci_register_sysfs(hdev);
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_REG);
return id;
+
+nomem:
+ write_lock_bh(&hci_dev_list_lock);
+ list_del(&hdev->list);
+ write_unlock_bh(&hci_dev_list_lock);
+
+ return -ENOMEM;
}
EXPORT_SYMBOL(hci_register_dev);
@@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_unregister_sysfs(hdev);
+ destroy_workqueue(hdev->workqueue);
+
__hci_dev_put(hdev);
return 0;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 0e8e1a5..a978449 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -14,8 +14,6 @@ static struct class *bt_class;
struct dentry *bt_debugfs = NULL;
EXPORT_SYMBOL_GPL(bt_debugfs);
-static struct workqueue_struct *bt_workq;
-
static inline char *link_typetostr(int type)
{
switch (type) {
@@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
{
BT_DBG("conn %p", conn);
- queue_work(bt_workq, &conn->work_add);
+ queue_work(conn->hdev->workqueue, &conn->work_add);
}
void hci_conn_del_sysfs(struct hci_conn *conn)
{
BT_DBG("conn %p", conn);
- queue_work(bt_workq, &conn->work_del);
+ queue_work(conn->hdev->workqueue, &conn->work_del);
}
static inline char *host_bustostr(int bus)
@@ -487,17 +485,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
int __init bt_sysfs_init(void)
{
- bt_workq = create_singlethread_workqueue("bluetooth");
- if (!bt_workq)
- return -ENOMEM;
-
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
bt_class = class_create(THIS_MODULE, "bluetooth");
- if (IS_ERR(bt_class)) {
- destroy_workqueue(bt_workq);
+ if (IS_ERR(bt_class))
return PTR_ERR(bt_class);
- }
return 0;
}
@@ -507,6 +499,4 @@ void bt_sysfs_cleanup(void)
class_destroy(bt_class);
debugfs_remove_recursive(bt_debugfs);
-
- destroy_workqueue(bt_workq);
}
--
1.6.6.1
^ permalink raw reply related
* [PATCH 59/64] Bluetooth: Fix storing negative values as unsigned char
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Dan Carpenter <error27@gmail.com>
This is mostly cleanup. There is only one caller and it just checks for
non-zero return values. Still "ret" should be int because we want to return
-EINVAL on errors.
Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
drivers/bluetooth/btmrvl_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 53a43ad..49ec89c 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -66,7 +66,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
{
struct btmrvl_adapter *adapter = priv->adapter;
struct btmrvl_event *event;
- u8 ret = 0;
+ int ret = 0;
event = (struct btmrvl_event *) skb->data;
if (event->ec != 0xff) {
--
1.6.6.1
^ permalink raw reply related
* [PATCH 60/64] Bluetooth: Decode btmrvl MODULE_BRINGUP_REG response correctly
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Bing Zhao <bzhao@marvell.com>
The MODULE_BRINGUP_REQ command response returns success with
either 0x00 or 0x0c.
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
drivers/bluetooth/btmrvl_drv.h | 5 ++++-
drivers/bluetooth/btmrvl_main.c | 6 ++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 2047275..da68c62 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -88,8 +88,11 @@ struct btmrvl_private {
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
#define BT_CMD_MODULE_CFG_REQ 0x5B
-/* Sub-commands: Module Bringup/Shutdown Request */
+/* Sub-commands: Module Bringup/Shutdown Request/Response */
#define MODULE_BRINGUP_REQ 0xF1
+#define MODULE_BROUGHT_UP 0x00
+#define MODULE_ALREADY_UP 0x0C
+
#define MODULE_SHUTDOWN_REQ 0xF2
#define BT_EVENT_POWER_STATE 0x20
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 49ec89c..87d0d3d 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -112,8 +112,10 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
case BT_CMD_MODULE_CFG_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");
+ BT_DBG("EVENT:%s",
+ ((event->data[2] == MODULE_BROUGHT_UP) ||
+ (event->data[2] == MODULE_ALREADY_UP)) ?
+ "Bring-up succeed" : "Bring-up failed");
} else if (priv->btmrvl_dev.sendcmdflag &&
event->data[1] == MODULE_SHUTDOWN_REQ) {
BT_DBG("EVENT:%s", (event->data[2]) ?
--
1.6.6.1
^ permalink raw reply related
* [PATCH 61/64] Bluetooth: Separate btmrvl_register_hdev() from btmrvl_add_card()
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Bing Zhao <bzhao@marvell.com>
Move btmrvl hdev registration code out of btmrvl_add_card().
New function btmrvl_register_hdev() is added.
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
drivers/bluetooth/btmrvl_drv.h | 1 +
drivers/bluetooth/btmrvl_main.c | 75 ++++++++++++++++++++++----------------
drivers/bluetooth/btmrvl_sdio.c | 7 +++-
3 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index da68c62..bf6d54f 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -126,6 +126,7 @@ struct btmrvl_event {
/* Prototype of global function */
+int btmrvl_register_hdev(struct btmrvl_private *priv);
struct btmrvl_private *btmrvl_add_card(void *card);
int btmrvl_remove_card(struct btmrvl_private *priv);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 87d0d3d..ec48bfe 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -524,47 +524,20 @@ static int btmrvl_service_main_thread(void *data)
return 0;
}
-struct btmrvl_private *btmrvl_add_card(void *card)
+int btmrvl_register_hdev(struct btmrvl_private *priv)
{
struct hci_dev *hdev = NULL;
- struct btmrvl_private *priv;
int ret;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- BT_ERR("Can not allocate priv");
- goto err_priv;
- }
-
- priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL);
- if (!priv->adapter) {
- BT_ERR("Allocate buffer for btmrvl_adapter failed!");
- goto err_adapter;
- }
-
- btmrvl_init_adapter(priv);
-
hdev = hci_alloc_dev();
if (!hdev) {
BT_ERR("Can not allocate HCI device");
goto err_hdev;
}
- BT_DBG("Starting kthread...");
- priv->main_thread.priv = priv;
- spin_lock_init(&priv->driver_lock);
-
- 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->btmrvl_dev.hcidev = hdev;
- priv->btmrvl_dev.card = card;
-
hdev->driver_data = priv;
- priv->btmrvl_dev.tx_dnld_rdy = true;
-
hdev->bus = HCI_SDIO;
hdev->open = btmrvl_open;
hdev->close = btmrvl_close;
@@ -574,6 +547,8 @@ struct btmrvl_private *btmrvl_add_card(void *card)
hdev->ioctl = btmrvl_ioctl;
hdev->owner = THIS_MODULE;
+ btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+
ret = hci_register_dev(hdev);
if (ret < 0) {
BT_ERR("Can not register HCI device");
@@ -584,16 +559,52 @@ struct btmrvl_private *btmrvl_add_card(void *card)
btmrvl_debugfs_init(hdev);
#endif
- return priv;
+ return 0;
err_hci_register_dev:
- /* Stop the thread servicing the interrupts */
- kthread_stop(priv->main_thread.task);
-
hci_free_dev(hdev);
err_hdev:
+ /* Stop the thread servicing the interrupts */
+ kthread_stop(priv->main_thread.task);
+
btmrvl_free_adapter(priv);
+ kfree(priv);
+
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(btmrvl_register_hdev);
+
+struct btmrvl_private *btmrvl_add_card(void *card)
+{
+ struct btmrvl_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ BT_ERR("Can not allocate priv");
+ goto err_priv;
+ }
+
+ priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL);
+ if (!priv->adapter) {
+ BT_ERR("Allocate buffer for btmrvl_adapter failed!");
+ goto err_adapter;
+ }
+
+ btmrvl_init_adapter(priv);
+
+ BT_DBG("Starting kthread...");
+ priv->main_thread.priv = priv;
+ spin_lock_init(&priv->driver_lock);
+
+ 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->btmrvl_dev.card = card;
+ priv->btmrvl_dev.tx_dnld_rdy = true;
+
+ return priv;
err_adapter:
kfree(priv);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 0dba76a..df0773e 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -931,7 +931,12 @@ 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;
- btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+ if (btmrvl_register_hdev(priv)) {
+ BT_ERR("Register hdev failed!");
+ ret = -ENODEV;
+ goto disable_host_int;
+ }
+
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
--
1.6.6.1
^ permalink raw reply related
* [PATCH 62/64] Bluetooth: Set hdev->dev_type based on Marvell device type
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Bing Zhao <bzhao@marvell.com>
Get the device type from MODULE_BRINGUP_REQ command response.
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
drivers/bluetooth/btmrvl_drv.h | 2 ++
drivers/bluetooth/btmrvl_main.c | 9 +++++++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index bf6d54f..bed0ba6 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -42,6 +42,8 @@ struct btmrvl_device {
void *card;
struct hci_dev *hcidev;
+ u8 dev_type;
+
u8 tx_dnld_rdy;
u8 psmode;
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index ec48bfe..ee37ef0 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -116,6 +116,13 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
((event->data[2] == MODULE_BROUGHT_UP) ||
(event->data[2] == MODULE_ALREADY_UP)) ?
"Bring-up succeed" : "Bring-up failed");
+
+ if (event->length > 3)
+ priv->btmrvl_dev.dev_type = event->data[3];
+ else
+ priv->btmrvl_dev.dev_type = HCI_BREDR;
+
+ BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type);
} else if (priv->btmrvl_dev.sendcmdflag &&
event->data[1] == MODULE_SHUTDOWN_REQ) {
BT_DBG("EVENT:%s", (event->data[2]) ?
@@ -549,6 +556,8 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
+ hdev->dev_type = priv->btmrvl_dev.dev_type;
+
ret = hci_register_dev(hdev);
if (ret < 0) {
BT_ERR("Can not register HCI device");
--
1.6.6.1
^ permalink raw reply related
* [PATCH 63/64] Bluetooth: Use strict_strtoul instead of simple_strtoul
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Tomas Winkler <tomas.winkler@intel.com>
Use strict_strtoul as suggested by checkpatch.pl for more strict input
checking.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_sysfs.c | 18 ++++++------------
1 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index a978449..463ffa4 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -281,11 +281,9 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at
static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct hci_dev *hdev = dev_get_drvdata(dev);
- char *ptr;
- __u32 val;
+ unsigned long val;
- val = simple_strtoul(buf, &ptr, 10);
- if (ptr == buf)
+ if (strict_strtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val != 0 && (val < 500 || val > 3600000))
@@ -305,11 +303,9 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu
static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct hci_dev *hdev = dev_get_drvdata(dev);
- char *ptr;
- __u16 val;
+ unsigned long val;
- val = simple_strtoul(buf, &ptr, 10);
- if (ptr == buf)
+ if (strict_strtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val < 0x0002 || val > 0xFFFE || val % 2)
@@ -332,11 +328,9 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu
static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct hci_dev *hdev = dev_get_drvdata(dev);
- char *ptr;
- __u16 val;
+ unsigned long val;
- val = simple_strtoul(buf, &ptr, 10);
- if (ptr == buf)
+ if (strict_strtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val < 0x0002 || val > 0xFFFE || val % 2)
--
1.6.6.1
^ permalink raw reply related
* [PATCH 64/64] Bluetooth: Fix issues where sk_sleep() helper is needed now
From: Marcel Holtmann @ 2010-05-10 9:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
There were some left-overs that used sk->sk_sleep instead of the new
sk_sleep() helper.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index ba49f9a..673a368 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1248,7 +1248,7 @@ static int __l2cap_wait_ack(struct sock *sk)
int err = 0;
int timeo = HZ/5;
- add_wait_queue(sk->sk_sleep, &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -1269,7 +1269,7 @@ static int __l2cap_wait_ack(struct sock *sk)
break;
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(sk->sk_sleep, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
return err;
}
@@ -3544,7 +3544,7 @@ static void l2cap_busy_work(struct work_struct *work)
lock_sock(sk);
- add_wait_queue(sk->sk_sleep, &wait);
+ add_wait_queue(sk_sleep(sk), &wait);
while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -3603,7 +3603,7 @@ done:
pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
set_current_state(TASK_RUNNING);
- remove_wait_queue(sk->sk_sleep, &wait);
+ remove_wait_queue(sk_sleep(sk), &wait);
release_sock(sk);
}
--
1.6.6.1
^ permalink raw reply related
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: David Miller @ 2010-05-10 9:47 UTC (permalink / raw)
To: marcel; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
From: Marcel Holtmann <marcel@holtmann.org>
Date: Mon, 10 May 2010 11:36:50 +0200
> this is the big merge for the L2CAP Enhanced Retransmission support work
> done by Gustavo F. Padovan. All other changes are small cleanups.
Yeah, "big", as in "too big".
Please sync with me more often so you don't have to obliterate the
list with unacceptable 64 posting patch bombs. Nobody is going to
really review such a huge patch set in any serious manner, which
makes posting those patches almost worthless.
Anything more than about 10 or 20 at a time is way too much.
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: Marcel Holtmann @ 2010-05-10 10:41 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20100510.024750.45124664.davem@davemloft.net>
Hi Dave,
> > this is the big merge for the L2CAP Enhanced Retransmission support work
> > done by Gustavo F. Padovan. All other changes are small cleanups.
>
> Yeah, "big", as in "too big".
>
> Please sync with me more often so you don't have to obliterate the
> list with unacceptable 64 posting patch bombs. Nobody is going to
> really review such a huge patch set in any serious manner, which
> makes posting those patches almost worthless.
>
> Anything more than about 10 or 20 at a time is way too much.
normally we don't have any big changes in the Bluetooth kernel side.
This is the first one that adds a big set of features. And it is limited
to the L2CAP layer. I took it out of last kernel release since it was
incomplete and would not have been useful. Right now it is in a stage
where it becomes usable. Only new profiles like the Health Medical stuff
is making use of these features for now. However in the future more and
more profile will requires support for it.
The number of patches are not getting smaller. Except I arbitrarily
merge them together. I am not planning to do that since I think it is
not a good idea at all. And the patches have been reviewed by João Paulo
Rechi Vita who worked with Gustavo on these changes.
So do you want to postpone this for 2.6.35 merge window?
Regards
Marcel
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: David Miller @ 2010-05-10 11:08 UTC (permalink / raw)
To: marcel; +Cc: netdev
In-Reply-To: <1273488069.375.30.camel@localhost.localdomain>
From: Marcel Holtmann <marcel@holtmann.org>
Date: Mon, 10 May 2010 12:41:09 +0200
> normally we don't have any big changes in the Bluetooth kernel side.
> This is the first one that adds a big set of features. And it is limited
> to the L2CAP layer. I took it out of last kernel release since it was
> incomplete and would not have been useful. Right now it is in a stage
> where it becomes usable. Only new profiles like the Health Medical stuff
> is making use of these features for now. However in the future more and
> more profile will requires support for it.
>
> The number of patches are not getting smaller. Except I arbitrarily
> merge them together. I am not planning to do that since I think it is
> not a good idea at all. And the patches have been reviewed by João Paulo
> Rechi Vita who worked with Gustavo on these changes.
It is your problem if you don't think there is any value to people
reviewing the stuff you're asking me to merge into the tree.
> So do you want to postpone this for 2.6.35 merge window?
I'll pull this stuff into net-next-2.6 after I give it a glance over
but you can't operate like this in the future.
Once you have about 10 commits ready in your tree, just push it to
me, don't delay.
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: David Miller @ 2010-05-10 11:20 UTC (permalink / raw)
To: marcel; +Cc: netdev
In-Reply-To: <cover.1273484094.git.marcel@holtmann.org>
Ok, I pulled this.
But patch #32 needs to be fixed. That TX window thing is, if
anything, a socket option not some obscure module load parameter.
Doing it with a module parameter means that you can't make it so that
only some sockets (or some network paths) use a certain TX window
value and other's not.
Another alternative is to, as implied, make it a route metric or
similar.
Anything but a module option is appropriate for this.
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: Marcel Holtmann @ 2010-05-10 11:26 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20100510.042031.135962157.davem@davemloft.net>
Hi Dave,
> Ok, I pulled this.
>
> But patch #32 needs to be fixed. That TX window thing is, if
> anything, a socket option not some obscure module load parameter.
>
> Doing it with a module parameter means that you can't make it so that
> only some sockets (or some network paths) use a certain TX window
> value and other's not.
>
> Another alternative is to, as implied, make it a route metric or
> similar.
>
> Anything but a module option is appropriate for this.
actually that was only a module option so we can easily test this at an
UnPlugFest. I think it can be removed all together now. We don't need it
anymore. I check with Gustavo.
Regards
Marcel
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: David Miller @ 2010-05-10 11:28 UTC (permalink / raw)
To: marcel; +Cc: netdev
In-Reply-To: <20100510.042031.135962157.davem@davemloft.net>
More problems.
In the future, don't fix things like you did in:
"Bluetooth: Fix issues where sk_sleep() helper is needed now"
That's something you take care of inside of the merge which causes the
build problems.
It's even trivial:
bash$ cd bluetooth-next-2.6
bash$ git pull .../net-next-2.6/.git
bash$ make
... build fails because sk_sleep() stuff ...
bash$ emacs ...
bash$ make
... build succeeds now ...
bash$ git commit --amend file1.c file2.c ...
and add some mention in the amended merge commit about what you did
to take care of the sk_sleep() stuff. That final commit command
will update the merge commit so that it has the build fix included
in it and therefore at any particular commit the tree does not fail
to build.
Otherwise you create a situation where the tree is not bisectable at
all, if someone bisects to the commit before the sk_sleep() fix the
tree won't build, and this makes bug hunting more painful than it
needs to be.
^ permalink raw reply
* Re: Pull request: bluetooth-next-2.6 2010-05-10
From: David Miller @ 2010-05-10 11:32 UTC (permalink / raw)
To: marcel; +Cc: netdev
In-Reply-To: <20100510.042829.93442711.davem@davemloft.net>
BT_L2CAP_EXT_FEATURES makes no sense at all...
If someone can rebuild their kernel, they can just as equally add
an entry to /etc/sysctl.conf to turn that thing on early in the
boot process.
It's not like you're going to get distributions to enable this kernel
config option by default to get "wider coverage" for testing this new
feature.
Please just toss this thing, and please don't post so much of this
kind of stuff in one go ever again, this way problems like this and
the other one's can be caught early, rather than my having to pick
apart several problematic changes in one huge pass. :-/
Thanks.
^ permalink raw reply
* Re: [PATCH 06/11] netdev: bfin_mac: avoid tx skb overflows in the tx DMA ring
From: David Miller @ 2010-05-10 11:40 UTC (permalink / raw)
To: vapier; +Cc: netdev, uclinux-dist-devel, sonic.zhang
In-Reply-To: <1273400337-26501-6-git-send-email-vapier@gentoo.org>
From: Mike Frysinger <vapier@gentoo.org>
Date: Sun, 9 May 2010 06:18:52 -0400
> From: Sonic Zhang <sonic.zhang@analog.com>
>
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This should never ever happen, it's a bug and you should print a warning
message when and if it does actually occur.
At any point where your ->next pointer hits tx_list_head, the queue
should have been stopped by your driver and therefore the networking
core will never pass another packet to you.
If this condition is actually triggering, it means you're not locking
properly or you have some race.
> ---
> drivers/net/bfin_mac.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
> index 6d69bbb..0b5ea01 100644
> --- a/drivers/net/bfin_mac.c
> +++ b/drivers/net/bfin_mac.c
> @@ -920,6 +920,9 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
> u32 data_align = (unsigned long)(skb->data) & 0x3;
> union skb_shared_tx *shtx = skb_tx(skb);
>
> + if (current_tx_ptr->next == tx_list_head)
> + return NETDEV_TX_BUSY;
> +
> current_tx_ptr->skb = skb;
>
> if (data_align == 0x2) {
> --
> 1.7.1
>
^ permalink raw reply
* Re: [PATCH 09/11] netdev: bfin_mac: only use hardware checksum in normal IPv4 mode
From: David Miller @ 2010-05-10 11:42 UTC (permalink / raw)
To: vapier; +Cc: netdev, uclinux-dist-devel, jon.kowal, sonic.zhang
In-Reply-To: <1273400337-26501-9-git-send-email-vapier@gentoo.org>
From: Mike Frysinger <vapier@gentoo.org>
Date: Sun, 9 May 2010 06:18:55 -0400
> From: Jon Kowal <jon.kowal@dspecialists.de>
>
> The Blackfin on-chip MAC checksum logic only works when the IP packet has
> a header length of 20 bytes. This is true for most IPv4 packets, but not
> for IPv6 packets or IPv4 packets which use header options. So only use
> the hardware checksum when appropriate.
>
> Signed-off-by: Jon Kowal <jon.kowal@dspecialists.de>
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
In order to make the tree bisectable, combine bug fixes into the changes
that add the bugs instead of letting them live in the final tree when
they don't need to.
You should have just combined this patch into the patch that added the
FCS inversion stuff.
You're going to need to respin and repost this entire patch set after
fixing all of these problems I've found.
Thanks.
^ permalink raw reply
* Re: [PATCH] X25: Replace BKL in sockopts calls
From: David Miller @ 2010-05-10 11:44 UTC (permalink / raw)
To: eric.dumazet; +Cc: andrew.hendry, netdev
In-Reply-To: <1273467040.2325.78.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 10 May 2010 06:50:40 +0200
> Well, its probably better than lock_kernel() ;)
>
> qbitincl is a char, I suspect some arches cant store a char in an atomic
> way ? Alpha comes to mind.
True.
> We now have lock_sock_bh()/unlock_sock_bh() for this kind of very short
> sections, where we cant sleep.
Another option is to simply use an atomic bitmask to represent these
booleans instead of a crufty set of chars.
^ permalink raw reply
* Re: [PATCH] IPv4: unresolved multicast route cleanup
From: David Miller @ 2010-05-10 11:48 UTC (permalink / raw)
To: andreas.meissner; +Cc: netdev
In-Reply-To: <4BE7CD4D.6050704@indakom.de>
From: Andreas Meissner <andreas.meissner@indakom.de>
Date: Mon, 10 May 2010 11:09:33 +0200
> from: Andreas Meissner <andreas.meissner@sphairon.com>
>
> Fixes the expiration timer for unresolved multicast route entries.
> In case new multicast routing requests come in faster than the
> expiration timeout occurs (e.g. zap through multicast TV streams), the
> timer is prevented from being called at time for already existing entries.
>
> Signed-off by: Andreas Meissner <andreas.meissner@sphairon.com>
> ---
> As the single timer is resetted to default whenever a new entry is made,
> the timeout for existing unresolved entires are missed and/or not
> updated. As a consequence new requests are denied when the limit of
> unresolved entries has been reached because old entries live longer than
> they are supposed to.
> The solution is to reset the timer only for the first unresolved entry
> in the multicast routing cache. All other timers are already set and
> updated correctly within the timer function itself by now.
Looks great, applied thanks!
^ permalink raw reply
* [PATCH] net: Fix FDDI and TR config checks in ipv4 arp and LLC.
From: David Miller @ 2010-05-10 11:59 UTC (permalink / raw)
To: netdev
Need to check both CONFIG_FOO and CONFIG_FOO_MODULE
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Committed to net-2.6
net/ipv4/arp.c | 6 +++---
net/llc/llc_sap.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 6e74706..80769f1 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -661,13 +661,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
#endif
#endif
-#ifdef CONFIG_FDDI
+#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
case ARPHRD_FDDI:
arp->ar_hrd = htons(ARPHRD_ETHER);
arp->ar_pro = htons(ETH_P_IP);
break;
#endif
-#ifdef CONFIG_TR
+#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
case ARPHRD_IEEE802_TR:
arp->ar_hrd = htons(ARPHRD_IEEE802);
arp->ar_pro = htons(ETH_P_IP);
@@ -1051,7 +1051,7 @@ static int arp_req_set(struct net *net, struct arpreq *r,
return -EINVAL;
}
switch (dev->type) {
-#ifdef CONFIG_FDDI
+#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
case ARPHRD_FDDI:
/*
* According to RFC 1390, FDDI devices should accept ARP
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index a432f0e..94e7fca 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -31,7 +31,7 @@ static int llc_mac_header_len(unsigned short devtype)
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
return sizeof(struct ethhdr);
-#ifdef CONFIG_TR
+#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
case ARPHRD_IEEE802_TR:
return sizeof(struct trh_hdr);
#endif
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox