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 | skb_checksum_none_assert(skb); |
15 | skb->protocol = *((__be16 *)data); |
16 | |
17 | skb_put_data(skb, data, len: size); |
18 | skb->mac_header = HFI1_IPOIB_PSEUDO_LEN; |
19 | skb_pull(skb, HFI1_IPOIB_ENCAP_LEN); |
20 | } |
21 | |
22 | static struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size) |
23 | { |
24 | struct sk_buff *skb; |
25 | int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD); |
26 | void *frag; |
27 | |
28 | skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); |
29 | skb_size = SKB_DATA_ALIGN(skb_size); |
30 | frag = napi_alloc_frag(fragsz: skb_size); |
31 | |
32 | if (unlikely(!frag)) |
33 | return napi_alloc_skb(napi, length: size); |
34 | |
35 | skb = build_skb(data: frag, frag_size: skb_size); |
36 | |
37 | if (unlikely(!skb)) { |
38 | skb_free_frag(addr: frag); |
39 | return NULL; |
40 | } |
41 | |
42 | skb_reserve(skb, HFI1_IPOIB_SKB_PAD); |
43 | return skb; |
44 | } |
45 | |
46 | struct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq, |
47 | int size, void *data) |
48 | { |
49 | struct napi_struct *napi = &rxq->napi; |
50 | int skb_size = size + HFI1_IPOIB_ENCAP_LEN; |
51 | struct sk_buff *skb; |
52 | |
53 | /* |
54 | * For smaller(4k + skb overhead) allocations we will go using |
55 | * napi cache. Otherwise we will try to use napi frag cache. |
56 | */ |
57 | if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE)) |
58 | skb = napi_alloc_skb(napi, length: skb_size); |
59 | else |
60 | skb = prepare_frag_skb(napi, size: skb_size); |
61 | |
62 | if (unlikely(!skb)) |
63 | return NULL; |
64 | |
65 | copy_ipoib_buf(skb, data, size); |
66 | |
67 | return skb; |
68 | } |
69 | |
70 | int hfi1_ipoib_rxq_init(struct net_device *netdev) |
71 | { |
72 | struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(dev: netdev); |
73 | struct hfi1_devdata *dd = ipoib_priv->dd; |
74 | int ret; |
75 | |
76 | ret = hfi1_netdev_rx_init(dd); |
77 | if (ret) |
78 | return ret; |
79 | |
80 | hfi1_init_aip_rsm(dd); |
81 | |
82 | return ret; |
83 | } |
84 | |
85 | void hfi1_ipoib_rxq_deinit(struct net_device *netdev) |
86 | { |
87 | struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(dev: netdev); |
88 | struct hfi1_devdata *dd = ipoib_priv->dd; |
89 | |
90 | hfi1_deinit_aip_rsm(dd); |
91 | hfi1_netdev_rx_destroy(dd); |
92 | } |
93 | |