From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This works similarly to bt_skb_sendmsg but can split the msg into multiple skb fragments which is useful for stream sockets. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> --- include/net/bluetooth/bluetooth.h | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index f858efcf9f40..96743e6e7a0a 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -446,6 +446,41 @@ static inline struct sk_buff *bt_skb_sendmsg(struct sock *sk, return skb; } +/* Similar to bt_skb_sendmsg but can split the msg into multiple fragments + * accourding to the MTU. + */ +static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, + struct msghdr *msg, + size_t len, size_t mtu, + size_t header, size_t footer) +{ + struct sk_buff *skb, **frag; + size_t size = min_t(size_t, len, mtu); + + skb = bt_skb_sendmsg(sk, msg, size, header, footer); + if (IS_ERR_OR_NULL(skb)) + return skb; + + len -= size; + if (!len) + return skb; + + /* Add remaining data over MTU as continuation fragments */ + frag = &skb_shinfo(skb)->frag_list; + while (len) { + *frag = bt_skb_sendmsg(sk, msg, size, header, footer); + if (IS_ERR_OR_NULL(*frag)) { + kfree_skb(skb); + return *frag; + } + + len -= (*frag)->len; + frag = &(*frag)->next; + } + + return skb; +} + int bt_to_errno(u16 code); void hci_sock_set_flag(struct sock *sk, int nr); -- 2.31.1