Commit b1c8ea3c authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

Merge bk://linux.bkbits.net/linux-2.5

into qualcomm.com:/home/kernel/bt-2.5
parents d0682bc8 1a6fe614
...@@ -535,6 +535,7 @@ int __init hci_uart_init(void) ...@@ -535,6 +535,7 @@ int __init hci_uart_init(void)
hci_uart_ldisc.receive_room= hci_uart_tty_room; hci_uart_ldisc.receive_room= hci_uart_tty_room;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive; hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
hci_uart_ldisc.owner = THIS_MODULE;
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
BT_ERR("HCI line discipline registration failed. (%d)", err); BT_ERR("HCI line discipline registration failed. (%d)", err);
......
...@@ -231,8 +231,10 @@ struct l2cap_pinfo { ...@@ -231,8 +231,10 @@ struct l2cap_pinfo {
struct sock *prev_c; struct sock *prev_c;
}; };
#define CONF_REQ_SENT 0x01 #define L2CAP_CONF_REQ_SENT 0x01
#define CONF_INPUT_DONE 0x02 #define L2CAP_CONF_INPUT_DONE 0x02
#define CONF_OUTPUT_DONE 0x04 #define L2CAP_CONF_OUTPUT_DONE 0x04
void l2cap_load(void);
#endif /* __L2CAP_H */ #endif /* __L2CAP_H */
...@@ -185,10 +185,11 @@ struct rfcomm_dlc { ...@@ -185,10 +185,11 @@ struct rfcomm_dlc {
atomic_t refcnt; atomic_t refcnt;
u8 dlci; u8 dlci;
u8 addr; u8 addr;
u8 priority;
uint mtu;
u8 v24_sig; u8 v24_sig;
u8 mscex;
uint mtu;
uint credits; uint credits;
uint rx_credits; uint rx_credits;
uint tx_credits; uint tx_credits;
...@@ -213,6 +214,11 @@ struct rfcomm_dlc { ...@@ -213,6 +214,11 @@ struct rfcomm_dlc {
#define RFCOMM_SCHED_TIMEO 3 #define RFCOMM_SCHED_TIMEO 3
#define RFCOMM_SCHED_WAKEUP 31 #define RFCOMM_SCHED_WAKEUP 31
/* MSC exchange flags */
#define RFCOMM_MSCEX_TX 1
#define RFCOMM_MSCEX_RX 2
#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX)
extern struct task_struct *rfcomm_thread; extern struct task_struct *rfcomm_thread;
extern unsigned long rfcomm_event; extern unsigned long rfcomm_event;
......
...@@ -92,6 +92,8 @@ int bt_sock_unregister(int proto) ...@@ -92,6 +92,8 @@ int bt_sock_unregister(int proto)
static int bt_sock_create(struct socket *sock, int proto) static int bt_sock_create(struct socket *sock, int proto)
{ {
int err = 0;
if (proto >= BT_MAX_PROTO) if (proto >= BT_MAX_PROTO)
return -EINVAL; return -EINVAL;
...@@ -102,11 +104,12 @@ static int bt_sock_create(struct socket *sock, int proto) ...@@ -102,11 +104,12 @@ static int bt_sock_create(struct socket *sock, int proto)
request_module(module_name); request_module(module_name);
} }
#endif #endif
err = -EPROTONOSUPPORT;
if (!bt_proto[proto]) if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
return -ENOENT; err = bt_proto[proto]->create(sock, proto);
module_put(bt_proto[proto]->owner);
return bt_proto[proto]->create(sock, proto); }
return err;
} }
struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio) struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio)
......
...@@ -85,14 +85,17 @@ static struct bnep_session *__bnep_get_session(u8 *dst) ...@@ -85,14 +85,17 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
static void __bnep_link_session(struct bnep_session *s) static void __bnep_link_session(struct bnep_session *s)
{ {
MOD_INC_USE_COUNT; /* It's safe to call __module_get() here because sessions are added
by the socket layer which has to hold the refference to this module.
*/
__module_get(THIS_MODULE);
list_add(&s->list, &bnep_session_list); list_add(&s->list, &bnep_session_list);
} }
static void __bnep_unlink_session(struct bnep_session *s) static void __bnep_unlink_session(struct bnep_session *s)
{ {
list_del(&s->list); list_del(&s->list);
MOD_DEC_USE_COUNT; module_put(THIS_MODULE);
} }
static int bnep_send(struct bnep_session *s, void *data, size_t len) static int bnep_send(struct bnep_session *s, void *data, size_t len)
...@@ -679,6 +682,8 @@ static int __init bnep_init_module(void) ...@@ -679,6 +682,8 @@ static int __init bnep_init_module(void)
{ {
char flt[50] = ""; char flt[50] = "";
l2cap_load();
#ifdef CONFIG_BT_BNEP_PROTO_FILTER #ifdef CONFIG_BT_BNEP_PROTO_FILTER
strcat(flt, "protocol "); strcat(flt, "protocol ");
#endif #endif
......
...@@ -67,8 +67,6 @@ static int bnep_sock_release(struct socket *sock) ...@@ -67,8 +67,6 @@ static int bnep_sock_release(struct socket *sock)
sock_orphan(sk); sock_orphan(sk);
sock_put(sk); sock_put(sk);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -179,13 +177,10 @@ static int bnep_sock_create(struct socket *sock, int protocol) ...@@ -179,13 +177,10 @@ static int bnep_sock_create(struct socket *sock, int protocol)
return -ENOMEM; return -ENOMEM;
sock->ops = &bnep_sock_ops; sock->ops = &bnep_sock_ops;
MOD_INC_USE_COUNT;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
sk->destruct = NULL; sk->destruct = NULL;
sk->protocol = protocol; sk->protocol = protocol;
return 0; return 0;
} }
......
...@@ -145,8 +145,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) ...@@ -145,8 +145,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
conn->chan_list.lock = RW_LOCK_UNLOCKED; conn->chan_list.lock = RW_LOCK_UNLOCKED;
BT_DBG("hcon %p conn %p", hcon, conn); BT_DBG("hcon %p conn %p", hcon, conn);
MOD_INC_USE_COUNT;
return conn; return conn;
} }
...@@ -173,8 +171,6 @@ static int l2cap_conn_del(struct hci_conn *hcon, int err) ...@@ -173,8 +171,6 @@ static int l2cap_conn_del(struct hci_conn *hcon, int err)
hcon->l2cap_data = NULL; hcon->l2cap_data = NULL;
kfree(conn); kfree(conn);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -242,8 +238,6 @@ static void l2cap_sock_destruct(struct sock *sk) ...@@ -242,8 +238,6 @@ static void l2cap_sock_destruct(struct sock *sk)
if (sk->protinfo) if (sk->protinfo)
kfree(sk->protinfo); kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
} }
static void l2cap_sock_cleanup_listen(struct sock *parent) static void l2cap_sock_cleanup_listen(struct sock *parent)
...@@ -356,6 +350,8 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -356,6 +350,8 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
if (!sk) if (!sk)
return NULL; return NULL;
sk_set_owner(sk, THIS_MODULE);
sk->destruct = l2cap_sock_destruct; sk->destruct = l2cap_sock_destruct;
sk->sndtimeo = L2CAP_CONN_TIMEOUT; sk->sndtimeo = L2CAP_CONN_TIMEOUT;
...@@ -365,8 +361,6 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -365,8 +361,6 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
l2cap_sock_init_timer(sk); l2cap_sock_init_timer(sk);
bt_sock_link(&l2cap_sk_list, sk); bt_sock_link(&l2cap_sk_list, sk);
MOD_INC_USE_COUNT;
return sk; return sk;
} }
...@@ -1319,15 +1313,18 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result) ...@@ -1319,15 +1313,18 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
{ {
struct l2cap_conf_rsp *rsp = data; struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data; void *ptr = rsp->data;
u16 flags = 0;
BT_DBG("sk %p complete %d", sk, result ? 1 : 0); BT_DBG("sk %p complete %d", sk, result ? 1 : 0);
if (result) if (result)
*result = l2cap_conf_output(sk, &ptr); *result = l2cap_conf_output(sk, &ptr);
else
flags = 0x0001;
rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid); rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid);
rsp->result = __cpu_to_le16(result ? *result : 0); rsp->result = __cpu_to_le16(result ? *result : 0);
rsp->flags = __cpu_to_le16(0); rsp->flags = __cpu_to_le16(flags);
return ptr - data; return ptr - data;
} }
...@@ -1440,7 +1437,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -1440,7 +1437,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
case L2CAP_CR_SUCCESS: case L2CAP_CR_SUCCESS:
sk->state = BT_CONFIG; sk->state = BT_CONFIG;
l2cap_pi(sk)->dcid = dcid; l2cap_pi(sk)->dcid = dcid;
l2cap_pi(sk)->conf_state |= CONF_REQ_SENT; l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req);
break; break;
...@@ -1475,7 +1472,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -1475,7 +1472,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req)); l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
if (flags & 0x01) { if (flags & 0x0001) {
/* Incomplete config. Send empty response. */ /* Incomplete config. Send empty response. */
l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp); l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp);
goto unlock; goto unlock;
...@@ -1488,12 +1485,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -1488,12 +1485,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto unlock; goto unlock;
/* Output config done */ /* Output config done */
l2cap_pi(sk)->conf_state |= CONF_OUTPUT_DONE; l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE;
if (l2cap_pi(sk)->conf_state & CONF_INPUT_DONE) { if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
sk->state = BT_CONNECTED; sk->state = BT_CONNECTED;
l2cap_chan_ready(sk); l2cap_chan_ready(sk);
} else if (!(l2cap_pi(sk)->conf_state & CONF_REQ_SENT)) { } else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
u8 req[64]; u8 req[64];
l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req);
} }
...@@ -1538,9 +1535,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -1538,9 +1535,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto done; goto done;
/* Input config done */ /* Input config done */
l2cap_pi(sk)->conf_state |= CONF_INPUT_DONE; l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
if (l2cap_pi(sk)->conf_state & CONF_OUTPUT_DONE) { if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
sk->state = BT_CONNECTED; sk->state = BT_CONNECTED;
l2cap_chan_ready(sk); l2cap_chan_ready(sk);
} }
...@@ -1943,21 +1940,27 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -1943,21 +1940,27 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
} }
if (skb->len < 2) { if (skb->len < 2) {
BT_ERR("Frame is too small (len %d)", skb->len); BT_ERR("Frame is too short (len %d)", skb->len);
goto drop; goto drop;
} }
hdr = (struct l2cap_hdr *) skb->data; hdr = (struct l2cap_hdr *) skb->data;
len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
BT_DBG("Start: total len %d, frag len %d", len, skb->len);
if (len == skb->len) { if (len == skb->len) {
/* Complete frame received */ /* Complete frame received */
l2cap_recv_frame(conn, skb); l2cap_recv_frame(conn, skb);
return 0; return 0;
} }
BT_DBG("Start: total len %d, frag len %d", len, skb->len);
if (skb->len > len) {
BT_ERR("Frame is too long (len %d, expected len %d)",
skb->len, len);
goto drop;
}
/* Allocate skb for the complete frame (with header) */ /* Allocate skb for the complete frame (with header) */
if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC))) if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC)))
goto drop; goto drop;
...@@ -1973,7 +1976,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -1973,7 +1976,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
} }
if (skb->len > conn->rx_len) { if (skb->len > conn->rx_len) {
BT_ERR("Fragment is too large (len %d, expect %d)", BT_ERR("Fragment is too long (len %d, expected %d)",
skb->len, conn->rx_len); skb->len, conn->rx_len);
kfree_skb(conn->rx_skb); kfree_skb(conn->rx_skb);
conn->rx_skb = NULL; conn->rx_skb = NULL;
...@@ -2134,7 +2137,6 @@ int __init l2cap_init(void) ...@@ -2134,7 +2137,6 @@ int __init l2cap_init(void)
return err; return err;
} }
l2cap_proc_init(); l2cap_proc_init();
BT_INFO("L2CAP ver %s", VERSION); BT_INFO("L2CAP ver %s", VERSION);
...@@ -2155,6 +2157,15 @@ void __exit l2cap_cleanup(void) ...@@ -2155,6 +2157,15 @@ void __exit l2cap_cleanup(void)
BT_ERR("L2CAP protocol unregistration failed"); BT_ERR("L2CAP protocol unregistration failed");
} }
void l2cap_load(void)
{
/* Dummy function to trigger automatic L2CAP module loading by
other modules that use L2CAP sockets but don not use any other
symbols from it. */
return;
}
EXPORT_SYMBOL(l2cap_load);
module_init(l2cap_init); module_init(l2cap_init);
module_exit(l2cap_cleanup); module_exit(l2cap_cleanup);
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#include <net/bluetooth/l2cap.h> #include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h> #include <net/bluetooth/rfcomm.h>
#define VERSION "0.3" #define VERSION "1.0"
#ifndef CONFIG_BT_RFCOMM_DEBUG #ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG #undef BT_DBG
...@@ -203,6 +203,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d) ...@@ -203,6 +203,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
d->state = BT_OPEN; d->state = BT_OPEN;
d->flags = 0; d->flags = 0;
d->mscex = 0;
d->mtu = RFCOMM_DEFAULT_MTU; d->mtu = RFCOMM_DEFAULT_MTU;
d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV; d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
...@@ -306,6 +307,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, ...@@ -306,6 +307,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d->dlci = dlci; d->dlci = dlci;
d->addr = __addr(s->initiator, dlci); d->addr = __addr(s->initiator, dlci);
d->priority = 7;
d->state = BT_CONFIG; d->state = BT_CONFIG;
rfcomm_dlc_link(s, d); rfcomm_dlc_link(s, d);
...@@ -481,9 +483,12 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state) ...@@ -481,9 +483,12 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
list_add(&s->list, &session_list); list_add(&s->list, &session_list);
/* Do not increment module usage count for listeting sessions. /* Do not increment module usage count for listeting sessions.
* Otherwise we won't be able to unload the module. */ * Otherwise we won't be able to unload the module.
* Non listening session are added either by a socket or a TTYs
* which means that we already hold refcount to this module.
*/
if (state != BT_LISTEN) if (state != BT_LISTEN)
MOD_INC_USE_COUNT; __module_get(THIS_MODULE);
return s; return s;
} }
...@@ -502,7 +507,7 @@ void rfcomm_session_del(struct rfcomm_session *s) ...@@ -502,7 +507,7 @@ void rfcomm_session_del(struct rfcomm_session *s)
kfree(s); kfree(s);
if (state != BT_LISTEN) if (state != BT_LISTEN)
MOD_DEC_USE_COUNT; module_put(THIS_MODULE);
} }
struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
...@@ -741,7 +746,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d ...@@ -741,7 +746,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
pn = (void *) ptr; ptr += sizeof(*pn); pn = (void *) ptr; ptr += sizeof(*pn);
pn->dlci = d->dlci; pn->dlci = d->dlci;
pn->priority = 0; pn->priority = d->priority;
pn->ack_timer = 0; pn->ack_timer = 0;
pn->max_retrans = 0; pn->max_retrans = 0;
...@@ -1099,8 +1104,6 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) ...@@ -1099,8 +1104,6 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
set_bit(RFCOMM_TX_THROTTLED, &d->flags); set_bit(RFCOMM_TX_THROTTLED, &d->flags);
d->credits = 0; d->credits = 0;
} }
d->mtu = btohs(pn->mtu);
} else { } else {
if (pn->flow_ctrl == 0xe0) { if (pn->flow_ctrl == 0xe0) {
d->tx_credits = pn->credits; d->tx_credits = pn->credits;
...@@ -1108,9 +1111,11 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) ...@@ -1108,9 +1111,11 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
set_bit(RFCOMM_TX_THROTTLED, &d->flags); set_bit(RFCOMM_TX_THROTTLED, &d->flags);
d->credits = 0; d->credits = 0;
} }
}
d->priority = pn->priority;
d->mtu = btohs(pn->mtu); d->mtu = btohs(pn->mtu);
}
return 0; return 0;
} }
...@@ -1229,21 +1234,21 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1229,21 +1234,21 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) { if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl); BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl);
rpn->flow_ctrl = RFCOMM_RPN_FLOW_NONE; flow_ctrl = RFCOMM_RPN_FLOW_NONE;
rpn_mask ^= RFCOMM_RPN_PM_FLOW; rpn_mask ^= RFCOMM_RPN_PM_FLOW;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XON) { if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) { if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char); BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char);
rpn->xon_char = RFCOMM_RPN_XON_CHAR; xon_char = RFCOMM_RPN_XON_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XON; rpn_mask ^= RFCOMM_RPN_PM_XON;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) { if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char); BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char);
rpn->xoff_char = RFCOMM_RPN_XOFF_CHAR; xoff_char = RFCOMM_RPN_XOFF_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XOFF; rpn_mask ^= RFCOMM_RPN_PM_XOFF;
} }
} }
...@@ -1284,11 +1289,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1284,11 +1289,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
if (!cr) d = rfcomm_dlc_get(s, dlci);
if (!d)
return 0; return 0;
d = rfcomm_dlc_get(s, dlci); if (cr) {
if (d) {
if (msc->v24_sig & RFCOMM_V24_FC && !d->credits) if (msc->v24_sig & RFCOMM_V24_FC && !d->credits)
set_bit(RFCOMM_TX_THROTTLED, &d->flags); set_bit(RFCOMM_TX_THROTTLED, &d->flags);
else else
...@@ -1300,7 +1305,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1300,7 +1305,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
rfcomm_dlc_unlock(d); rfcomm_dlc_unlock(d);
rfcomm_send_msc(s, 0, dlci, msc->v24_sig); rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
}
d->mscex |= RFCOMM_MSCEX_RX;
} else
d->mscex |= RFCOMM_MSCEX_TX;
return 0; return 0;
} }
...@@ -1524,7 +1533,8 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) ...@@ -1524,7 +1533,8 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue; continue;
} }
if (d->state == BT_CONNECTED || d->state == BT_DISCONN) if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
d->mscex == RFCOMM_MSCEX_OK)
rfcomm_process_tx(d); rfcomm_process_tx(d);
} }
} }
...@@ -1869,6 +1879,8 @@ static void __exit rfcomm_proc_cleanup(void) ...@@ -1869,6 +1879,8 @@ static void __exit rfcomm_proc_cleanup(void)
/* ---- Initialization ---- */ /* ---- Initialization ---- */
int __init rfcomm_init(void) int __init rfcomm_init(void)
{ {
l2cap_load();
kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
BT_INFO("RFCOMM ver %s", VERSION); BT_INFO("RFCOMM ver %s", VERSION);
......
...@@ -182,8 +182,6 @@ static void rfcomm_sock_destruct(struct sock *sk) ...@@ -182,8 +182,6 @@ static void rfcomm_sock_destruct(struct sock *sk)
if (sk->protinfo) if (sk->protinfo)
kfree(sk->protinfo); kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
} }
static void rfcomm_sock_cleanup_listen(struct sock *parent) static void rfcomm_sock_cleanup_listen(struct sock *parent)
...@@ -265,6 +263,8 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -265,6 +263,8 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
if (!sk) if (!sk)
return NULL; return NULL;
sk_set_owner(sk, THIS_MODULE);
d = rfcomm_dlc_alloc(prio); d = rfcomm_dlc_alloc(prio);
if (!d) { if (!d) {
sk_free(sk); sk_free(sk);
...@@ -288,8 +288,6 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -288,8 +288,6 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
bt_sock_link(&rfcomm_sk_list, sk); bt_sock_link(&rfcomm_sk_list, sk);
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
MOD_INC_USE_COUNT;
return sk; return sk;
} }
......
...@@ -99,7 +99,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) ...@@ -99,7 +99,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
rfcomm_dlc_put(dlc); rfcomm_dlc_put(dlc);
kfree(dev); kfree(dev);
MOD_DEC_USE_COUNT; /* It's safe to call module_put() here because socket still
holds refference to this module. */
module_put(THIS_MODULE);
} }
static inline void rfcomm_dev_hold(struct rfcomm_dev *dev) static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
...@@ -211,8 +213,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) ...@@ -211,8 +213,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->dlc = dlc; dev->dlc = dlc;
rfcomm_dlc_unlock(dlc); rfcomm_dlc_unlock(dlc);
MOD_INC_USE_COUNT; /* It's safe to call __module_get() here because socket already
holds refference to this module. */
__module_get(THIS_MODULE);
out: out:
write_unlock_bh(&rfcomm_dev_lock); write_unlock_bh(&rfcomm_dev_lock);
......
...@@ -145,8 +145,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status) ...@@ -145,8 +145,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status)
conn->mtu = 60; conn->mtu = 60;
BT_DBG("hcon %p conn %p", hcon, conn); BT_DBG("hcon %p conn %p", hcon, conn);
MOD_INC_USE_COUNT;
return conn; return conn;
} }
...@@ -180,8 +178,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err) ...@@ -180,8 +178,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
hcon->sco_data = NULL; hcon->sco_data = NULL;
kfree(conn); kfree(conn);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -347,8 +343,6 @@ static void sco_sock_destruct(struct sock *sk) ...@@ -347,8 +343,6 @@ static void sco_sock_destruct(struct sock *sk)
if (sk->protinfo) if (sk->protinfo)
kfree(sk->protinfo); kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
} }
static void sco_sock_cleanup_listen(struct sock *parent) static void sco_sock_cleanup_listen(struct sock *parent)
...@@ -434,6 +428,8 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -434,6 +428,8 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
if (!sk) if (!sk)
return NULL; return NULL;
sk_set_owner(sk, THIS_MODULE);
sk->destruct = sco_sock_destruct; sk->destruct = sco_sock_destruct;
sk->sndtimeo = SCO_CONN_TIMEOUT; sk->sndtimeo = SCO_CONN_TIMEOUT;
sk->state = BT_OPEN; sk->state = BT_OPEN;
...@@ -441,8 +437,6 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio) ...@@ -441,8 +437,6 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
sco_sock_init_timer(sk); sco_sock_init_timer(sk);
bt_sock_link(&sco_sk_list, sk); bt_sock_link(&sco_sk_list, sk);
MOD_INC_USE_COUNT;
return sk; return sk;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment