xref: /openbmc/linux/drivers/infiniband/hw/hfi1/ipoib_rx.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
16991abcbSKaike Wan // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
26991abcbSKaike Wan /*
36991abcbSKaike Wan  * Copyright(c) 2020 Intel Corporation.
46991abcbSKaike Wan  *
56991abcbSKaike Wan  */
66991abcbSKaike Wan 
76991abcbSKaike Wan #include "netdev.h"
86991abcbSKaike Wan #include "ipoib.h"
96991abcbSKaike Wan 
106991abcbSKaike Wan #define HFI1_IPOIB_SKB_PAD ((NET_SKB_PAD) + (NET_IP_ALIGN))
116991abcbSKaike Wan 
copy_ipoib_buf(struct sk_buff * skb,void * data,int size)126991abcbSKaike Wan static void copy_ipoib_buf(struct sk_buff *skb, void *data, int size)
136991abcbSKaike Wan {
146991abcbSKaike Wan 	skb_checksum_none_assert(skb);
156991abcbSKaike Wan 	skb->protocol = *((__be16 *)data);
166991abcbSKaike Wan 
17*cbdae01dSShang XiaoJing 	skb_put_data(skb, data, size);
186991abcbSKaike Wan 	skb->mac_header = HFI1_IPOIB_PSEUDO_LEN;
196991abcbSKaike Wan 	skb_pull(skb, HFI1_IPOIB_ENCAP_LEN);
206991abcbSKaike Wan }
216991abcbSKaike Wan 
prepare_frag_skb(struct napi_struct * napi,int size)226991abcbSKaike Wan static struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size)
236991abcbSKaike Wan {
246991abcbSKaike Wan 	struct sk_buff *skb;
256991abcbSKaike Wan 	int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD);
266991abcbSKaike Wan 	void *frag;
276991abcbSKaike Wan 
286991abcbSKaike Wan 	skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
296991abcbSKaike Wan 	skb_size = SKB_DATA_ALIGN(skb_size);
306991abcbSKaike Wan 	frag = napi_alloc_frag(skb_size);
316991abcbSKaike Wan 
326991abcbSKaike Wan 	if (unlikely(!frag))
336991abcbSKaike Wan 		return napi_alloc_skb(napi, size);
346991abcbSKaike Wan 
356991abcbSKaike Wan 	skb = build_skb(frag, skb_size);
366991abcbSKaike Wan 
376991abcbSKaike Wan 	if (unlikely(!skb)) {
386991abcbSKaike Wan 		skb_free_frag(frag);
396991abcbSKaike Wan 		return NULL;
406991abcbSKaike Wan 	}
416991abcbSKaike Wan 
426991abcbSKaike Wan 	skb_reserve(skb, HFI1_IPOIB_SKB_PAD);
436991abcbSKaike Wan 	return skb;
446991abcbSKaike Wan }
456991abcbSKaike Wan 
hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq * rxq,int size,void * data)466991abcbSKaike Wan struct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq,
476991abcbSKaike Wan 				       int size, void *data)
486991abcbSKaike Wan {
496991abcbSKaike Wan 	struct napi_struct *napi = &rxq->napi;
506991abcbSKaike Wan 	int skb_size = size + HFI1_IPOIB_ENCAP_LEN;
516991abcbSKaike Wan 	struct sk_buff *skb;
526991abcbSKaike Wan 
536991abcbSKaike Wan 	/*
546991abcbSKaike Wan 	 * For smaller(4k + skb overhead) allocations we will go using
556991abcbSKaike Wan 	 * napi cache. Otherwise we will try to use napi frag cache.
566991abcbSKaike Wan 	 */
576991abcbSKaike Wan 	if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE))
586991abcbSKaike Wan 		skb = napi_alloc_skb(napi, skb_size);
596991abcbSKaike Wan 	else
606991abcbSKaike Wan 		skb = prepare_frag_skb(napi, skb_size);
616991abcbSKaike Wan 
626991abcbSKaike Wan 	if (unlikely(!skb))
636991abcbSKaike Wan 		return NULL;
646991abcbSKaike Wan 
656991abcbSKaike Wan 	copy_ipoib_buf(skb, data, size);
666991abcbSKaike Wan 
676991abcbSKaike Wan 	return skb;
686991abcbSKaike Wan }
69370caa5bSGrzegorz Andrejczuk 
hfi1_ipoib_rxq_init(struct net_device * netdev)70370caa5bSGrzegorz Andrejczuk int hfi1_ipoib_rxq_init(struct net_device *netdev)
71370caa5bSGrzegorz Andrejczuk {
72370caa5bSGrzegorz Andrejczuk 	struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
73370caa5bSGrzegorz Andrejczuk 	struct hfi1_devdata *dd = ipoib_priv->dd;
744730f4a6SGrzegorz Andrejczuk 	int ret;
75370caa5bSGrzegorz Andrejczuk 
764730f4a6SGrzegorz Andrejczuk 	ret = hfi1_netdev_rx_init(dd);
774730f4a6SGrzegorz Andrejczuk 	if (ret)
784730f4a6SGrzegorz Andrejczuk 		return ret;
794730f4a6SGrzegorz Andrejczuk 
804730f4a6SGrzegorz Andrejczuk 	hfi1_init_aip_rsm(dd);
814730f4a6SGrzegorz Andrejczuk 
824730f4a6SGrzegorz Andrejczuk 	return ret;
83370caa5bSGrzegorz Andrejczuk }
84370caa5bSGrzegorz Andrejczuk 
hfi1_ipoib_rxq_deinit(struct net_device * netdev)85370caa5bSGrzegorz Andrejczuk void hfi1_ipoib_rxq_deinit(struct net_device *netdev)
86370caa5bSGrzegorz Andrejczuk {
87370caa5bSGrzegorz Andrejczuk 	struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
88370caa5bSGrzegorz Andrejczuk 	struct hfi1_devdata *dd = ipoib_priv->dd;
89370caa5bSGrzegorz Andrejczuk 
904730f4a6SGrzegorz Andrejczuk 	hfi1_deinit_aip_rsm(dd);
91370caa5bSGrzegorz Andrejczuk 	hfi1_netdev_rx_destroy(dd);
92370caa5bSGrzegorz Andrejczuk }
93