blob: 52048d341298ee6c07dd930a9f5b804a7a88b098 [file] [log] [blame]
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <nss_dp_dev.h>
#include "syn_dma_reg.h"
/*
* syn_dp_cfg_rx_setup_desc_queue
* This sets up the receive Descriptor queue in ring mode.
*/
static int syn_dp_cfg_rx_setup_desc_queue(struct syn_dp_info *dev_info)
{
struct syn_dp_info_rx *rx_info = &dev_info->dp_info_rx;
struct dma_desc_rx *first_desc = NULL;
struct net_device *netdev = rx_info->netdev;
netdev_dbg(netdev, "Total size of memory required for Rx Descriptors in Ring Mode = %u\n", (uint32_t)((sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE)));
/*
* Allocate cacheable descriptors for Rx
*/
first_desc = kzalloc(sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE, GFP_KERNEL);
if (!first_desc) {
netdev_dbg(netdev, "Error in Rx Descriptor Memory allocation in Ring mode\n");
return -ENOMEM;
}
dev_info->rx_desc_dma_addr = (dma_addr_t)virt_to_phys(first_desc);
rx_info->rx_desc = first_desc;
syn_dp_gmac_rx_desc_init_ring(rx_info->rx_desc, SYN_DP_RX_DESC_SIZE);
rx_info->rx_refill_idx = 0;
rx_info->rx_idx = 0;
rx_info->busy_rx_desc_cnt = 0;
netdev_dbg(netdev, "Rx Descriptors in Ring Mode: No. of descriptors = %d base = 0x%px dma = 0x%px\n",
SYN_DP_RX_DESC_SIZE, first_desc, (void *)dev_info->rx_desc_dma_addr);
return NSS_DP_SUCCESS;
}
/*
* syn_dp_cfg_rx_setup_rings
* Perform initial setup of Rx rings
*/
int syn_dp_cfg_rx_setup_rings(struct syn_dp_info *dev_info)
{
int err;
err = syn_dp_cfg_rx_setup_desc_queue(dev_info);
if (err) {
netdev_dbg(dev_info->dp_info_rx.netdev, "nss_dp_gmac: rx descriptor setup unsuccessfull, err code: %d", err);
return NSS_DP_FAILURE;
}
if (likely(!dev_info->dp_info_rx.page_mode)) {
syn_dp_rx_refill(&dev_info->dp_info_rx);
} else {
syn_dp_rx_refill_page_mode(&dev_info->dp_info_rx);
}
syn_init_rx_desc_base(dev_info->mac_base, dev_info->rx_desc_dma_addr);
return NSS_DP_SUCCESS;
}
/*
* syn_dp_cfg_rx_cleanup_rings
* Cleanup Synopsys GMAC Rx rings
*/
void syn_dp_cfg_rx_cleanup_rings(struct syn_dp_info *dev_info)
{
struct syn_dp_info_rx *rx_info = &dev_info->dp_info_rx;
uint32_t rx_skb_index;
struct dma_desc_rx *rxdesc;
int i;
struct sk_buff *skb;
/*
* Rx Ring cleaning
* We are assuming that the NAPI poll was already completed.
* No need of a lock here since the NAPI and interrupts have been disabled now
*/
rx_skb_index = rx_info->rx_idx;
for (i = 0; i < rx_info->busy_rx_desc_cnt; i++) {
rx_skb_index = (rx_skb_index + i) & SYN_DP_RX_DESC_MAX_INDEX;
rxdesc = rx_info->rx_desc;
skb = rx_info->rx_buf_pool[rx_skb_index].skb;
if (unlikely(skb != NULL)) {
dev_kfree_skb_any(skb);
rx_info->rx_buf_pool[rx_skb_index].skb = NULL;
}
}
kfree(rx_info->rx_desc);
rx_info->rx_desc = NULL;
dev_info->rx_desc_dma_addr = (dma_addr_t)0;
}