aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/l2cap.h29
-rw-r--r--net/bluetooth/a2mp.c1
-rw-r--r--net/bluetooth/l2cap_core.c6
-rw-r--r--net/bluetooth/l2cap_sock.c34
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
607struct l2cap_conn { 611struct 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
864static 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
860extern bool disable_ertm; 889extern bool disable_ertm;
861 890
862int l2cap_init_sockets(void); 891int 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
725static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) 726static 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
1316static 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
1316static void l2cap_sock_ready_cb(struct l2cap_chan *chan) 1323static 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
1381static const struct l2cap_ops l2cap_chan_ops = { 1388static 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
1397static void l2cap_sock_destruct(struct sock *sk) 1405static void l2cap_sock_destruct(struct sock *sk)