diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 29 | ||||
-rw-r--r-- | net/bluetooth/a2mp.c | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 6 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 34 |
4 files changed, 55 insertions, 15 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 92511034d1d4..1ee6f00d7096 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -602,6 +602,10 @@ struct l2cap_ops { | |||
602 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 602 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
603 | unsigned long hdr_len, | 603 | unsigned long hdr_len, |
604 | unsigned long len, int nb); | 604 | unsigned long len, int nb); |
605 | int (*memcpy_fromiovec) (struct l2cap_chan *chan, | ||
606 | unsigned char *kdata, | ||
607 | struct iovec *iov, | ||
608 | int len); | ||
605 | }; | 609 | }; |
606 | 610 | ||
607 | struct l2cap_conn { | 611 | struct l2cap_conn { |
@@ -857,6 +861,31 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) | |||
857 | return 0; | 861 | return 0; |
858 | } | 862 | } |
859 | 863 | ||
864 | static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan, | ||
865 | unsigned char *kdata, | ||
866 | struct iovec *iov, | ||
867 | int len) | ||
868 | { | ||
869 | /* Following is safe since for compiler definitions of kvec and | ||
870 | * iovec are identical, yielding the same in-core layout and alignment | ||
871 | */ | ||
872 | struct kvec *vec = (struct kvec *)iov; | ||
873 | |||
874 | while (len > 0) { | ||
875 | if (vec->iov_len) { | ||
876 | int copy = min_t(unsigned int, len, vec->iov_len); | ||
877 | memcpy(kdata, vec->iov_base, copy); | ||
878 | len -= copy; | ||
879 | kdata += copy; | ||
880 | vec->iov_base += copy; | ||
881 | vec->iov_len -= copy; | ||
882 | } | ||
883 | vec++; | ||
884 | } | ||
885 | |||
886 | return 0; | ||
887 | } | ||
888 | |||
860 | extern bool disable_ertm; | 889 | extern bool disable_ertm; |
861 | 890 | ||
862 | int l2cap_init_sockets(void); | 891 | int l2cap_init_sockets(void); |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 0fd8d1dda709..5dcade511fdb 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -720,6 +720,7 @@ static const struct l2cap_ops a2mp_chan_ops = { | |||
720 | .resume = l2cap_chan_no_resume, | 720 | .resume = l2cap_chan_no_resume, |
721 | .set_shutdown = l2cap_chan_no_set_shutdown, | 721 | .set_shutdown = l2cap_chan_no_set_shutdown, |
722 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | 722 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
723 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
723 | }; | 724 | }; |
724 | 725 | ||
725 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | 726 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ac2461442f21..d0a5fde61a07 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2118,7 +2118,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2118 | struct sk_buff **frag; | 2118 | struct sk_buff **frag; |
2119 | int sent = 0; | 2119 | int sent = 0; |
2120 | 2120 | ||
2121 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) | 2121 | if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count), |
2122 | msg->msg_iov, count)) | ||
2122 | return -EFAULT; | 2123 | return -EFAULT; |
2123 | 2124 | ||
2124 | sent += count; | 2125 | sent += count; |
@@ -2138,7 +2139,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2138 | 2139 | ||
2139 | *frag = tmp; | 2140 | *frag = tmp; |
2140 | 2141 | ||
2141 | if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) | 2142 | if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count), |
2143 | msg->msg_iov, count)) | ||
2142 | return -EFAULT; | 2144 | return -EFAULT; |
2143 | 2145 | ||
2144 | sent += count; | 2146 | sent += count; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 55215ebf6547..bf72886de6ef 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1313,6 +1313,13 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | |||
1313 | return skb; | 1313 | return skb; |
1314 | } | 1314 | } |
1315 | 1315 | ||
1316 | static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan, | ||
1317 | unsigned char *kdata, | ||
1318 | struct iovec *iov, int len) | ||
1319 | { | ||
1320 | return memcpy_fromiovec(kdata, iov, len); | ||
1321 | } | ||
1322 | |||
1316 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | 1323 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) |
1317 | { | 1324 | { |
1318 | struct sock *sk = chan->data; | 1325 | struct sock *sk = chan->data; |
@@ -1379,19 +1386,20 @@ static void l2cap_sock_suspend_cb(struct l2cap_chan *chan) | |||
1379 | } | 1386 | } |
1380 | 1387 | ||
1381 | static const struct l2cap_ops l2cap_chan_ops = { | 1388 | static const struct l2cap_ops l2cap_chan_ops = { |
1382 | .name = "L2CAP Socket Interface", | 1389 | .name = "L2CAP Socket Interface", |
1383 | .new_connection = l2cap_sock_new_connection_cb, | 1390 | .new_connection = l2cap_sock_new_connection_cb, |
1384 | .recv = l2cap_sock_recv_cb, | 1391 | .recv = l2cap_sock_recv_cb, |
1385 | .close = l2cap_sock_close_cb, | 1392 | .close = l2cap_sock_close_cb, |
1386 | .teardown = l2cap_sock_teardown_cb, | 1393 | .teardown = l2cap_sock_teardown_cb, |
1387 | .state_change = l2cap_sock_state_change_cb, | 1394 | .state_change = l2cap_sock_state_change_cb, |
1388 | .ready = l2cap_sock_ready_cb, | 1395 | .ready = l2cap_sock_ready_cb, |
1389 | .defer = l2cap_sock_defer_cb, | 1396 | .defer = l2cap_sock_defer_cb, |
1390 | .resume = l2cap_sock_resume_cb, | 1397 | .resume = l2cap_sock_resume_cb, |
1391 | .suspend = l2cap_sock_suspend_cb, | 1398 | .suspend = l2cap_sock_suspend_cb, |
1392 | .set_shutdown = l2cap_sock_set_shutdown_cb, | 1399 | .set_shutdown = l2cap_sock_set_shutdown_cb, |
1393 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, | 1400 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, |
1394 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1401 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
1402 | .memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb, | ||
1395 | }; | 1403 | }; |
1396 | 1404 | ||
1397 | static void l2cap_sock_destruct(struct sock *sk) | 1405 | static void l2cap_sock_destruct(struct sock *sk) |