You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
@@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
.helper = "sd8688_helper.bin",
|
||||
.firmware = "sd8688.bin",
|
||||
.helper = "mrvl/sd8688_helper.bin",
|
||||
.firmware = "mrvl/sd8688.bin",
|
||||
.reg = &btmrvl_reg_8688,
|
||||
.sd_blksz_fw_dl = 64,
|
||||
};
|
||||
@@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
||||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
||||
|
||||
@@ -232,7 +232,7 @@ struct bt_sock_list {
|
||||
};
|
||||
|
||||
int bt_sock_register(int proto, const struct net_proto_family *ops);
|
||||
int bt_sock_unregister(int proto);
|
||||
void bt_sock_unregister(int proto);
|
||||
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
|
||||
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
|
||||
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
@@ -260,12 +260,22 @@ struct l2cap_ctrl {
|
||||
__u8 retries;
|
||||
};
|
||||
|
||||
struct hci_dev;
|
||||
|
||||
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
|
||||
|
||||
struct hci_req_ctrl {
|
||||
bool start;
|
||||
hci_req_complete_t complete;
|
||||
};
|
||||
|
||||
struct bt_skb_cb {
|
||||
__u8 pkt_type;
|
||||
__u8 incoming;
|
||||
__u16 expect;
|
||||
__u8 force_active;
|
||||
struct l2cap_ctrl control;
|
||||
struct hci_req_ctrl req;
|
||||
};
|
||||
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
|
||||
|
||||
|
||||
@@ -119,10 +119,16 @@ enum {
|
||||
HCI_CONNECTABLE,
|
||||
HCI_DISCOVERABLE,
|
||||
HCI_LINK_SECURITY,
|
||||
HCI_PENDING_CLASS,
|
||||
HCI_PERIODIC_INQ,
|
||||
HCI_FAST_CONNECTABLE,
|
||||
};
|
||||
|
||||
/* A mask for the flags that are supposed to remain when a reset happens
|
||||
* or the HCI device is closed.
|
||||
*/
|
||||
#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
|
||||
BIT(HCI_FAST_CONNECTABLE))
|
||||
|
||||
/* HCI ioctl defines */
|
||||
#define HCIDEVUP _IOW('H', 201, int)
|
||||
#define HCIDEVDOWN _IOW('H', 202, int)
|
||||
@@ -881,12 +887,25 @@ struct hci_rp_read_data_block_size {
|
||||
__le16 num_blocks;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b
|
||||
struct hci_rp_read_page_scan_activity {
|
||||
__u8 status;
|
||||
__le16 interval;
|
||||
__le16 window;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
|
||||
struct hci_cp_write_page_scan_activity {
|
||||
__le16 interval;
|
||||
__le16 window;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46
|
||||
struct hci_rp_read_page_scan_type {
|
||||
__u8 status;
|
||||
__u8 type;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
|
||||
#define PAGE_SCAN_TYPE_STANDARD 0x00
|
||||
#define PAGE_SCAN_TYPE_INTERLACED 0x01
|
||||
|
||||
@@ -165,6 +165,10 @@ struct hci_dev {
|
||||
__u16 voice_setting;
|
||||
__u8 io_capability;
|
||||
__s8 inq_tx_power;
|
||||
__u16 page_scan_interval;
|
||||
__u16 page_scan_window;
|
||||
__u8 page_scan_type;
|
||||
|
||||
__u16 devid_source;
|
||||
__u16 devid_vendor;
|
||||
__u16 devid_product;
|
||||
@@ -248,8 +252,6 @@ struct hci_dev {
|
||||
__u32 req_status;
|
||||
__u32 req_result;
|
||||
|
||||
__u16 init_last_cmd;
|
||||
|
||||
struct list_head mgmt_pending;
|
||||
|
||||
struct discovery_state discovery;
|
||||
@@ -574,7 +576,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
|
||||
void hci_disconnect(struct hci_conn *conn, __u8 reason);
|
||||
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
|
||||
void hci_sco_setup(struct hci_conn *conn, __u8 status);
|
||||
|
||||
@@ -742,8 +744,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
|
||||
u8 *randomizer);
|
||||
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
|
||||
int hci_update_ad(struct hci_dev *hdev);
|
||||
|
||||
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
|
||||
int hci_recv_frame(struct sk_buff *skb);
|
||||
@@ -1041,6 +1041,22 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
|
||||
int hci_register_cb(struct hci_cb *hcb);
|
||||
int hci_unregister_cb(struct hci_cb *hcb);
|
||||
|
||||
struct hci_request {
|
||||
struct hci_dev *hdev;
|
||||
struct sk_buff_head cmd_q;
|
||||
|
||||
/* If something goes wrong when building the HCI request, the error
|
||||
* value is stored in this field.
|
||||
*/
|
||||
int err;
|
||||
};
|
||||
|
||||
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
|
||||
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
|
||||
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
|
||||
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
|
||||
void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status);
|
||||
|
||||
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
|
||||
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
|
||||
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
|
||||
@@ -1153,7 +1169,7 @@ struct hci_sec_filter {
|
||||
#define hci_req_lock(d) mutex_lock(&d->req_lock)
|
||||
#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
|
||||
|
||||
void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
|
||||
void hci_update_ad(struct hci_request *req);
|
||||
|
||||
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
|
||||
u16 latency, u16 to_multiplier);
|
||||
|
||||
@@ -158,7 +158,6 @@ struct rfcomm_session {
|
||||
struct timer_list timer;
|
||||
unsigned long state;
|
||||
unsigned long flags;
|
||||
atomic_t refcnt;
|
||||
int initiator;
|
||||
|
||||
/* Default DLC parameters */
|
||||
@@ -276,11 +275,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
|
||||
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
|
||||
bdaddr_t *dst);
|
||||
|
||||
static inline void rfcomm_session_hold(struct rfcomm_session *s)
|
||||
{
|
||||
atomic_inc(&s->refcnt);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM sockets ---- */
|
||||
struct sockaddr_rc {
|
||||
sa_family_t rc_family;
|
||||
|
||||
@@ -397,13 +397,12 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
if (ctrl) {
|
||||
u8 *assoc;
|
||||
|
||||
assoc = kzalloc(assoc_len, GFP_KERNEL);
|
||||
assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL);
|
||||
if (!assoc) {
|
||||
amp_ctrl_put(ctrl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(assoc, rsp->amp_assoc, assoc_len);
|
||||
ctrl->assoc = assoc;
|
||||
ctrl->assoc_len = assoc_len;
|
||||
ctrl->assoc_rem_len = assoc_len;
|
||||
@@ -472,13 +471,12 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||
size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
|
||||
u8 *assoc;
|
||||
|
||||
assoc = kzalloc(assoc_len, GFP_KERNEL);
|
||||
assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL);
|
||||
if (!assoc) {
|
||||
amp_ctrl_put(ctrl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(assoc, req->amp_assoc, assoc_len);
|
||||
ctrl->assoc = assoc;
|
||||
ctrl->assoc_len = assoc_len;
|
||||
ctrl->assoc_rem_len = assoc_len;
|
||||
|
||||
@@ -92,23 +92,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops)
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_register);
|
||||
|
||||
int bt_sock_unregister(int proto)
|
||||
void bt_sock_unregister(int proto)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (proto < 0 || proto >= BT_MAX_PROTO)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
write_lock(&bt_proto_lock);
|
||||
|
||||
if (!bt_proto[proto])
|
||||
err = -ENOENT;
|
||||
else
|
||||
bt_proto[proto] = NULL;
|
||||
|
||||
bt_proto[proto] = NULL;
|
||||
write_unlock(&bt_proto_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_unregister);
|
||||
|
||||
|
||||
@@ -253,8 +253,6 @@ error:
|
||||
void __exit bnep_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "bnep");
|
||||
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
|
||||
BT_ERR("Can't unregister BNEP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_BNEP);
|
||||
proto_unregister(&bnep_proto);
|
||||
}
|
||||
|
||||
@@ -264,8 +264,6 @@ error:
|
||||
void cmtp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "cmtp");
|
||||
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
|
||||
BT_ERR("Can't unregister CMTP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_CMTP);
|
||||
proto_unregister(&cmtp_proto);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn)
|
||||
hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
|
||||
void hci_disconnect(struct hci_conn *conn, __u8 reason)
|
||||
{
|
||||
struct hci_cp_disconnect cp;
|
||||
|
||||
@@ -253,7 +253,7 @@ static void hci_conn_disconnect(struct hci_conn *conn)
|
||||
hci_amp_disconn(conn, reason);
|
||||
break;
|
||||
default:
|
||||
hci_acl_disconn(conn, reason);
|
||||
hci_disconnect(conn, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+601
-126
File diff suppressed because it is too large
Load Diff
+101
-506
File diff suppressed because it is too large
Load Diff
@@ -854,6 +854,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
skb_queue_tail(&hdev->raw_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
} else {
|
||||
/* Stand-alone HCI commands must be flaged as
|
||||
* single-command requests.
|
||||
*/
|
||||
bt_cb(skb)->req.start = true;
|
||||
|
||||
skb_queue_tail(&hdev->cmd_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->cmd_work);
|
||||
}
|
||||
@@ -1121,8 +1126,6 @@ error:
|
||||
void hci_sock_cleanup(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hci");
|
||||
if (bt_sock_unregister(BTPROTO_HCI) < 0)
|
||||
BT_ERR("HCI socket unregistration failed");
|
||||
|
||||
bt_sock_unregister(BTPROTO_HCI);
|
||||
proto_unregister(&hci_sk_proto);
|
||||
}
|
||||
|
||||
@@ -590,10 +590,8 @@ int __init bt_sysfs_init(void)
|
||||
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
|
||||
|
||||
bt_class = class_create(THIS_MODULE, "bluetooth");
|
||||
if (IS_ERR(bt_class))
|
||||
return PTR_ERR(bt_class);
|
||||
|
||||
return 0;
|
||||
return PTR_RET(bt_class);
|
||||
}
|
||||
|
||||
void bt_sysfs_cleanup(void)
|
||||
|
||||
@@ -311,6 +311,9 @@ static int hidp_get_raw_report(struct hid_device *hid,
|
||||
int numbered_reports = hid->report_enum[report_type].numbered;
|
||||
int ret;
|
||||
|
||||
if (atomic_read(&session->terminate))
|
||||
return -EIO;
|
||||
|
||||
switch (report_type) {
|
||||
case HID_FEATURE_REPORT:
|
||||
report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
|
||||
@@ -722,6 +725,7 @@ static int hidp_session(void *arg)
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
atomic_inc(&session->terminate);
|
||||
remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
|
||||
remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
|
||||
|
||||
|
||||
@@ -304,8 +304,6 @@ error:
|
||||
void __exit hidp_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "hidp");
|
||||
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
|
||||
BT_ERR("Can't unregister HIDP socket");
|
||||
|
||||
bt_sock_unregister(BTPROTO_HIDP);
|
||||
proto_unregister(&hidp_proto);
|
||||
}
|
||||
|
||||
@@ -1312,8 +1312,6 @@ error:
|
||||
void l2cap_cleanup_sockets(void)
|
||||
{
|
||||
bt_procfs_cleanup(&init_net, "l2cap");
|
||||
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
|
||||
BT_ERR("L2CAP socket unregistration failed");
|
||||
|
||||
bt_sock_unregister(BTPROTO_L2CAP);
|
||||
proto_unregister(&l2cap_proto);
|
||||
}
|
||||
|
||||
+476
-220
File diff suppressed because it is too large
Load Diff
+79
-88
@@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
u8 sec_level,
|
||||
int *err);
|
||||
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
|
||||
static void rfcomm_session_del(struct rfcomm_session *s);
|
||||
static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
|
||||
|
||||
/* ---- RFCOMM frame parsing macros ---- */
|
||||
#define __get_dlci(b) ((b & 0xfc) >> 2)
|
||||
@@ -108,12 +108,6 @@ static void rfcomm_schedule(void)
|
||||
wake_up_process(rfcomm_thread);
|
||||
}
|
||||
|
||||
static void rfcomm_session_put(struct rfcomm_session *s)
|
||||
{
|
||||
if (atomic_dec_and_test(&s->refcnt))
|
||||
rfcomm_session_del(s);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM FCS computation ---- */
|
||||
|
||||
/* reversed, 8-bit, poly=0x07 */
|
||||
@@ -249,16 +243,14 @@ static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout)
|
||||
{
|
||||
BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout);
|
||||
|
||||
if (!mod_timer(&s->timer, jiffies + timeout))
|
||||
rfcomm_session_hold(s);
|
||||
mod_timer(&s->timer, jiffies + timeout);
|
||||
}
|
||||
|
||||
static void rfcomm_session_clear_timer(struct rfcomm_session *s)
|
||||
{
|
||||
BT_DBG("session %p state %ld", s, s->state);
|
||||
|
||||
if (del_timer(&s->timer))
|
||||
rfcomm_session_put(s);
|
||||
del_timer_sync(&s->timer);
|
||||
}
|
||||
|
||||
/* ---- RFCOMM DLCs ---- */
|
||||
@@ -336,8 +328,6 @@ static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d)
|
||||
{
|
||||
BT_DBG("dlc %p session %p", d, s);
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
rfcomm_dlc_hold(d);
|
||||
list_add(&d->list, &s->dlcs);
|
||||
@@ -356,8 +346,6 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
|
||||
|
||||
if (list_empty(&s->dlcs))
|
||||
rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT);
|
||||
|
||||
rfcomm_session_put(s);
|
||||
}
|
||||
|
||||
static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
|
||||
@@ -493,12 +481,34 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
|
||||
|
||||
int rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
|
||||
{
|
||||
int r;
|
||||
int r = 0;
|
||||
struct rfcomm_dlc *d_list;
|
||||
struct rfcomm_session *s, *s_list;
|
||||
|
||||
BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err);
|
||||
|
||||
rfcomm_lock();
|
||||
|
||||
r = __rfcomm_dlc_close(d, err);
|
||||
s = d->session;
|
||||
if (!s)
|
||||
goto no_session;
|
||||
|
||||
/* after waiting on the mutex check the session still exists
|
||||
* then check the dlc still exists
|
||||
*/
|
||||
list_for_each_entry(s_list, &session_list, list) {
|
||||
if (s_list == s) {
|
||||
list_for_each_entry(d_list, &s->dlcs, list) {
|
||||
if (d_list == d) {
|
||||
r = __rfcomm_dlc_close(d, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
no_session:
|
||||
rfcomm_unlock();
|
||||
return r;
|
||||
}
|
||||
@@ -609,7 +619,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_session_del(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s)
|
||||
{
|
||||
int state = s->state;
|
||||
|
||||
@@ -617,15 +627,14 @@ static void rfcomm_session_del(struct rfcomm_session *s)
|
||||
|
||||
list_del(&s->list);
|
||||
|
||||
if (state == BT_CONNECTED)
|
||||
rfcomm_send_disc(s, 0);
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
sock_release(s->sock);
|
||||
kfree(s);
|
||||
|
||||
if (state != BT_LISTEN)
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
|
||||
@@ -644,17 +653,16 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rfcomm_session_close(struct rfcomm_session *s, int err)
|
||||
static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
|
||||
int err)
|
||||
{
|
||||
struct rfcomm_dlc *d;
|
||||
struct list_head *p, *n;
|
||||
|
||||
BT_DBG("session %p state %ld err %d", s, s->state, err);
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
|
||||
BT_DBG("session %p state %ld err %d", s, s->state, err);
|
||||
|
||||
/* Close all dlcs */
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
@@ -663,7 +671,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
|
||||
}
|
||||
|
||||
rfcomm_session_clear_timer(s);
|
||||
rfcomm_session_put(s);
|
||||
return rfcomm_session_del(s);
|
||||
}
|
||||
|
||||
static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
@@ -715,8 +723,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
|
||||
if (*err == 0 || *err == -EINPROGRESS)
|
||||
return s;
|
||||
|
||||
rfcomm_session_del(s);
|
||||
return NULL;
|
||||
return rfcomm_session_del(s);
|
||||
|
||||
failed:
|
||||
sock_release(sock);
|
||||
@@ -1105,7 +1112,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
|
||||
}
|
||||
|
||||
/* ---- RFCOMM frame reception ---- */
|
||||
static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
{
|
||||
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
|
||||
|
||||
@@ -1114,7 +1121,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
|
||||
if (!d) {
|
||||
rfcomm_send_dm(s, dlci);
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (d->state) {
|
||||
@@ -1150,25 +1157,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
|
||||
break;
|
||||
|
||||
case BT_DISCONN:
|
||||
/* rfcomm_session_put is called later so don't do
|
||||
* anything here otherwise we will mess up the session
|
||||
* reference counter:
|
||||
*
|
||||
* (a) when we are the initiator dlc_unlink will drive
|
||||
* the reference counter to 0 (there is no initial put
|
||||
* after session_add)
|
||||
*
|
||||
* (b) when we are not the initiator rfcomm_rx_process
|
||||
* will explicitly call put to balance the initial hold
|
||||
* done after session add.
|
||||
*/
|
||||
s = rfcomm_session_close(s, ECONNRESET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -1192,13 +1188,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
|
||||
else
|
||||
err = ECONNRESET;
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, err);
|
||||
s = rfcomm_session_close(s, err);
|
||||
}
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
|
||||
static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s,
|
||||
u8 dlci)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -1227,11 +1223,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
|
||||
else
|
||||
err = ECONNRESET;
|
||||
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, err);
|
||||
s = rfcomm_session_close(s, err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
|
||||
@@ -1652,11 +1646,18 @@ drop:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rfcomm_hdr *hdr = (void *) skb->data;
|
||||
u8 type, dlci, fcs;
|
||||
|
||||
if (!s) {
|
||||
/* no session, so free socket data */
|
||||
kfree_skb(skb);
|
||||
return s;
|
||||
}
|
||||
|
||||
dlci = __get_dlci(hdr->addr);
|
||||
type = __get_type(hdr->ctrl);
|
||||
|
||||
@@ -1667,7 +1668,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
if (__check_fcs(skb->data, type, fcs)) {
|
||||
BT_ERR("bad checksum in packet");
|
||||
kfree_skb(skb);
|
||||
return -EILSEQ;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (__test_ea(hdr->len))
|
||||
@@ -1683,22 +1684,23 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
|
||||
case RFCOMM_DISC:
|
||||
if (__test_pf(hdr->ctrl))
|
||||
rfcomm_recv_disc(s, dlci);
|
||||
s = rfcomm_recv_disc(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_UA:
|
||||
if (__test_pf(hdr->ctrl))
|
||||
rfcomm_recv_ua(s, dlci);
|
||||
s = rfcomm_recv_ua(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_DM:
|
||||
rfcomm_recv_dm(s, dlci);
|
||||
s = rfcomm_recv_dm(s, dlci);
|
||||
break;
|
||||
|
||||
case RFCOMM_UIH:
|
||||
if (dlci)
|
||||
return rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
|
||||
|
||||
if (dlci) {
|
||||
rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb);
|
||||
return s;
|
||||
}
|
||||
rfcomm_recv_mcc(s, skb);
|
||||
break;
|
||||
|
||||
@@ -1707,7 +1709,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ---- Connection and data processing ---- */
|
||||
@@ -1844,7 +1846,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void rfcomm_process_rx(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s)
|
||||
{
|
||||
struct socket *sock = s->sock;
|
||||
struct sock *sk = sock->sk;
|
||||
@@ -1856,17 +1858,15 @@ static void rfcomm_process_rx(struct rfcomm_session *s)
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
if (!skb_linearize(skb))
|
||||
rfcomm_recv_frame(s, skb);
|
||||
s = rfcomm_recv_frame(s, skb);
|
||||
else
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
if (sk->sk_state == BT_CLOSED) {
|
||||
if (!s->initiator)
|
||||
rfcomm_session_put(s);
|
||||
if (s && (sk->sk_state == BT_CLOSED))
|
||||
s = rfcomm_session_close(s, sk->sk_err);
|
||||
|
||||
rfcomm_session_close(s, sk->sk_err);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
@@ -1891,8 +1891,6 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
|
||||
s = rfcomm_session_add(nsock, BT_OPEN);
|
||||
if (s) {
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
/* We should adjust MTU on incoming sessions.
|
||||
* L2CAP MTU minus UIH header and FCS. */
|
||||
s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
|
||||
@@ -1903,7 +1901,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s)
|
||||
sock_release(nsock);
|
||||
}
|
||||
|
||||
static void rfcomm_check_connection(struct rfcomm_session *s)
|
||||
static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s)
|
||||
{
|
||||
struct sock *sk = s->sock->sk;
|
||||
|
||||
@@ -1921,10 +1919,10 @@ static void rfcomm_check_connection(struct rfcomm_session *s)
|
||||
break;
|
||||
|
||||
case BT_CLOSED:
|
||||
s->state = BT_CLOSED;
|
||||
rfcomm_session_close(s, sk->sk_err);
|
||||
s = rfcomm_session_close(s, sk->sk_err);
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rfcomm_process_sessions(void)
|
||||
@@ -1940,7 +1938,6 @@ static void rfcomm_process_sessions(void)
|
||||
if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
|
||||
s->state = BT_DISCONN;
|
||||
rfcomm_send_disc(s, 0);
|
||||
rfcomm_session_put(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1949,21 +1946,18 @@ static void rfcomm_process_sessions(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
switch (s->state) {
|
||||
case BT_BOUND:
|
||||
rfcomm_check_connection(s);
|
||||
s = rfcomm_check_connection(s);
|
||||
break;
|
||||
|
||||
default:
|
||||
rfcomm_process_rx(s);
|
||||
s = rfcomm_process_rx(s);
|
||||
break;
|
||||
}
|
||||
|
||||
rfcomm_process_dlcs(s);
|
||||
|
||||
rfcomm_session_put(s);
|
||||
if (s)
|
||||
rfcomm_process_dlcs(s);
|
||||
}
|
||||
|
||||
rfcomm_unlock();
|
||||
@@ -2010,10 +2004,11 @@ static int rfcomm_add_listener(bdaddr_t *ba)
|
||||
|
||||
/* Add listening session */
|
||||
s = rfcomm_session_add(sock, BT_LISTEN);
|
||||
if (!s)
|
||||
if (!s) {
|
||||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
return 0;
|
||||
failed:
|
||||
sock_release(sock);
|
||||
@@ -2071,8 +2066,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
rfcomm_session_hold(s);
|
||||
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
|
||||
@@ -2104,8 +2097,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
||||
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
|
||||
}
|
||||
|
||||
rfcomm_session_put(s);
|
||||
|
||||
rfcomm_schedule();
|
||||
}
|
||||
|
||||
|
||||
@@ -1065,8 +1065,7 @@ void __exit rfcomm_cleanup_sockets(void)
|
||||
|
||||
debugfs_remove(rfcomm_sock_debugfs);
|
||||
|
||||
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
|
||||
BT_ERR("RFCOMM socket layer unregistration failed");
|
||||
bt_sock_unregister(BTPROTO_RFCOMM);
|
||||
|
||||
proto_unregister(&rfcomm_proto);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user