blob: 096293dfdc1fdef80d58feb97c311d73e41ec604 [file] [log] [blame]
/*
* Copyright (C) 1991-2015, the Linux Kernel authors
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*
* This file consists of various bits of Linux code used in porting drivers to
* Akaros. */
#pragma once
#include <arch/types.h>
#include <ros/common.h>
#include <atomic.h>
#include <bitops.h>
#include <kthread.h>
#include <list.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <taskqueue.h>
#include <rbtree.h>
#define ETH_ALEN 6 /* Octets in one ethernet addr */
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
#define ETH_FCS_LEN 4 /* Octets in the FCS */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
uint16_t h_proto; /* packet type ID field */
} __attribute__((packed));
extern int ____ilog2_NaN;
/**
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
* @n - parameter
*
* constant-capable log of base 2 calculation
* - this can be used to initialise global variables from constant data, hence
* the massive ternary operator construction
*
* selects the appropriately-sized optimised version depending on sizeof(n)
*/
#define ilog2(n) \
( \
__builtin_constant_p(n) ? ( \
(n) < 1 ? ____ilog2_NaN : \
(n) & (1ULL << 63) ? 63 : \
(n) & (1ULL << 62) ? 62 : \
(n) & (1ULL << 61) ? 61 : \
(n) & (1ULL << 60) ? 60 : \
(n) & (1ULL << 59) ? 59 : \
(n) & (1ULL << 58) ? 58 : \
(n) & (1ULL << 57) ? 57 : \
(n) & (1ULL << 56) ? 56 : \
(n) & (1ULL << 55) ? 55 : \
(n) & (1ULL << 54) ? 54 : \
(n) & (1ULL << 53) ? 53 : \
(n) & (1ULL << 52) ? 52 : \
(n) & (1ULL << 51) ? 51 : \
(n) & (1ULL << 50) ? 50 : \
(n) & (1ULL << 49) ? 49 : \
(n) & (1ULL << 48) ? 48 : \
(n) & (1ULL << 47) ? 47 : \
(n) & (1ULL << 46) ? 46 : \
(n) & (1ULL << 45) ? 45 : \
(n) & (1ULL << 44) ? 44 : \
(n) & (1ULL << 43) ? 43 : \
(n) & (1ULL << 42) ? 42 : \
(n) & (1ULL << 41) ? 41 : \
(n) & (1ULL << 40) ? 40 : \
(n) & (1ULL << 39) ? 39 : \
(n) & (1ULL << 38) ? 38 : \
(n) & (1ULL << 37) ? 37 : \
(n) & (1ULL << 36) ? 36 : \
(n) & (1ULL << 35) ? 35 : \
(n) & (1ULL << 34) ? 34 : \
(n) & (1ULL << 33) ? 33 : \
(n) & (1ULL << 32) ? 32 : \
(n) & (1ULL << 31) ? 31 : \
(n) & (1ULL << 30) ? 30 : \
(n) & (1ULL << 29) ? 29 : \
(n) & (1ULL << 28) ? 28 : \
(n) & (1ULL << 27) ? 27 : \
(n) & (1ULL << 26) ? 26 : \
(n) & (1ULL << 25) ? 25 : \
(n) & (1ULL << 24) ? 24 : \
(n) & (1ULL << 23) ? 23 : \
(n) & (1ULL << 22) ? 22 : \
(n) & (1ULL << 21) ? 21 : \
(n) & (1ULL << 20) ? 20 : \
(n) & (1ULL << 19) ? 19 : \
(n) & (1ULL << 18) ? 18 : \
(n) & (1ULL << 17) ? 17 : \
(n) & (1ULL << 16) ? 16 : \
(n) & (1ULL << 15) ? 15 : \
(n) & (1ULL << 14) ? 14 : \
(n) & (1ULL << 13) ? 13 : \
(n) & (1ULL << 12) ? 12 : \
(n) & (1ULL << 11) ? 11 : \
(n) & (1ULL << 10) ? 10 : \
(n) & (1ULL << 9) ? 9 : \
(n) & (1ULL << 8) ? 8 : \
(n) & (1ULL << 7) ? 7 : \
(n) & (1ULL << 6) ? 6 : \
(n) & (1ULL << 5) ? 5 : \
(n) & (1ULL << 4) ? 4 : \
(n) & (1ULL << 3) ? 3 : \
(n) & (1ULL << 2) ? 2 : \
(n) & (1ULL << 1) ? 1 : \
(n) & (1ULL << 0) ? 0 : \
____ilog2_NaN \
) : \
LOG2_UP(n) \
)
#define sprintf(s, fmt, ...) ({ \
int ret = -1; \
if (__builtin_types_compatible_p(typeof(s), char[])) \
ret = snprintf(s, sizeof(s), fmt, ##__VA_ARGS__); \
else \
panic("Not implemented"); \
ret; \
})
#define printk_once(fmt, ...) ({ \
static bool __print_once; \
if (!__print_once) { \
__print_once = true; \
printk(fmt, ##__VA_ARGS__); \
} \
})
#define dev_warn(dev, format, ...) \
pr_warn(format, ## __VA_ARGS__)
#define dev_printk(level, dev, fmt, ...) \
printk(level fmt, ## __VA_ARGS__)
/* XXX This is not a tree. */
struct radix_tree_node {
struct list_head linkage;
unsigned long index;
void *item;
};
struct radix_tree_root {
struct list_head hlinks;
};
static inline void INIT_RADIX_TREE(struct radix_tree_root *rp, int mask)
{
INIT_LIST_HEAD(&rp->hlinks);
}
static inline int radix_tree_insert(struct radix_tree_root *root,
unsigned long index, void *item)
{
struct list_head *lp = root->hlinks.next;
struct radix_tree_node *p;
while (lp != &root->hlinks) {
p = (struct radix_tree_node *)lp;
if (p->index == index)
return -EEXIST;
lp = lp->next;
}
p = kmalloc(sizeof(*p), MEM_WAIT);
if (!p)
return -ENOMEM;
p->index = index;
p->item = item;
list_add(&p->linkage, &root->hlinks);
return 0;
}
static inline void *radix_tree_lookup(struct radix_tree_root *root,
unsigned long index)
{
struct list_head *lp = root->hlinks.next;
struct radix_tree_node *p;
while (lp != &root->hlinks) {
p = (struct radix_tree_node *)lp;
if (p->index == index)
return p->item;
lp = lp->next;
}
return NULL;
}
static inline void radix_tree_delete(struct radix_tree_root *root,
unsigned long index)
{
struct list_head *lp = root->hlinks.next;
struct radix_tree_node *p;
while (lp != &root->hlinks) {
p = (struct radix_tree_node *)lp;
if (p->index == index) {
list_del(lp);
return;
}
lp = lp->next;
}
panic("Node not found\n");
}
#define INIT_DEFERRABLE_WORK(_work, _func) \
INIT_DELAYED_WORK(_work, _func) /* XXX */
struct tasklet_struct {
uint32_t state;
void (*func)(unsigned long);
unsigned long data;
};
static void __tasklet_wrapper(uint32_t srcid, long a0, long a1, long a2)
{
struct tasklet_struct *t = (struct tasklet_struct *)a0;
if (atomic_cas_u32(&t->state, 1, 0))
t->func(t->data);
}
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (atomic_cas_u32(&t->state, 0, 1)) {
send_kernel_message(core_id(), __tasklet_wrapper, (long)t, 0, 0,
KMSG_ROUTINE);
}
}
static inline void tasklet_disable(struct tasklet_struct *t)
{
panic("tasklet_disable unimplemented");
// XXX t->state = 2
}
static inline void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data)
{
t->state = 0;
t->func = func;
t->data = data;
}
struct completion {
unsigned int done;
};
static inline void init_completion(struct completion *x)
{
x->done = 0;
}
static inline void reinit_completion(struct completion *x)
{
printd("Core %d: reinit_completion %p\n", core_id(), x);
x->done = 0;
}
static inline void complete(struct completion *x)
{
printd("Core %d: complete %p\n", core_id(), x);
x->done = 1;
wmb();
}
static inline void wait_for_completion(struct completion *x)
{
while (!x->done)
cmb();
}
static inline unsigned long wait_for_completion_timeout(struct completion *x,
unsigned long timeout)
{
printd("Core %d: wait_for_completion_timeout %p\n", core_id(), x);
while (!x->done) {
if (timeout) {
kthread_usleep(1000);
timeout--;
cmb();
} else {
break;
}
}
return timeout;
}
#define jiffies tsc2msec(read_tsc())
static inline unsigned long round_jiffies(unsigned long j)
{
return j / 1000 * 1000;
}
static inline unsigned long round_jiffies_relative(unsigned long j)
{
return round_jiffies(j);
}
struct timer_list {
spinlock_t lock;
bool scheduled;
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
};
static inline void init_timer(struct timer_list *timer)
{
spinlock_init_irqsave(&timer->lock);
timer->scheduled = false;
timer->expires = -1;
timer->function = 0;
timer->data = 0;
}
static inline void setup_timer(struct timer_list *timer,
void (*func)(unsigned long), unsigned long data)
{
init_timer(timer);
timer->function = func;
timer->data = data;
}
static void __timer_wrapper(uint32_t srcid, long a0, long a1, long a2)
{
struct timer_list *timer = (struct timer_list *)a0;
unsigned long expires, now_j;
spin_lock_irqsave(&timer->lock);
expires = timer->expires;
timer->scheduled = false;
spin_unlock_irqsave(&timer->lock);
now_j = jiffies;
if (expires > now_j)
kthread_usleep((expires - now_j) * 1000);
timer->function(timer->data);
}
static inline void add_timer(struct timer_list *timer)
{
timer->scheduled = true;
send_kernel_message(core_id(), __timer_wrapper, (long)timer, 0, 0,
KMSG_ROUTINE);
}
static inline void mod_timer(struct timer_list *timer, unsigned long expires)
{
spin_lock_irqsave(&timer->lock);
timer->expires = expires;
if (timer->scheduled) {
spin_unlock_irqsave(&timer->lock);
return;
}
timer->scheduled = true;
spin_unlock_irqsave(&timer->lock);
send_kernel_message(core_id(), __timer_wrapper, (long)timer, 0, 0,
KMSG_ROUTINE);
}
static inline void del_timer_sync(struct timer_list *timer)
{
panic("del_timer_sync unimplemented");
}
static inline void setup_timer_on_stack(struct timer_list *timer,
void (*func)(unsigned long),
unsigned long data)
{
setup_timer(timer, func, data);
}
static inline void destroy_timer_on_stack(struct timer_list *timer)
{
}
/* TODO: This is nasty (all of the timer stuff). We don't know if a timer
* actually finished or not. Someone could mod_timer repeatedly and have the
* same handler running concurrently. */
static inline bool timer_pending(struct timer_list *timer)
{
return timer->expires >= jiffies;
}
struct cpu_rmap {
};
extern unsigned long saved_max_pfn;
struct device_attribute {
};
#define DEFINE_MUTEX(mutexname) \
qlock_t mutexname = QLOCK_INITIALIZER(mutexname);
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
/*
* Check at compile time that 'function' is a certain type, or is a pointer
* to that type (needs to use typedef for the function type.)
*/
#define typecheck_fn(type,function) \
({ typeof(type) __tmp = function; \
(void)__tmp; \
})
#if BITS_PER_LONG > 32
#define NET_SKBUFF_DATA_USES_OFFSET 1
#endif
#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif
typedef struct skb_frag_struct skb_frag_t;
struct skb_frag_struct {
struct {
struct page *p;
} page;
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
uint32_t page_offset;
uint32_t size;
#else
uint16_t page_offset;
uint16_t size;
#endif
};
/* asm-generic/getorder.h */
/*
* Runtime evaluation of get_order()
*/
static inline __attribute_const__
int __get_order(unsigned long size)
{
int order;
size--;
size >>= PAGE_SHIFT;
#if BITS_PER_LONG == 32
order = fls(size);
#else
order = fls64(size);
#endif
return order;
}
/**
* get_order - Determine the allocation order of a memory size
* @size: The size for which to get the order
*
* Determine the allocation order of a particular sized block of memory. This
* is on a logarithmic scale, where:
*
* 0 -> 2^0 * PAGE_SIZE and below
* 1 -> 2^1 * PAGE_SIZE to 2^0 * PAGE_SIZE + 1
* 2 -> 2^2 * PAGE_SIZE to 2^1 * PAGE_SIZE + 1
* 3 -> 2^3 * PAGE_SIZE to 2^2 * PAGE_SIZE + 1
* 4 -> 2^4 * PAGE_SIZE to 2^3 * PAGE_SIZE + 1
* ...
*
* The order returned is used to find the smallest allocation granule required
* to hold an object of the specified size.
*
* The result is undefined if the size is 0.
*
* This function may be used to initialise variables with compile time
* evaluations of constants.
*/
#define get_order(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 0UL) ? BITS_PER_LONG - PAGE_SHIFT : \
(((n) < (1UL << PAGE_SHIFT)) ? 0 : \
ilog2((n) - 1) - PAGE_SHIFT + 1) \
) : \
__get_order(n) \
)
/* asm-generic/io.h */
static inline void __raw_writeq(uint64_t value, volatile void *addr)
{
*(volatile uint64_t *)addr = value;
}
/* linux/export.h */
#define EXPORT_SYMBOL_GPL(...)
/* linux/gfp.h */
/* These are all set to 0. Silently passing flags to Akaros's memory allocator
* is dangerous - we could be turning on some Akaros feature that shares the
* same bit.
*
* Similarly, note that some Linux flags (__GFP_ZERO) is not here. Those flags
* need to be dealt with. Silently ignoring them will cause errors. */
#define __GFP_DMA 0
#define __GFP_HIGHMEM 0
#define __GFP_DMA32 0
#define __GFP_MOVABLE 0
#define __GFP_WAIT 0
#define __GFP_HIGH 0
#define __GFP_IO 0
#define __GFP_FS 0
#define __GFP_COLD 0
#define __GFP_NOWARN 0
#define __GFP_REPEAT 0
#define __GFP_NOFAIL 0
#define __GFP_NORETRY 0
#define __GFP_MEMALLOC 0
#define __GFP_COMP 0
#define __GFP_NOMEMALLOC 0
#define __GFP_HARDWALL 0
#define __GFP_THISNODE 0
#define __GFP_RECLAIMABLE 0
#define __GFP_NOACCOUNT 0
#define __GFP_NOTRACK 0
#define __GFP_NO_KSWAPD 0
#define __GFP_OTHER_NODE 0
#define __GFP_WRITE 0
#define GFP_HIGHUSER 0
/* linux/kernel.h */
#define min3(x, y, z) MIN((typeof(x))MIN(x, y), z)
#define max3(x, y, z) MAX((typeof(x))MAX(x, y), z)
typedef unsigned int pci_channel_state_t;
enum pci_channel_state {
/* I/O channel is in normal state */
pci_channel_io_normal = 1,
/* I/O to channel is blocked */
pci_channel_io_frozen = 2,
/* PCI card is dead */
pci_channel_io_perm_failure = 3,
};
typedef unsigned int pci_ers_result_t;
enum pci_ers_result {
/* no result/none/not supported in device driver */
PCI_ERS_RESULT_NONE = 1,
/* Device driver can recover without slot reset */
PCI_ERS_RESULT_CAN_RECOVER = 2,
/* Device driver wants slot to be reset. */
PCI_ERS_RESULT_NEED_RESET = 3,
/* Device has completely failed, is unrecoverable */
PCI_ERS_RESULT_DISCONNECT = 4,
/* Device driver is fully recovered and operational */
PCI_ERS_RESULT_RECOVERED = 5,
/* No AER capabilities registered for the driver */
PCI_ERS_RESULT_NO_AER_DRIVER = 6,
};
/* These values come from the PCI Express Spec */
enum pcie_link_width {
PCIE_LNK_WIDTH_RESRV = 0x00,
PCIE_LNK_X1 = 0x01,
PCIE_LNK_X2 = 0x02,
PCIE_LNK_X4 = 0x04,
PCIE_LNK_X8 = 0x08,
PCIE_LNK_X12 = 0x0C,
PCIE_LNK_X16 = 0x10,
PCIE_LNK_X32 = 0x20,
PCIE_LNK_WIDTH_UNKNOWN = 0xFF,
};
/* Based on the PCI Hotplug Spec, but some values are made up by us */
enum pci_bus_speed {
PCI_SPEED_33MHz = 0x00,
PCI_SPEED_66MHz = 0x01,
PCI_SPEED_66MHz_PCIX = 0x02,
PCI_SPEED_100MHz_PCIX = 0x03,
PCI_SPEED_133MHz_PCIX = 0x04,
PCI_SPEED_66MHz_PCIX_ECC = 0x05,
PCI_SPEED_100MHz_PCIX_ECC = 0x06,
PCI_SPEED_133MHz_PCIX_ECC = 0x07,
PCI_SPEED_66MHz_PCIX_266 = 0x09,
PCI_SPEED_100MHz_PCIX_266 = 0x0a,
PCI_SPEED_133MHz_PCIX_266 = 0x0b,
AGP_UNKNOWN = 0x0c,
AGP_1X = 0x0d,
AGP_2X = 0x0e,
AGP_4X = 0x0f,
AGP_8X = 0x10,
PCI_SPEED_66MHz_PCIX_533 = 0x11,
PCI_SPEED_100MHz_PCIX_533 = 0x12,
PCI_SPEED_133MHz_PCIX_533 = 0x13,
PCIE_SPEED_2_5GT = 0x14,
PCIE_SPEED_5_0GT = 0x15,
PCIE_SPEED_8_0GT = 0x16,
PCI_SPEED_UNKNOWN = 0xff,
};
/* linux/slab.h */
#define kzalloc_node(...) (0 /* XXX */)
#define __cpu_to_le32(x) (x)
#define __le32_to_cpu(x) (x)
#define swab32 __builtin_bswap32
#define swab16 __builtin_bswap16
#define cond_resched() { /* XXX */ \
volatile int i = 100000; \
/* printk("%s:%d %s cond_resched\n", __FILE__, __LINE__, __FUNCTION__); */ \
while (i--); \
}
#define iounmap(...) (0 /* XXX */)
typedef uint64_t phys_addr_t;
typedef phys_addr_t resource_size_t;
struct dma_pool *dma_pool_create(const char *name, void *dev,
size_t size, size_t align, size_t allocation);
void dma_pool_destroy(struct dma_pool *pool);
void *dma_pool_alloc(struct dma_pool *pool, int mem_flags, dma_addr_t *handle);
void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
#define pci_pool dma_pool
#define pci_pool_create(name, pdev, size, align, allocation) \
dma_pool_create(name, pdev, size, align, allocation)
#define pci_pool_destroy(pool) dma_pool_destroy(pool)
#define pci_pool_alloc(pool, flags, handle) dma_pool_alloc(pool, flags, handle)
#define pci_pool_free(pool, vaddr, addr) dma_pool_free(pool, vaddr, addr)
#define __user
#define __bitwise
struct vm_area_struct {
};
/* uapi/rdma/ib_user_mad.h */
#define IB_USER_MAD_USER_RMPP 1
#define be16_to_cpup(p) be16_to_cpu(*(uint16_t *)(p))
#define be32_to_cpup(p) be32_to_cpu(*(uint32_t *)(p))
/* access_ok.h */
static inline uint16_t get_unaligned_le16(const void *p)
{
return le16_to_cpu(*(uint16_t *)p);
}
static inline uint32_t get_unaligned_le32(const void *p)
{
return le32_to_cpu(*(uint32_t *)p);
}
static inline uint64_t get_unaligned_le64(const void *p)
{
return le64_to_cpu(*(uint64_t *)p);
}
static inline void put_unaligned_le16(uint16_t val, void *p)
{
*((uint16_t *)p) = cpu_to_le16(val);
}
static inline void put_unaligned_le32(uint32_t val, void *p)
{
*((uint32_t *)p) = cpu_to_le32(val);
}
static inline void put_unaligned_le64(uint64_t val, void *p)
{
*((uint64_t *)p) = cpu_to_le64(val);
}
extern void __bad_unaligned_access_size(void);
#define __get_unaligned_le(ptr) ({ \
__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \
__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \
__bad_unaligned_access_size())))); \
})
#define __put_unaligned_le(val, ptr) ({ \
void *__gu_p = (ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
*(uint8_t *)__gu_p = (uint8_t)(val); \
break; \
case 2: \
put_unaligned_le16((uint16_t)(val), __gu_p); \
break; \
case 4: \
put_unaligned_le32((uint32_t)(val), __gu_p); \
break; \
case 8: \
put_unaligned_le64((uint64_t)(val), __gu_p); \
break; \
default: \
__bad_unaligned_access_size(); \
break; \
} \
(void)0; })
#define get_unaligned __get_unaligned_le
#define put_unaligned __put_unaligned_le
#define vmalloc_node(...) (0 /* XXX */)
/* needed by icm.c: */
#define kmalloc_node(size, flags, node) kmalloc(size, flags)
#define alloc_pages_node(nid, gfp_mask, order) 0
struct scatterlist {
unsigned long page_link;
unsigned int offset;
unsigned int length;
dma_addr_t dma_address;
};
#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_is_last(sg) ((sg)->page_link & 0x02)
#define sg_chain_ptr(sg) ((struct scatterlist *) ((sg)->page_link & ~0x03))
static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
{
unsigned long page_link = sg->page_link & 0x3;
sg->page_link = page_link | (unsigned long) page;
}
/**
* sg_set_page - Set sg entry to point at given page
* @sg: SG entry
* @page: The page
* @len: Length of data
* @offset: Offset into page
*
* Description:
* Use this function to set an sg entry pointing at a page, never assign
* the page directly. We encode sg table information in the lower bits
* of the page pointer. See sg_page() for looking up the page belonging
* to an sg entry.
*
**/
static inline void sg_set_page(struct scatterlist *sg, struct page *page,
unsigned int len, unsigned int offset)
{
sg_assign_page(sg, page);
sg->offset = offset;
sg->length = len;
}
static inline struct page *sg_page(struct scatterlist *sg)
{
return (struct page *)(sg->page_link & ~0x3);
}
static inline void sg_set_buf(struct scatterlist *sg, void *buf,
unsigned int buflen)
{
sg_set_page(sg, kva2page(buf), buflen, PGOFF(buf));
}
#define for_each_sg(sglist, sg, nr, __i) \
for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
static inline void sg_mark_end(struct scatterlist *sg)
{
/*
* Set termination bit, clear potential chain bit
*/
sg->page_link |= 0x02;
sg->page_link &= ~0x01;
}
void sg_init_table(struct scatterlist *, unsigned int);
struct scatterlist *sg_next(struct scatterlist *);
static inline int nontranslate_map_sg(void *dev, struct scatterlist *sglist,
int nelems, int dir)
{
int i;
struct scatterlist *sg;
for_each_sg(sglist, sg, nelems, i) {
sg_dma_address(sg) = page2pa(sg_page(sg)) + sg->offset;
sg_dma_len(sg) = sg->length;
}
return nelems;
}
static inline int dma_map_sg(void *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
return nontranslate_map_sg(dev, sg, nents, dir);
}
static inline void dma_unmap_sg(void *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
/* TODO nop */
}
struct dma_attrs {
};
#define dma_map_sg_attrs(d, s, n, r, a) dma_map_sg(d, s, n, r)
#define dma_unmap_sg_attrs(d, s, n, r, a) dma_unmap_sg(d, s, n, r)
static inline int pci_map_sg(struct pci_device *pdev, struct scatterlist *sg,
int nents, int direction)
{
return dma_map_sg(NULL, sg, nents, (enum dma_data_direction)direction);
}
static inline void pci_unmap_sg(struct pci_device *pdev, struct scatterlist *sg,
int nents, int direction)
{
dma_unmap_sg(NULL, sg, nents, (enum dma_data_direction)direction);
}
/* TODO: get this in an arch-dependent manner. On x86, be careful of adjacent
* cacheline prefetching. */
#define cache_line_size() 64
static inline void *lowmem_page_address(struct page *page)
{
/* XXX not sure about this */
return page2kva(page);
}
#define page_address(page) lowmem_page_address(page)
#define netif_get_num_default_rss_queues() (8 /* FIXME */)
static inline void netdev_rss_key_fill(void *buffer, size_t len)
{
/* XXX */
memset(buffer, 0, len);
}
/* Hacked up version of Linux's. Assuming reg's are implemented and
* read_config never fails. */
static int pcie_capability_read_dword(struct pci_device *dev, int pos,
uint32_t *val)
{
uint32_t pcie_cap;
*val = 0;
if (pos & 3)
return -EINVAL;
if (pci_find_cap(dev, PCI_CAP_ID_EXP, &pcie_cap))
return -EINVAL;
pci_read_config_dword(dev, pcie_cap + pos, val);
return 0;
}
static inline const char *pci_name(const struct pci_device *pdev)
{
return pdev->name;
}
#define dev_name(dev) ("ether0" /* XXX */)
#define pci_request_regions(...) (0 /* XXX */)
#define pci_save_state(...) (0 /* XXX */)
#define pci_set_consistent_dma_mask(...) (0 /* XXX */)
#define pci_set_dma_mask(...) (0 /* XXX */)
#define pci_channel_offline(...) (0 /* XXX */)
#define dma_set_max_seg_size(...) (0 /* XXX */)
#define dma_get_cache_alignment(...) (1 /* XXX */)
#define dev_to_node(...) (0 /* XXX */)
#define set_dev_node(...) /* TODO */
#define num_online_cpus() (1U /* XXX */)
#define cpu_to_node(cpu) ((void)(cpu),0)
#define pcie_get_minimum_link(dev, speed, width) ({ \
*(speed) = PCIE_SPEED_8_0GT; \
*(width) = PCIE_LNK_X8; \
0; })
static inline void get_random_bytes(char *buf, int nbytes)
{
// FIXME this is not random
for (int i = 0; i < nbytes; i++)
buf[i] = i;
}
/* linux/moduleparam.h */
#define module_param_array(...)
#define ATOMIC_INIT(i) (i)
/* linux/pci_ids.h */
#define PCI_VENDOR_ID_MELLANOX 0x15b3
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};
#define pci_pcie_cap(...) (0 /* TODO use pci_device->caps ? */)
#define NET_IP_ALIGN 2
#define ____cacheline_aligned_in_smp
typedef struct cpumask { } cpumask_t;
typedef struct cpumask cpumask_var_t[1];
#define cpumask_set_cpu(...) (0 /* TODO */)
#define zalloc_cpumask_var(...) (1 /* TODO */)
#define cpumask_local_spread(...) (0 /* TODO */)
struct notifier_block {
};
struct hwtstamp_config {
int flags;
int tx_type;
int rx_filter;
};
struct skb_shared_hwtstamps {
};
#define VLAN_N_VID 4096
/* linux/if_vlan.h */
#define VLAN_PRIO_SHIFT 13
/* linux/pci.h */
#define PCI_DMA_BIDIRECTIONAL 0
#define PCI_DMA_TODEVICE 1
#define PCI_DMA_FROMDEVICE 2
#define PCI_DMA_NONE 3
/* uapi/linux/net_tstamp.h */
enum hwtstamp_tx_types {
HWTSTAMP_TX_OFF,
HWTSTAMP_TX_ON,
HWTSTAMP_TX_ONESTEP_SYNC,
};
/* linux/skbuff.h */
enum {
SKBTX_HW_TSTAMP = 1 << 0,
SKBTX_SW_TSTAMP = 1 << 1,
SKBTX_IN_PROGRESS = 1 << 2,
SKBTX_DEV_ZEROCOPY = 1 << 3,
SKBTX_WIFI_STATUS = 1 << 4,
SKBTX_SHARED_FRAG = 1 << 5,
SKBTX_SCHED_TSTAMP = 1 << 6,
SKBTX_ACK_TSTAMP = 1 << 7,
};
#define CHECKSUM_NONE 0
#define CHECKSUM_UNNECESSARY 1
#define CHECKSUM_COMPLETE 2
#define CHECKSUM_PARTIAL 3
#define IPPROTO_IP 0
#define IPPROTO_ICMP 1
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_GRE 47
#define IPPROTO_RAW 255
#define IFNAMSIZ 16
#define MAX_ADDR_LEN 32
/* linux/mmzone.h */
#define PAGE_ALLOC_COSTLY_ORDER 3
/* linux/cache.h */
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES
/* linux/if_vlan.h */
#define VLAN_HLEN 4
#define NETIF_F_RXFCS 0
#define irq_to_desc(irq) ({ /* I_AM_HERE; */ NULL; /* TODO */ })
static inline void eth_broadcast_addr(uint8_t *addr)
{
memset(addr, 0xff, Eaddrlen);
}
#define BOND_LINK_FAIL 1
#define BOND_LINK_UP 2
#define BOND_MODE_8023AD 1
#define BOND_MODE_ACTIVEBACKUP 2
#define BOND_MODE_XOR 3
#define BOND_STATE_BACKUP 0
#define eth_validate_addr 0
#define HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ 1
#define HWTSTAMP_FILTER_PTP_V1_L4_EVENT 2
#define HWTSTAMP_FILTER_PTP_V1_L4_SYNC 3
#define HWTSTAMP_FILTER_PTP_V2_DELAY_REQ 4
#define HWTSTAMP_FILTER_PTP_V2_EVENT 5
#define HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ 6
#define HWTSTAMP_FILTER_PTP_V2_L2_EVENT 7
#define HWTSTAMP_FILTER_PTP_V2_L2_SYNC 8
#define HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ 9
#define HWTSTAMP_FILTER_PTP_V2_L4_EVENT 10
#define HWTSTAMP_FILTER_PTP_V2_L4_SYNC 11
#define HWTSTAMP_FILTER_PTP_V2_SYNC 12
#define HWTSTAMP_FILTER_SOME 13
#define HWTSTAMP_FILTER_ALL 14
#define HWTSTAMP_FILTER_NONE 15
#define IFF_ALLMULTI 1
#define IFF_PROMISC 2
#define IFF_UNICAST_FLT 3
#define NETDEV_BONDING_INFO 0
#define NETIF_F_HW_VLAN_CTAG_FILTER 1
#define NETIF_F_NTUPLE 2
#define NETIF_F_RXALL 3
#define NOTIFY_DONE 0
#define SIOCGHWTSTAMP 1
#define SIOCSHWTSTAMP 2
/* Misc crap (from rcu/torture.c), which might be unused. */
#define DEFINE_SPINLOCK(x) spinlock_t x = SPINLOCK_INITIALIZER_IRQSAVE
#define DEFINE_PER_CPU DEFINE_PERCPU
#define per_cpu(var, i) _PERCPU_VAR(var, i)
/* Don't macro per_cpu_ptr, since its usage differs for static and dynamic */
#define for_each_possible_cpu(x) for_each_core(x)
#define for_each_online_cpu(x) for_each_core(x)
#define alloc_percpu_gfp(x, f) percpu_alloc(x, f)
#define free_percpu(x) percpu_free(x)
#define __this_cpu_read(x) PERCPU_VAR(x)
#define __this_cpu_add(x, v) ({ PERCPU_VAR(x) + (v); })
#define __this_cpu_sub(x, v) __this_cpu_add(x, -(v))
#define __this_cpu_inc(x) __this_cpu_add(x, 1)
#define this_cpu_read __this_cpu_read
#define this_cpu_add __this_cpu_add
#define this_cpu_sub __this_cpu_sub
#define this_cpu_inc __this_cpu_inc
typedef atomic_t atomic_long_t;
#define atomic_long_inc atomic_inc
#define atomic_long_read atomic_read
#define __read_mostly
static inline void local_irq_disable(void)
{
disable_irq();
}
static inline void local_irq_enable(void)
{
enable_irq();
}
static inline void preempt_disable(void)
{
}
static inline void preempt_enable(void)
{
}
static inline void preempt_schedule(void)
{
}