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)
hci_uart_ldisc.receive_room= hci_uart_tty_room;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
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))) {
BT_ERR("HCI line discipline registration failed. (%d)", err);
......
......@@ -231,8 +231,10 @@ struct l2cap_pinfo {
struct sock *prev_c;
};
#define CONF_REQ_SENT 0x01
#define CONF_INPUT_DONE 0x02
#define CONF_OUTPUT_DONE 0x04
#define L2CAP_CONF_REQ_SENT 0x01
#define L2CAP_CONF_INPUT_DONE 0x02
#define L2CAP_CONF_OUTPUT_DONE 0x04
void l2cap_load(void);
#endif /* __L2CAP_H */
......@@ -185,10 +185,11 @@ struct rfcomm_dlc {
atomic_t refcnt;
u8 dlci;
u8 addr;
uint mtu;
u8 priority;
u8 v24_sig;
u8 mscex;
uint mtu;
uint credits;
uint rx_credits;
uint tx_credits;
......@@ -213,6 +214,11 @@ struct rfcomm_dlc {
#define RFCOMM_SCHED_TIMEO 3
#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 unsigned long rfcomm_event;
......
......@@ -92,6 +92,8 @@ int bt_sock_unregister(int proto)
static int bt_sock_create(struct socket *sock, int proto)
{
int err = 0;
if (proto >= BT_MAX_PROTO)
return -EINVAL;
......@@ -102,11 +104,12 @@ static int bt_sock_create(struct socket *sock, int proto)
request_module(module_name);
}
#endif
if (!bt_proto[proto])
return -ENOENT;
return bt_proto[proto]->create(sock, proto);
err = -EPROTONOSUPPORT;
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(sock, proto);
module_put(bt_proto[proto]->owner);
}
return err;
}
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)
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);
}
static void __bnep_unlink_session(struct bnep_session *s)
{
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)
......@@ -679,6 +682,8 @@ static int __init bnep_init_module(void)
{
char flt[50] = "";
l2cap_load();
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
strcat(flt, "protocol ");
#endif
......
......@@ -67,8 +67,6 @@ static int bnep_sock_release(struct socket *sock)
sock_orphan(sk);
sock_put(sk);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -179,13 +177,10 @@ static int bnep_sock_create(struct socket *sock, int protocol)
return -ENOMEM;
sock->ops = &bnep_sock_ops;
MOD_INC_USE_COUNT;
sock->state = SS_UNCONNECTED;
sk->destruct = NULL;
sk->protocol = protocol;
return 0;
}
......
......@@ -145,8 +145,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
conn->chan_list.lock = RW_LOCK_UNLOCKED;
BT_DBG("hcon %p conn %p", hcon, conn);
MOD_INC_USE_COUNT;
return conn;
}
......@@ -173,8 +171,6 @@ static int l2cap_conn_del(struct hci_conn *hcon, int err)
hcon->l2cap_data = NULL;
kfree(conn);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -242,8 +238,6 @@ static void l2cap_sock_destruct(struct sock *sk)
if (sk->protinfo)
kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
}
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)
if (!sk)
return NULL;
sk_set_owner(sk, THIS_MODULE);
sk->destruct = l2cap_sock_destruct;
sk->sndtimeo = L2CAP_CONN_TIMEOUT;
......@@ -365,8 +361,6 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
l2cap_sock_init_timer(sk);
bt_sock_link(&l2cap_sk_list, sk);
MOD_INC_USE_COUNT;
return sk;
}
......@@ -1319,15 +1313,18 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
{
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
u16 flags = 0;
BT_DBG("sk %p complete %d", sk, result ? 1 : 0);
if (result)
*result = l2cap_conf_output(sk, &ptr);
else
flags = 0x0001;
rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid);
rsp->result = __cpu_to_le16(result ? *result : 0);
rsp->flags = __cpu_to_le16(0);
rsp->flags = __cpu_to_le16(flags);
return ptr - data;
}
......@@ -1440,7 +1437,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
case L2CAP_CR_SUCCESS:
sk->state = BT_CONFIG;
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);
break;
......@@ -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));
if (flags & 0x01) {
if (flags & 0x0001) {
/* Incomplete config. Send empty response. */
l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp);
goto unlock;
......@@ -1488,12 +1485,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto unlock;
/* 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;
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];
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
goto 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;
l2cap_chan_ready(sk);
}
......@@ -1943,21 +1940,27 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
}
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;
}
hdr = (struct l2cap_hdr *) skb->data;
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) {
/* Complete frame received */
l2cap_recv_frame(conn, skb);
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) */
if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC)))
goto drop;
......@@ -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) {
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);
kfree_skb(conn->rx_skb);
conn->rx_skb = NULL;
......@@ -2134,7 +2137,6 @@ int __init l2cap_init(void)
return err;
}
l2cap_proc_init();
BT_INFO("L2CAP ver %s", VERSION);
......@@ -2155,6 +2157,15 @@ void __exit l2cap_cleanup(void)
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_exit(l2cap_cleanup);
......
......@@ -52,7 +52,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#define VERSION "0.3"
#define VERSION "1.0"
#ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG
......@@ -203,6 +203,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
d->state = BT_OPEN;
d->flags = 0;
d->mscex = 0;
d->mtu = RFCOMM_DEFAULT_MTU;
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,
d->dlci = dlci;
d->addr = __addr(s->initiator, dlci);
d->priority = 7;
d->state = BT_CONFIG;
rfcomm_dlc_link(s, d);
......@@ -481,9 +483,12 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
list_add(&s->list, &session_list);
/* 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)
MOD_INC_USE_COUNT;
__module_get(THIS_MODULE);
return s;
}
......@@ -502,7 +507,7 @@ void rfcomm_session_del(struct rfcomm_session *s)
kfree(s);
if (state != BT_LISTEN)
MOD_DEC_USE_COUNT;
module_put(THIS_MODULE);
}
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
pn = (void *) ptr; ptr += sizeof(*pn);
pn->dlci = d->dlci;
pn->priority = 0;
pn->priority = d->priority;
pn->ack_timer = 0;
pn->max_retrans = 0;
......@@ -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);
d->credits = 0;
}
d->mtu = btohs(pn->mtu);
} else {
if (pn->flow_ctrl == 0xe0) {
d->tx_credits = pn->credits;
......@@ -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);
d->credits = 0;
}
}
d->priority = pn->priority;
d->mtu = btohs(pn->mtu);
}
return 0;
}
......@@ -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->flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
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;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
if (rpn->xon_char != RFCOMM_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;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
if (rpn->xoff_char != RFCOMM_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;
}
}
......@@ -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);
if (!cr)
d = rfcomm_dlc_get(s, dlci);
if (!d)
return 0;
d = rfcomm_dlc_get(s, dlci);
if (d) {
if (cr) {
if (msc->v24_sig & RFCOMM_V24_FC && !d->credits)
set_bit(RFCOMM_TX_THROTTLED, &d->flags);
else
......@@ -1300,7 +1305,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
rfcomm_dlc_unlock(d);
rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
}
d->mscex |= RFCOMM_MSCEX_RX;
} else
d->mscex |= RFCOMM_MSCEX_TX;
return 0;
}
......@@ -1524,7 +1533,8 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
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);
}
}
......@@ -1869,6 +1879,8 @@ static void __exit rfcomm_proc_cleanup(void)
/* ---- Initialization ---- */
int __init rfcomm_init(void)
{
l2cap_load();
kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
BT_INFO("RFCOMM ver %s", VERSION);
......
......@@ -182,8 +182,6 @@ static void rfcomm_sock_destruct(struct sock *sk)
if (sk->protinfo)
kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
}
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)
if (!sk)
return NULL;
sk_set_owner(sk, THIS_MODULE);
d = rfcomm_dlc_alloc(prio);
if (!d) {
sk_free(sk);
......@@ -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_DBG("sk %p", sk);
MOD_INC_USE_COUNT;
return sk;
}
......
......@@ -99,7 +99,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
rfcomm_dlc_put(dlc);
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)
......@@ -211,8 +213,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->dlc = 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:
write_unlock_bh(&rfcomm_dev_lock);
......
......@@ -145,8 +145,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status)
conn->mtu = 60;
BT_DBG("hcon %p conn %p", hcon, conn);
MOD_INC_USE_COUNT;
return conn;
}
......@@ -180,8 +178,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
hcon->sco_data = NULL;
kfree(conn);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -347,8 +343,6 @@ static void sco_sock_destruct(struct sock *sk)
if (sk->protinfo)
kfree(sk->protinfo);
MOD_DEC_USE_COUNT;
}
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)
if (!sk)
return NULL;
sk_set_owner(sk, THIS_MODULE);
sk->destruct = sco_sock_destruct;
sk->sndtimeo = SCO_CONN_TIMEOUT;
sk->state = BT_OPEN;
......@@ -441,8 +437,6 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
sco_sock_init_timer(sk);
bt_sock_link(&sco_sk_list, sk);
MOD_INC_USE_COUNT;
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