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