cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ethernet-mem.c (3917B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * This file is based on code from OCTEON SDK by Cavium Networks.
      4 *
      5 * Copyright (c) 2003-2010 Cavium Networks
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/netdevice.h>
     10#include <linux/slab.h>
     11
     12#include "octeon-ethernet.h"
     13#include "ethernet-mem.h"
     14#include "ethernet-defines.h"
     15
     16/**
     17 * cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs
     18 * @pool:     Pool to allocate an skbuff for
     19 * @size:     Size of the buffer needed for the pool
     20 * @elements: Number of buffers to allocate
     21 *
     22 * Returns the actual number of buffers allocated.
     23 */
     24static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)
     25{
     26	int freed = elements;
     27
     28	while (freed) {
     29		struct sk_buff *skb = dev_alloc_skb(size + 256);
     30
     31		if (unlikely(!skb))
     32			break;
     33		skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f));
     34		*(struct sk_buff **)(skb->data - sizeof(void *)) = skb;
     35		cvmx_fpa_free(skb->data, pool, size / 128);
     36		freed--;
     37	}
     38	return elements - freed;
     39}
     40
     41/**
     42 * cvm_oct_free_hw_skbuff- free hardware pool skbuffs
     43 * @pool:     Pool to allocate an skbuff for
     44 * @size:     Size of the buffer needed for the pool
     45 * @elements: Number of buffers to allocate
     46 */
     47static void cvm_oct_free_hw_skbuff(int pool, int size, int elements)
     48{
     49	char *memory;
     50
     51	do {
     52		memory = cvmx_fpa_alloc(pool);
     53		if (memory) {
     54			struct sk_buff *skb =
     55			    *(struct sk_buff **)(memory - sizeof(void *));
     56			elements--;
     57			dev_kfree_skb(skb);
     58		}
     59	} while (memory);
     60
     61	if (elements < 0)
     62		pr_warn("Freeing of pool %u had too many skbuffs (%d)\n",
     63			pool, elements);
     64	else if (elements > 0)
     65		pr_warn("Freeing of pool %u is missing %d skbuffs\n",
     66			pool, elements);
     67}
     68
     69/**
     70 * cvm_oct_fill_hw_memory - fill a hardware pool with memory.
     71 * @pool:     Pool to populate
     72 * @size:     Size of each buffer in the pool
     73 * @elements: Number of buffers to allocate
     74 *
     75 * Returns the actual number of buffers allocated.
     76 */
     77static int cvm_oct_fill_hw_memory(int pool, int size, int elements)
     78{
     79	char *memory;
     80	char *fpa;
     81	int freed = elements;
     82
     83	while (freed) {
     84		/*
     85		 * FPA memory must be 128 byte aligned.  Since we are
     86		 * aligning we need to save the original pointer so we
     87		 * can feed it to kfree when the memory is returned to
     88		 * the kernel.
     89		 *
     90		 * We allocate an extra 256 bytes to allow for
     91		 * alignment and space for the original pointer saved
     92		 * just before the block.
     93		 */
     94		memory = kmalloc(size + 256, GFP_ATOMIC);
     95		if (unlikely(!memory)) {
     96			pr_warn("Unable to allocate %u bytes for FPA pool %d\n",
     97				elements * size, pool);
     98			break;
     99		}
    100		fpa = (char *)(((unsigned long)memory + 256) & ~0x7fUL);
    101		*((char **)fpa - 1) = memory;
    102		cvmx_fpa_free(fpa, pool, 0);
    103		freed--;
    104	}
    105	return elements - freed;
    106}
    107
    108/**
    109 * cvm_oct_free_hw_memory - Free memory allocated by cvm_oct_fill_hw_memory
    110 * @pool:     FPA pool to free
    111 * @size:     Size of each buffer in the pool
    112 * @elements: Number of buffers that should be in the pool
    113 */
    114static void cvm_oct_free_hw_memory(int pool, int size, int elements)
    115{
    116	char *memory;
    117	char *fpa;
    118
    119	do {
    120		fpa = cvmx_fpa_alloc(pool);
    121		if (fpa) {
    122			elements--;
    123			fpa = (char *)phys_to_virt(cvmx_ptr_to_phys(fpa));
    124			memory = *((char **)fpa - 1);
    125			kfree(memory);
    126		}
    127	} while (fpa);
    128
    129	if (elements < 0)
    130		pr_warn("Freeing of pool %u had too many buffers (%d)\n",
    131			pool, elements);
    132	else if (elements > 0)
    133		pr_warn("Warning: Freeing of pool %u is missing %d buffers\n",
    134			pool, elements);
    135}
    136
    137int cvm_oct_mem_fill_fpa(int pool, int size, int elements)
    138{
    139	int freed;
    140
    141	if (pool == CVMX_FPA_PACKET_POOL)
    142		freed = cvm_oct_fill_hw_skbuff(pool, size, elements);
    143	else
    144		freed = cvm_oct_fill_hw_memory(pool, size, elements);
    145	return freed;
    146}
    147
    148void cvm_oct_mem_empty_fpa(int pool, int size, int elements)
    149{
    150	if (pool == CVMX_FPA_PACKET_POOL)
    151		cvm_oct_free_hw_skbuff(pool, size, elements);
    152	else
    153		cvm_oct_free_hw_memory(pool, size, elements);
    154}