18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright(c) 2020 Intel Corporation.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "netdev.h"
88c2ecf20Sopenharmony_ci#include "ipoib.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define HFI1_IPOIB_SKB_PAD ((NET_SKB_PAD) + (NET_IP_ALIGN))
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic void copy_ipoib_buf(struct sk_buff *skb, void *data, int size)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	void *dst_data;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	skb_checksum_none_assert(skb);
178c2ecf20Sopenharmony_ci	skb->protocol = *((__be16 *)data);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	dst_data = skb_put(skb, size);
208c2ecf20Sopenharmony_ci	memcpy(dst_data, data, size);
218c2ecf20Sopenharmony_ci	skb->mac_header = HFI1_IPOIB_PSEUDO_LEN;
228c2ecf20Sopenharmony_ci	skb_pull(skb, HFI1_IPOIB_ENCAP_LEN);
238c2ecf20Sopenharmony_ci}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct sk_buff *prepare_frag_skb(struct napi_struct *napi, int size)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	struct sk_buff *skb;
288c2ecf20Sopenharmony_ci	int skb_size = SKB_DATA_ALIGN(size + HFI1_IPOIB_SKB_PAD);
298c2ecf20Sopenharmony_ci	void *frag;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	skb_size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
328c2ecf20Sopenharmony_ci	skb_size = SKB_DATA_ALIGN(skb_size);
338c2ecf20Sopenharmony_ci	frag = napi_alloc_frag(skb_size);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (unlikely(!frag))
368c2ecf20Sopenharmony_ci		return napi_alloc_skb(napi, size);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	skb = build_skb(frag, skb_size);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (unlikely(!skb)) {
418c2ecf20Sopenharmony_ci		skb_free_frag(frag);
428c2ecf20Sopenharmony_ci		return NULL;
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	skb_reserve(skb, HFI1_IPOIB_SKB_PAD);
468c2ecf20Sopenharmony_ci	return skb;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct sk_buff *hfi1_ipoib_prepare_skb(struct hfi1_netdev_rxq *rxq,
508c2ecf20Sopenharmony_ci				       int size, void *data)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	struct napi_struct *napi = &rxq->napi;
538c2ecf20Sopenharmony_ci	int skb_size = size + HFI1_IPOIB_ENCAP_LEN;
548c2ecf20Sopenharmony_ci	struct sk_buff *skb;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	/*
578c2ecf20Sopenharmony_ci	 * For smaller(4k + skb overhead) allocations we will go using
588c2ecf20Sopenharmony_ci	 * napi cache. Otherwise we will try to use napi frag cache.
598c2ecf20Sopenharmony_ci	 */
608c2ecf20Sopenharmony_ci	if (size <= SKB_WITH_OVERHEAD(PAGE_SIZE))
618c2ecf20Sopenharmony_ci		skb = napi_alloc_skb(napi, skb_size);
628c2ecf20Sopenharmony_ci	else
638c2ecf20Sopenharmony_ci		skb = prepare_frag_skb(napi, skb_size);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	if (unlikely(!skb))
668c2ecf20Sopenharmony_ci		return NULL;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	copy_ipoib_buf(skb, data, size);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return skb;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciint hfi1_ipoib_rxq_init(struct net_device *netdev)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
768c2ecf20Sopenharmony_ci	struct hfi1_devdata *dd = ipoib_priv->dd;
778c2ecf20Sopenharmony_ci	int ret;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	ret = hfi1_netdev_rx_init(dd);
808c2ecf20Sopenharmony_ci	if (ret)
818c2ecf20Sopenharmony_ci		return ret;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	hfi1_init_aip_rsm(dd);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return ret;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_civoid hfi1_ipoib_rxq_deinit(struct net_device *netdev)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct hfi1_ipoib_dev_priv *ipoib_priv = hfi1_ipoib_priv(netdev);
918c2ecf20Sopenharmony_ci	struct hfi1_devdata *dd = ipoib_priv->dd;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	hfi1_deinit_aip_rsm(dd);
948c2ecf20Sopenharmony_ci	hfi1_netdev_rx_destroy(dd);
958c2ecf20Sopenharmony_ci}
96