GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / infiniband / hw / hfi1 / ipoib_rx.c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Copyright(c) 2020 Intel Corporation.
4  *
5  */
6
7 #include "netdev.h"
8 #include "ipoib.h"
9
10 #define HFI1_IPOIB_SKB_PAD ((NET_SKB_PAD) + (NET_IP_ALIGN))
11
12 static void copy_ipoib_buf(struct sk_buff *skb, void *data, int size)
13 {
14         void *dst_data;
15
16         skb_checksum_none_assert(skb);
17         skb->protocol = *((__be16 *)data);
18
19         dst_data = skb_put(skb, size);
20         memcpy(dst_data, data, size);
21         skb->mac_header = HFI1_IPOIB_PSEUDO_LEN;
22         skb_pull(skb, HFI1_IPOIB_ENCAP_LEN);
23 }
24
25 static struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size)
26 {
27         struct sk_buff *skb;
28         int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD);
29         void *frag;
30
31         skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
32         skb_size = SKB_DATA_ALIGN(skb_size);
33         frag = napi_alloc_frag(skb_size);
34
35         if (unlikely(!frag))
36                 return napi_alloc_skb(napi, size);
37
38         skb = build_skb(frag, skb_size);
39
40         if (unlikely(!skb)) {
41                 skb_free_frag(frag);
42                 return NULL;
43         }
44
45         skb_reserve(skb, HFI1_IPOIB_SKB_PAD);
46         return skb;
47 }
48
49 struct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq,
50                                        int size, void *data)
51 {
52         struct napi_struct *napi = &rxq->napi;
53         int skb_size = size + HFI1_IPOIB_ENCAP_LEN;
54         struct sk_buff *skb;
55
56         /*
57          * For smaller(4k + skb overhead) allocations we will go using
58          * napi cache. Otherwise we will try to use napi frag cache.
59          */
60         if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE))
61                 skb = napi_alloc_skb(napi, skb_size);
62         else
63                 skb = prepare_frag_skb(napi, skb_size);
64
65         if (unlikely(!skb))
66                 return NULL;
67
68         copy_ipoib_buf(skb, data, size);
69
70         return skb;
71 }
72
73 int hfi1_ipoib_rxq_init(struct net_device *netdev)
74 {
75         struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
76         struct hfi1_devdata *dd = ipoib_priv->dd;
77         int ret;
78
79         ret = hfi1_netdev_rx_init(dd);
80         if (ret)
81                 return ret;
82
83         hfi1_init_aip_rsm(dd);
84
85         return ret;
86 }
87
88 void hfi1_ipoib_rxq_deinit(struct net_device *netdev)
89 {
90         struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
91         struct hfi1_devdata *dd = ipoib_priv->dd;
92
93         hfi1_deinit_aip_rsm(dd);
94         hfi1_netdev_rx_destroy(dd);
95 }