| --- a/include/net/bluetooth/l2cap.h |
| +++ b/include/net/bluetooth/l2cap.h |
| @@ -613,6 +613,12 @@ struct l2cap_ops { |
| struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
| unsigned long hdr_len, |
| unsigned long len, int nb); |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + int (*memcpy_fromiovec) (struct l2cap_chan *chan, |
| + unsigned char *kdata, |
| + struct iovec *iov, |
| + int len); |
| +#endif |
| }; |
| |
| struct l2cap_conn { |
| @@ -906,6 +912,33 @@ static inline long l2cap_chan_no_get_snd |
| return 0; |
| } |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| +static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan, |
| + unsigned char *kdata, |
| + struct iovec *iov, |
| + int len) |
| +{ |
| + /* Following is safe since for compiler definitions of kvec and |
| + * iovec are identical, yielding the same in-core layout and alignment |
| + */ |
| + struct kvec *vec = (struct kvec *)iov; |
| + |
| + while (len > 0) { |
| + if (vec->iov_len) { |
| + int copy = min_t(unsigned int, len, vec->iov_len); |
| + memcpy(kdata, vec->iov_base, copy); |
| + len -= copy; |
| + kdata += copy; |
| + vec->iov_base += copy; |
| + vec->iov_len -= copy; |
| + } |
| + vec++; |
| + } |
| + |
| + return 0; |
| +} |
| +#endif |
| + |
| extern bool disable_ertm; |
| |
| int l2cap_init_sockets(void); |
| --- a/net/bluetooth/6lowpan.c |
| +++ b/net/bluetooth/6lowpan.c |
| @@ -510,11 +510,18 @@ static int send_pkt(struct l2cap_chan *c |
| */ |
| chan->data = skb; |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + memset(&msg, 0, sizeof(msg)); |
| + msg.msg_iov = (struct iovec *) &iv; |
| + msg.msg_iovlen = 1; |
| +#endif |
| iv.iov_base = skb->data; |
| iv.iov_len = skb->len; |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) |
| memset(&msg, 0, sizeof(msg)); |
| iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len); |
| +#endif |
| |
| err = l2cap_chan_send(chan, &msg, skb->len); |
| if (err > 0) { |
| @@ -1014,6 +1021,9 @@ static const struct l2cap_ops bt_6lowpan |
| .suspend = chan_suspend_cb, |
| .get_sndtimeo = chan_get_sndtimeo_cb, |
| .alloc_skb = chan_alloc_skb_cb, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, |
| +#endif |
| |
| .teardown = l2cap_chan_no_teardown, |
| .defer = l2cap_chan_no_defer, |
| --- a/net/bluetooth/a2mp.c |
| +++ b/net/bluetooth/a2mp.c |
| @@ -63,7 +63,12 @@ static void a2mp_send(struct amp_mgr *mg |
| |
| memset(&msg, 0, sizeof(msg)); |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) |
| iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len); |
| +#else |
| + msg.msg_iov = (struct iovec *) &iv; |
| + msg.msg_iovlen = 1; |
| +#endif |
| |
| l2cap_chan_send(chan, &msg, total_len); |
| |
| @@ -753,6 +758,9 @@ static const struct l2cap_ops a2mp_chan_ |
| .resume = l2cap_chan_no_resume, |
| .set_shutdown = l2cap_chan_no_set_shutdown, |
| .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, |
| +#endif |
| }; |
| |
| static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
| --- a/net/bluetooth/l2cap_core.c |
| +++ b/net/bluetooth/l2cap_core.c |
| @@ -2116,7 +2116,12 @@ static inline int l2cap_skbuff_fromiovec |
| struct sk_buff **frag; |
| int sent = 0; |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) |
| if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count) |
| +#else |
| + if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count), |
| + msg->msg_iov, count)) |
| +#endif |
| return -EFAULT; |
| |
| sent += count; |
| @@ -2136,8 +2141,13 @@ static inline int l2cap_skbuff_fromiovec |
| |
| *frag = tmp; |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) |
| if (copy_from_iter(skb_put(*frag, count), count, |
| &msg->msg_iter) != count) |
| +#else |
| + if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count), |
| + msg->msg_iov, count)) |
| +#endif |
| return -EFAULT; |
| |
| sent += count; |
| --- a/net/bluetooth/l2cap_sock.c |
| +++ b/net/bluetooth/l2cap_sock.c |
| @@ -1383,6 +1383,15 @@ static struct sk_buff *l2cap_sock_alloc_ |
| return skb; |
| } |
| |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| +static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan, |
| + unsigned char *kdata, |
| + struct iovec *iov, int len) |
| +{ |
| + return memcpy_fromiovec(kdata, iov, len); |
| +} |
| +#endif |
| + |
| static void l2cap_sock_ready_cb(struct l2cap_chan *chan) |
| { |
| struct sock *sk = chan->data; |
| @@ -1467,6 +1476,9 @@ static const struct l2cap_ops l2cap_chan |
| .set_shutdown = l2cap_sock_set_shutdown_cb, |
| .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, |
| .alloc_skb = l2cap_sock_alloc_skb_cb, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + .memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb, |
| +#endif |
| }; |
| |
| static void l2cap_sock_destruct(struct sock *sk) |
| --- a/net/bluetooth/smp.c |
| +++ b/net/bluetooth/smp.c |
| @@ -619,7 +619,12 @@ static void smp_send_cmd(struct l2cap_co |
| |
| memset(&msg, 0, sizeof(msg)); |
| |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) |
| iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len); |
| +#else |
| + msg.msg_iov = (struct iovec *) &iv; |
| + msg.msg_iovlen = 2; |
| +#endif |
| |
| l2cap_chan_send(chan, &msg, 1 + len); |
| |
| @@ -3084,6 +3089,9 @@ static const struct l2cap_ops smp_chan_o |
| .suspend = l2cap_chan_no_suspend, |
| .set_shutdown = l2cap_chan_no_set_shutdown, |
| .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, |
| +#endif |
| }; |
| |
| static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) |
| @@ -3132,6 +3140,9 @@ static const struct l2cap_ops smp_root_c |
| .resume = l2cap_chan_no_resume, |
| .set_shutdown = l2cap_chan_no_set_shutdown, |
| .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) |
| + .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, |
| +#endif |
| }; |
| |
| static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) |