xref: /linux/drivers/infiniband/hw/hfi1/ipoib_rx.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
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, 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(skb_size);
31 
32 	if (unlikely(!frag))
33 		return napi_alloc_skb(napi, size);
34 
35 	skb = build_skb(frag, skb_size);
36 
37 	if (unlikely(!skb)) {
38 		skb_free_frag(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, skb_size);
59 	else
60 		skb = prepare_frag_skb(napi, 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(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(netdev);
88 	struct hfi1_devdata *dd = ipoib_priv->dd;
89 
90 	hfi1_deinit_aip_rsm(dd);
91 	hfi1_netdev_rx_destroy(dd);
92 }
93