blob: 6e242f78389ba80de8ab0350124ae1a093a6af92 [file] [log] [blame]
--- 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)