From 492a0a7ac95ab534481731ede263adabeab83803 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 1 Nov 2017 15:49:47 +0100 Subject: [PATCH 01/14] dde_linux: wandboard ethernet driver Fixes #2665 --- repos/dde_linux/fec.list | 54 + .../lib/import/import-fec_nic_include.mk | 5 + repos/dde_linux/lib/mk/fec_nic_include.mk | 35 + repos/dde_linux/patches/fec_skbuff_cast.patch | 13 + repos/dde_linux/ports/dde_linux.hash | 2 +- repos/dde_linux/ports/dde_linux.port | 16 +- .../src/drivers/nic/fec/component.cc | 180 ++ .../dde_linux/src/drivers/nic/fec/component.h | 75 + repos/dde_linux/src/drivers/nic/fec/dummy.c | 368 +++++ .../dde_linux/src/drivers/nic/fec/lx_emul.cc | 910 ++++++++++ repos/dde_linux/src/drivers/nic/fec/lx_emul.h | 1461 +++++++++++++++++ repos/dde_linux/src/drivers/nic/fec/lxc.c | 65 + repos/dde_linux/src/drivers/nic/fec/lxc.h | 40 + repos/dde_linux/src/drivers/nic/fec/main.cc | 111 ++ .../dde_linux/src/drivers/nic/fec/platform.cc | 39 + repos/dde_linux/src/drivers/nic/fec/target.mk | 49 + 16 files changed, 3421 insertions(+), 2 deletions(-) create mode 100644 repos/dde_linux/fec.list create mode 100644 repos/dde_linux/lib/import/import-fec_nic_include.mk create mode 100644 repos/dde_linux/lib/mk/fec_nic_include.mk create mode 100644 repos/dde_linux/patches/fec_skbuff_cast.patch create mode 100644 repos/dde_linux/src/drivers/nic/fec/component.cc create mode 100644 repos/dde_linux/src/drivers/nic/fec/component.h create mode 100644 repos/dde_linux/src/drivers/nic/fec/dummy.c create mode 100644 repos/dde_linux/src/drivers/nic/fec/lx_emul.cc create mode 100644 repos/dde_linux/src/drivers/nic/fec/lx_emul.h create mode 100644 repos/dde_linux/src/drivers/nic/fec/lxc.c create mode 100644 repos/dde_linux/src/drivers/nic/fec/lxc.h create mode 100644 repos/dde_linux/src/drivers/nic/fec/main.cc create mode 100644 repos/dde_linux/src/drivers/nic/fec/platform.cc create mode 100644 repos/dde_linux/src/drivers/nic/fec/target.mk diff --git a/repos/dde_linux/fec.list b/repos/dde_linux/fec.list new file mode 100644 index 00000000000..90e72bd7206 --- /dev/null +++ b/repos/dde_linux/fec.list @@ -0,0 +1,54 @@ +linux-x.x.x/drivers/net/ethernet/freescale/fec.h +linux-x.x.x/drivers/net/ethernet/freescale/fec_main.c +linux-x.x.x/drivers/net/ethernet/freescale/fec_ptp.c +linux-x.x.x/drivers/net/phy/mdio_bus.c +linux-x.x.x/drivers/net/phy/phy_device.c +linux-x.x.x/drivers/net/phy/phy.c +linux-x.x.x/net/core/skbuff.c +linux-x.x.x/net/ethernet/eth.c +linux-x.x.x/include/asm-generic/atomic64.h +linux-x.x.x/include/asm-generic/bitops/non-atomic.h +linux-x.x.x/include/asm-generic/bitops/__ffs.h +linux-x.x.x/include/asm-generic/bitops/__fls.h +linux-x.x.x/include/asm-generic/bitops/ffs.h +linux-x.x.x/include/asm-generic/bitops/fls.h +linux-x.x.x/include/asm-generic/bitops/fls64.h +linux-x.x.x/include/linux/errqueue.h +linux-x.x.x/include/linux/fec.h +linux-x.x.x/include/linux/if_ether.h +linux-x.x.x/include/linux/list.h +linux-x.x.x/include/linux/list_nulls.h +linux-x.x.x/include/linux/log2.h +linux-x.x.x/include/linux/mii.h +linux-x.x.x/include/linux/mod_devicetable.h +linux-x.x.x/include/linux/net.h +linux-x.x.x/include/linux/netdev_features.h +linux-x.x.x/include/linux/phy.h +linux-x.x.x/include/linux/ptp_clock_kernel.h +linux-x.x.x/include/linux/rculist.h +linux-x.x.x/include/linux/rculist_nulls.h +linux-x.x.x/include/linux/skbuff.h +linux-x.x.x/include/linux/socket.h +linux-x.x.x/include/linux/timecounter.h +linux-x.x.x/include/net/dst.h +linux-x.x.x/include/net/dst_ops.h +linux-x.x.x/include/net/neighbour.h +linux-x.x.x/include/net/sock.h +linux-x.x.x/include/net/tcp_states.h +linux-x.x.x/include/net/tso.h +linux-x.x.x/include/uapi/linux/byteorder/little_endian.h +linux-x.x.x/include/uapi/linux/errqueue.h +linux-x.x.x/include/uapi/linux/ethtool.h +linux-x.x.x/include/uapi/linux/if.h +linux-x.x.x/include/uapi/linux/if_ether.h +linux-x.x.x/include/uapi/linux/if_packet.h +linux-x.x.x/include/uapi/linux/mdio.h +linux-x.x.x/include/uapi/linux/mii.h +linux-x.x.x/include/uapi/linux/net.h +linux-x.x.x/include/uapi/linux/net_tstamp.h +linux-x.x.x/include/uapi/linux/neighbour.h +linux-x.x.x/include/uapi/linux/ptp_clock.h +linux-x.x.x/include/uapi/linux/rtnetlink.h +linux-x.x.x/include/uapi/linux/socket.h +linux-x.x.x/include/uapi/linux/sockios.h +linux-x.x.x/include/uapi/linux/swab.h diff --git a/repos/dde_linux/lib/import/import-fec_nic_include.mk b/repos/dde_linux/lib/import/import-fec_nic_include.mk new file mode 100644 index 00000000000..7c410190c45 --- /dev/null +++ b/repos/dde_linux/lib/import/import-fec_nic_include.mk @@ -0,0 +1,5 @@ +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/nic/fec +SRC_DIR := $(REP_DIR)/src/drivers/nic/fec +INC_DIR += $(LX_CONTRIB_DIR)/drivers/net/ethernet/freescale +INC_DIR += $(LIB_CACHE_DIR)/fec_nic_include/include/include/include +CC_OPT += -U__linux__ -D__KERNEL__ diff --git a/repos/dde_linux/lib/mk/fec_nic_include.mk b/repos/dde_linux/lib/mk/fec_nic_include.mk new file mode 100644 index 00000000000..e620915a9af --- /dev/null +++ b/repos/dde_linux/lib/mk/fec_nic_include.mk @@ -0,0 +1,35 @@ +# +# Pseudo library to generate a symlink for each header file included by the +# contrib code. Each symlink points to the same 'lx_emul.h' file, which +# provides our emulation of the Linux kernel API. +# + +ifeq ($(called_from_lib_mk),yes) + +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/nic/fec +LX_EMUL_H := $(REP_DIR)/src/drivers/nic/fec/lx_emul.h + +# +# Determine the header files included by the contrib code. For each +# of these header files we create a symlink to 'lx_emul.h'. +# +SCAN_DIRS := $(addprefix $(LX_CONTRIB_DIR)/include/, asm-generic linux net uapi) \ + $(addprefix $(LX_CONTRIB_DIR)/, drivers net) +GEN_INCLUDES := $(shell grep -rIh "^\#include .*" $(SCAN_DIRS) |\ + sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\ + sort | uniq) + +# +# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use +# three level include hierarchy +# +GEN_INC := $(shell pwd)/include/include/include +GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES)) + +all: $(GEN_INCLUDES) + +$(GEN_INCLUDES): + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)ln -sf $(LX_EMUL_H) $@ + +endif diff --git a/repos/dde_linux/patches/fec_skbuff_cast.patch b/repos/dde_linux/patches/fec_skbuff_cast.patch new file mode 100644 index 00000000000..5e63596db9c --- /dev/null +++ b/repos/dde_linux/patches/fec_skbuff_cast.patch @@ -0,0 +1,13 @@ +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 9147f9f..c63ee5c 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -3281,7 +3281,7 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, + + if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { + __skb_checksum_complete(skb); +- skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); ++ skb_postpull_rcsum(skb, skb->data, (unsigned char*)ptr - skb->data); + } + + delta = remcsum_adjust(ptr, skb->csum, start, offset); diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index 2bfaac92e68..f9231242fb5 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -4956fbfec9787772b2679e900a38f8701db8205a +82b2f79a8ecbbfeb42de534b776c6b348573bd60 diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index f64aa55d0dd..0453f60ae34 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -1,7 +1,7 @@ LICENSE := GPLv2 VERSION := 2 DOWNLOADS := dwc_otg.git usb.archive intel_fb.archive lxip.archive \ - wifi.archive libnl.archive wpa_supplicant.archive \ + wifi.archive fec.archive libnl.archive wpa_supplicant.archive \ fw_6000.archive fw_6205a.archive fw_6205b.archive fw_7260.archive \ fw_7265.archive fw_8260.archive @@ -79,6 +79,16 @@ DIR(lxip) := $(SRC_DIR_LXIP) TAR_OPT(lxip) := --strip-components=1 --files-from $(REP_DIR)/lxip.list HASH_INPUT += $(REP_DIR)/lxip.list +# +# Freescale Ethernet controller +# +SRC_DIR_FEC := src/drivers/nic/fec +VERSION_FEC := 4.4.3 +URL(fec) := https://www.kernel.org/pub/linux/kernel/v4.x/linux-$(VERSION_FEC).tar.xz +SHA(fec) := 336d66925a15ce9077cbf2c38acbdc6c2644e33f +DIR(fec) := $(SRC_DIR_FEC) +TAR_OPT(fec) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_FEC)/g' $(REP_DIR)/fec.list) +HASH_INPUT += $(REP_DIR)/fec.list # # libnl sources @@ -161,6 +171,7 @@ PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/lxip*.pat PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/intel*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/usb*.patch))) PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/intel*.patch))) +PATCHES += $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/fec_*.patch))) #IP stack LXIP_OPT = -p1 -d$(SRC_DIR_LXIP) @@ -194,4 +205,7 @@ PATCH_OPT(patches/usb_usbnet.patch) := $(USB_OPT) # INTEL FB PATCH_OPT(patches/intel_fb_export_api.patch) := -p1 -d$(SRC_DIR_INTEL_FB) +# Freescale NIC +PATCH_OPT(patches/fec_skbuff_cast.patch) := -p1 -d$(SRC_DIR_FEC) + # vi: set ft=make : diff --git a/repos/dde_linux/src/drivers/nic/fec/component.cc b/repos/dde_linux/src/drivers/nic/fec/component.cc new file mode 100644 index 00000000000..13e404e979a --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/component.cc @@ -0,0 +1,180 @@ +/* + * \brief Freescale ethernet driver component + * \author Stefan Kalkowski + * \date 2017-11-01 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +extern "C" { +#include +}; + +void Session_component::_run_rx_task(void * args) +{ + Rx_data *data = static_cast(args); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + int ret = 0; + struct napi_struct * n = data->napi; + + for (;;) { + + /* This NAPI_STATE_SCHED test is for avoiding a race + * with netpoll's poll_napi(). Only the entity which + * obtains the lock and sees NAPI_STATE_SCHED set will + * actually make the ->poll() call. Therefore we avoid + * accidentally calling ->poll() when NAPI is not scheduled. + */ + if (!test_bit(NAPI_STATE_SCHED, &n->state)) break; + + int weight = n->weight; + int work = n->poll(n, weight); + ret += work; + + if (work < weight) break; + + Genode::warning("Too much incoming traffic, we should schedule RX more intelligent"); + } + } +} + + +void Session_component::_run_tx_task(void * args) +{ + Tx_data *data = static_cast(args); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + net_device * ndev = data->ndev; + struct sk_buff * skb = data->skb; + + ndev->netdev_ops->ndo_start_xmit(skb, ndev); + } +} + + +bool Session_component::_send() +{ + using namespace Genode; + + /* + * We must not be called from another task, just from the + * packet stream dispatcher. + */ + if (Lx::scheduler().active()) { + warning("scheduler active"); + return false; + } + + if (!_tx.sink()->ready_to_ack()) { return false; } + if (!_tx.sink()->packet_avail()) { return false; } + + Packet_descriptor packet = _tx.sink()->get_packet(); + if (!packet.size()) { + warning("invalid tx packet"); + return true; + } + + enum { HEAD_ROOM = 8 }; + + struct sk_buff *skb = lxc_alloc_skb(packet.size() + HEAD_ROOM, HEAD_ROOM); + + unsigned char *data = lxc_skb_put(skb, packet.size()); + Genode::memcpy(data, _tx.sink()->packet_content(packet), packet.size()); + + _tx_data.ndev = _ndev; + _tx_data.skb = skb; + + _tx_task.unblock(); + Lx::scheduler().schedule(); + + _tx.sink()->acknowledge_packet(packet); + + return true; +} + + +void Session_component::_handle_rx() +{ + while (_rx.source()->ack_avail()) + _rx.source()->release_packet(_rx.source()->get_acked_packet()); +} + + +void Session_component::_handle_packet_stream() +{ + _handle_rx(); + + while (_send()) continue; +} + + +void Session_component::unblock_rx_task(napi_struct * n) +{ + _rx_data.napi = n; + _rx_task.unblock(); +} + + +Nic::Mac_address Session_component::mac_address() +{ + net_device * dev = fec_get_my_registered_net_device(); + return dev ? Nic::Mac_address(dev->dev_addr) : Nic::Mac_address(); +} + + +void Session_component::receive(struct sk_buff *skb) +{ + _handle_rx(); + + if (!_rx.source()->ready_to_submit()) { + Genode::warning("not ready to receive packet"); + return; + } + + Skb s = skb_helper(skb); + + try { + Nic::Packet_descriptor p = _rx.source()->alloc_packet(s.packet_size + s.frag_size); + void *buffer = _rx.source()->packet_content(p); + memcpy(buffer, s.packet, s.packet_size); + + if (s.frag_size) + memcpy((char *)buffer + s.packet_size, s.frag, s.frag_size); + + _rx.source()->submit_packet(p); + } catch (...) { + Genode::warning("failed to process received packet"); + } +} + + +void Session_component::link_state(bool link) +{ + if (link == _has_link) return; + + _has_link = link; + _link_state_changed(); +} + + +Session_component::Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env) +: Nic::Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, env), + _ndev(fec_get_my_registered_net_device()), + _has_link(!(_ndev->state & (1UL << __LINK_STATE_NOCARRIER))) { + _register_session_component(*this); } diff --git a/repos/dde_linux/src/drivers/nic/fec/component.h b/repos/dde_linux/src/drivers/nic/fec/component.h new file mode 100644 index 00000000000..cf1f0b75905 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/component.h @@ -0,0 +1,75 @@ +/* + * \brief Freescale ethernet driver component + * \author Stefan Kalkowski + * \date 2017-11-01 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ +#define _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ + +/* Genode includes */ +#include + +#include + +extern "C" { + struct net_device; + struct napi_struct; + struct sk_buff; +} + +class Session_component : public Nic::Session_component +{ + private: + + struct Tx_data + { + net_device * ndev; + sk_buff * skb; + }; + + struct Rx_data + { + struct napi_struct * napi; + }; + + net_device * _ndev = nullptr; + bool _has_link = false; + Tx_data _tx_data; + Rx_data _rx_data; + + static void _run_tx_task(void * args); + static void _run_rx_task(void * args); + static void _register_session_component(Session_component &); + + Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task", + Lx::Task::PRIORITY_1, Lx::scheduler() }; + Lx::Task _rx_task { _run_rx_task, &_rx_data, "rx_task", + Lx::Task::PRIORITY_1, Lx::scheduler() }; + + bool _send(); + void _handle_rx(); + void _handle_packet_stream() override; + + public: + + Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env); + + Nic::Mac_address mac_address() override; + bool link_state() override { return _has_link; } + void link_state(bool link); + void receive(struct sk_buff *skb); + void unblock_rx_task(napi_struct * n); +}; + +#endif /* _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/dummy.c b/repos/dde_linux/src/drivers/nic/fec/dummy.c new file mode 100644 index 00000000000..b1e3239a15f --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/dummy.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include + +size_t copy_from_user(void *to, void const *from, size_t len) +{ + TRACE_AND_STOP; + return -1; +} + +size_t copy_to_user(void *dst, void const *src, size_t len) +{ + TRACE_AND_STOP; + return -1; +} + +bool device_may_wakeup(struct device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void device_release_driver(struct device *dev) +{ + TRACE_AND_STOP; +} + +int disable_irq(unsigned int irq) +{ + TRACE_AND_STOP; + return -1; +} + +int disable_irq_nosync(unsigned int irq) +{ + TRACE_AND_STOP; + return -1; +} + +int disable_irq_wake(unsigned int irq) +{ + TRACE_AND_STOP; + return -1; +} + +void dma_free_coherent(struct device * d, size_t size, void *vaddr, dma_addr_t bus) +{ + TRACE_AND_STOP; +} + +void dst_release(struct dst_entry *dst) +{ + TRACE_AND_STOP; +} + +int enable_irq_wake(unsigned int irq) +{ + TRACE_AND_STOP; + return -1; +} + +int enable_irq(unsigned int irq) +{ + TRACE_AND_STOP; + return -1; +} + +void eth_hw_addr_random(struct net_device *dev) +{ + TRACE_AND_STOP; +} + +u32 ethtool_op_get_link(struct net_device * d) +{ + TRACE_AND_STOP; + return -1; +} + +int ethtool_op_get_ts_info(struct net_device * d, struct ethtool_ts_info * i) +{ + TRACE_AND_STOP; + return -1; +} + +bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap) +{ + TRACE_AND_STOP; + return -1; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + TRACE_AND_STOP; +} + +void free_netdev(struct net_device * d) +{ + TRACE_AND_STOP; +} + +bool gfp_pfmemalloc_allowed(gfp_t g) +{ + TRACE_AND_STOP; + return -1; +} + +int in_irq(void) +{ + TRACE_AND_STOP; + return -1; +} + +struct iphdr *ip_hdr(const struct sk_buff *skb) +{ + TRACE_AND_STOP; + return NULL; +} + +void *kmap_atomic(struct page *page) +{ + TRACE_AND_STOP; + return NULL; +} + +void kunmap_atomic(void *addr) +{ + TRACE_AND_STOP; +} + +void netif_tx_disable(struct net_device *dev) +{ + TRACE_AND_STOP; +} + +void netif_tx_stop_queue(struct netdev_queue *dev_queue) +{ + TRACE_AND_STOP; +} + +void netif_tx_wake_all_queues(struct net_device * d) +{ + TRACE_AND_STOP; +} + +void netif_tx_wake_queue(struct netdev_queue *dev_queue) +{ + TRACE_AND_STOP; +} + +int net_ratelimit(void) +{ + TRACE_AND_STOP; + return -1; +} + +ktime_t ns_to_ktime(u64 ns) +{ + ktime_t ret; + TRACE_AND_STOP; + return ret; +} + +struct timespec64 ns_to_timespec64(const s64 nsec) +{ + struct timespec64 ret; + TRACE_AND_STOP; + return ret; +} + +bool of_device_is_available(const struct device_node *device) +{ + TRACE_AND_STOP; + return -1; +} + +const void *of_get_mac_address(struct device_node *np) +{ + TRACE_AND_STOP; + return NULL; +} + +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +{ + TRACE_AND_STOP; + return -1; +} + +struct device_node *of_node_get(struct device_node *node) +{ + TRACE_AND_STOP; + return NULL; +} + +void of_node_put(struct device_node *node) +{ + TRACE_AND_STOP; +} + +struct phy_device *of_phy_connect(struct net_device *dev, struct device_node *phy_np, void (*hndlr)(struct net_device *), u32 flags, int iface) +{ + TRACE_AND_STOP; + return NULL; +} + +int of_phy_register_fixed_link(struct device_node *np) +{ + TRACE_AND_STOP; + return -1; +} + +int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) +{ + TRACE_AND_STOP; + return -1; +} + +void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event) +{ + TRACE_AND_STOP; +} + +int ptp_clock_index(struct ptp_clock *ptp) +{ + TRACE_AND_STOP; + return -1; +} + +int ptp_clock_unregister(struct ptp_clock *ptp) +{ + TRACE_AND_STOP; + return -1; +} + +int regulator_disable(struct regulator *r) +{ + TRACE_AND_STOP; + return -1; +} + +resource_size_t resource_size(const struct resource *res) +{ + TRACE_AND_STOP; + return -1; +} + +void rtnl_lock(void) +{ + TRACE_AND_STOP; +} + +void rtnl_unlock(void) +{ + TRACE_AND_STOP; +} + +bool page_is_pfmemalloc(struct page *page) +{ + TRACE_AND_STOP; + return -1; +} + +void put_page(struct page *page) +{ + TRACE_AND_STOP; +} + +void read_lock_bh(rwlock_t * l) +{ + TRACE_AND_STOP; +} + +void read_unlock_bh(rwlock_t * l) +{ + TRACE_AND_STOP; +} + +unsigned int tcp_hdrlen(const struct sk_buff *skb) +{ + TRACE_AND_STOP; + return -1; +} + +u64 timecounter_cyc2time(struct timecounter *tc, cycle_t cycle_tstamp) +{ + TRACE_AND_STOP; + return -1; +} + +u64 timecounter_read(struct timecounter *tc) +{ + TRACE_AND_STOP; + return -1; +} + +void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) +{ + TRACE_AND_STOP; +} + +void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, int size, bool is_last) +{ + TRACE_AND_STOP; +} + +int tso_count_descs(struct sk_buff *skb) +{ + TRACE_AND_STOP; + return -1; +} + +void tso_start(struct sk_buff *skb, struct tso_t *tso) +{ + TRACE_AND_STOP; +} + +void unregister_netdev(struct net_device * d) +{ + TRACE_AND_STOP; +} + +void __vlan_hwaccel_put_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) +{ + TRACE_AND_STOP; +} + +void module_put(struct module *mod) +{ + TRACE_AND_STOP; +} + +void put_device(struct device *dev) +{ + TRACE_AND_STOP; +} + +int strcmp(const char *s1, const char *s2) +{ + TRACE_AND_STOP; + return -1; +} + +int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void class_unregister(struct class *cls) +{ + TRACE_AND_STOP; +} + +void bus_unregister(struct bus_type *bus) +{ + TRACE_AND_STOP; +} + +void driver_unregister(struct device_driver *drv) +{ + TRACE_AND_STOP; +} + +struct user_namespace init_user_ns; +int sysctl_tstamp_allow_data; + diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc new file mode 100644 index 00000000000..6705c883a60 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -0,0 +1,910 @@ +/* + * \brief Emulation of Linux kernel interfaces + * \author Stefan Kalkowski + * \date 2018-01-16 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/** + * Unconditionally include common Genode headers _before_ lx_emul.h to + * prevent shenanigans with macro definitions. + */ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { struct page; } + +class Addr_to_page_mapping : public Genode::List::Element +{ + private: + + unsigned long _addr { 0 }; + struct page *_page { nullptr }; + + static Genode::List & _list() + { + static Genode::List _l; + return _l; + } + + public: + + Addr_to_page_mapping(unsigned long addr, struct page *page) + : _addr(addr), _page(page) { } + + static void insert(struct page * page) + { + Addr_to_page_mapping *m = (Addr_to_page_mapping*) + Lx::Malloc::mem().alloc(sizeof (Addr_to_page_mapping)); + m->_addr = (unsigned long)page->addr; + m->_page = page; + _list().insert(m); + } + + static struct page * remove(unsigned long addr) + { + for (Addr_to_page_mapping *m = _list().first(); m; m = m->next()) + if (m->_addr == addr) { + struct page * ret = m->_page; + _list().remove(m); + Lx::Malloc::mem().free(m); + return ret; + } + + return nullptr; + } +}; + + +struct Device : Genode::List::Element +{ + struct device * dev; /* Linux device */ + + Device(struct device *dev) : dev(dev) { + list()->insert(this); } + + static Genode::List *list() + { + static Genode::List _list; + return &_list; + } +}; + + +class Driver : public Genode::List::Element +{ + private: + + struct device_driver * _drv; /* Linux driver */ + + public: + + Driver(struct device_driver *drv) : _drv(drv) + { + list()->insert(this); + } + + /** + * List of all currently registered drivers + */ + static Genode::List *list() + { + static Genode::List _list; + return &_list; + } + + /** + * Match device and drivers + */ + bool match(struct device *dev) + { + /* + * Don't try if buses don't match, since drivers often use 'container_of' + * which might cast the device to non-matching type + */ + if (_drv->bus != dev->bus) + return false; + + return _drv->bus->match ? _drv->bus->match(dev, _drv) : true; + } + + /** + * Probe device with driver + */ + int probe(struct device *dev) + { + dev->driver = _drv; + + if (dev->bus->probe) return dev->bus->probe(dev); + else if (_drv->probe) + return _drv->probe(dev); + + return 0; + } +}; + +static Session_component * session = nullptr; + +void Session_component::_register_session_component(Session_component & s) { + session = &s; } + + +#include +#include +#include +#include + +extern "C" { + +void lx_backtrace() +{ + Genode::backtrace(); +} + + +int platform_driver_register(struct platform_driver * drv) +{ + static platform_device pd_fec; + static const char * name = "2188000.ethernet"; + pd_fec.name = name; + return drv->probe(&pd_fec); +} + + +struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *), + unsigned int txqs, unsigned int rxqs) +{ + size_t alloc_size = ALIGN(sizeof(struct net_device), NETDEV_ALIGN); + alloc_size += sizeof_priv; + alloc_size += NETDEV_ALIGN - 1; + + struct net_device *p = (struct net_device*) kzalloc(alloc_size, + GFP_KERNEL); + struct net_device *dev = PTR_ALIGN(p, NETDEV_ALIGN); + + INIT_LIST_HEAD(&dev->mc.list); + dev->mc.count = 0; + + dev->gso_max_segs = GSO_MAX_SEGS; + + static const struct ethtool_ops default_ethtool_ops { }; + if (!dev->ethtool_ops) dev->ethtool_ops = &default_ethtool_ops; + + dev->dev_addr = (unsigned char*) kzalloc(ETH_ALEN, GFP_KERNEL); + + return dev; +} + + +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct device *dev) +{ + for (; matches && matches->compatible[0]; matches++) + if (Genode::strcmp(matches->compatible, "fsl,imx6q-fec") == 0) + return matches; + + return NULL; +} + +void * devm_ioremap_resource(struct device *dev, struct resource *res) +{ + static Genode::Attached_io_mem_dataspace io_ds(Lx_kit::env().env(), + 0x2188000, 0x1000); + + return io_ds.local_addr(); +} + + +void platform_set_drvdata(struct platform_device *pdev, void *data) +{ + pdev->dev.driver_data = data; +} + +int of_get_phy_mode(struct device_node *np) +{ + for (int i = 0; i < PHY_INTERFACE_MODE_MAX; i++) + if (!Genode::strcmp("rgmii", phy_modes((phy_interface_t)i))) + return i; + + return -ENODEV; +} + + +ktime_t ktime_get_real(void) +{ + Lx::timer_update_jiffies(); + return ktime_get(); +} + + +void timecounter_init(struct timecounter *tc, const struct cyclecounter *cc, u64 start_tstamp) +{ + tc->cc = cc; + tc->cycle_last = cc->read(cc); + tc->nsec = start_tstamp; + tc->mask = (1ULL << cc->shift) - 1; + tc->frac = 0; +} + + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *addr = Lx::Malloc::dma().alloc_large(size); + + static unsigned waechter = 0; + ASSERT(!waechter++); + + *dma_handle = (dma_addr_t) addr; + return addr; +} + + +void *dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) +{ + dma_addr_t dma_addr; + void *addr = Lx::Malloc::dma().alloc(size, 12, &dma_addr); + + *dma_handle = dma_addr; + return addr; +} + + +dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction) +{ + dma_addr_t dma_addr = (dma_addr_t) Lx::Malloc::dma().phys_addr(cpu_addr); + + if (dma_addr == ~0UL) + Genode::error(__func__, ": virtual address ", cpu_addr, + " not registered for DMA"); + + return dma_addr; +} + + +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return (dma_addr == ~0UL) ? 1 : 0; +} + + +void *dev_get_platdata(const struct device *dev) +{ + return dev->platform_data; +} + + +int netif_running(const struct net_device *dev) +{ + return dev->state & (1 << __LINK_STATE_START); +} + + +void netif_carrier_on(struct net_device *dev) +{ + dev->state &= ~(1UL << __LINK_STATE_NOCARRIER); + if (session) session->link_state(true); +} + + +void netif_carrier_off(struct net_device *dev) +{ + dev->state |= 1UL << __LINK_STATE_NOCARRIER; + if (session) session->link_state(false); +} + + +int netif_device_present(struct net_device * d) +{ + TRACE; + return 1; +} + + + +int platform_get_irq(struct platform_device * d, unsigned int i) +{ + if (i > 1) return -1; + + return 150 + i; +} + + +int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) +{ + Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev_id); + return 0; +} + + +struct clk *devm_clk_get(struct device *dev, const char *id) +{ + static struct clk clocks[] { + { "ipg", 66*1000*1000 }, + { "ahb", 132*1000*1000 }, + { "enet_clk_ref", 500*1000*1000 } }; + + for (unsigned i = 0; i < (sizeof(clocks) / sizeof(struct clk)); i++) + if (Genode::strcmp(clocks[i].name, id) == 0) + return &clocks[i]; + + return NULL; +} + + +unsigned long clk_get_rate(struct clk * clk) +{ + if (!clk) return 0; + return clk->rate; +} + + +int is_valid_ether_addr(const u8 * a) +{ + for (unsigned i = 0; i < ETH_ALEN; i++) + if (a[i] != 0 && a[i] != 255) return 1; + return 0; +} + + +static struct net_device * my_net_device = nullptr; + + +int register_netdev(struct net_device * d) +{ + my_net_device = d; + + d->state |= (1 << __LINK_STATE_START) | (1UL << __LINK_STATE_NOCARRIER); + + int err = d->netdev_ops->ndo_open(d); + if (err) { + Genode::error("ndo_open() failed: ", err); + return err; + } + + return 0; +} + + +struct net_device * fec_get_my_registered_net_device() +{ + return my_net_device; +} + + +void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t, int) +{ + return (void*)cache->alloc(); +} + + + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) +{ + struct page *page = (struct page *)kzalloc(sizeof(struct page), 0); + + size_t size = PAGE_SIZE << order; + + page->addr = Lx::Malloc::dma().alloc(size, 12); + + if (!page->addr) { + Genode::error("alloc_pages: ", size, " failed"); + kfree(page); + return 0; + } + + Addr_to_page_mapping::insert(page); + + atomic_set(&page->_count, 1); + + return page; +} + + +void get_page(struct page *page) +{ + atomic_inc(&page->_count); +} + + +void *__alloc_page_frag(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask) +{ + struct page *page = alloc_pages(GFP_LX_DMA, fragsz / PAGE_SIZE); + if (!page) return nullptr; + return page->addr; +} + + +void __free_page_frag(void *addr) +{ + struct page *page = Addr_to_page_mapping::remove((unsigned long)addr); + + if (!atomic_dec_and_test(&page->_count)) + Genode::error("page reference count != 0"); + + Lx::Malloc::dma().free(page->addr); + kfree(page); +} + +int driver_register(struct device_driver *drv) +{ + new (Lx::Malloc::mem()) Driver(drv); + return 0; +} + + +int device_add(struct device *dev) +{ + if (dev->driver) + return 0; + + /* foreach driver match and probe device */ + for (Driver *driver = Driver::list()->first(); driver; driver = driver->next()) + if (driver->match(dev)) { + int ret = driver->probe(dev); + + if (!ret) return 0; + } + + return 0; +} + + +void device_del(struct device *dev) +{ + if (dev->driver && dev->driver->remove) + dev->driver->remove(dev); +} + + +int device_register(struct device *dev) +{ + return device_add(dev); +} + + +void reinit_completion(struct completion *work) +{ + init_completion(work); +} + + +static void _completion_timeout(unsigned long t) +{ + Lx::Task *task = (Lx::Task *)t; + task->unblock(); +} + + +long __wait_completion(struct completion *work, unsigned long timeout) +{ + timer_list t; + Lx::timer_update_jiffies(); + unsigned long j = timeout ? jiffies + timeout : 0; + + if (timeout) { + setup_timer(&t, _completion_timeout, (unsigned long)Lx::scheduler().current()); + mod_timer(&t, timeout); + } + + while (!work->done) { + + if (j && j <= jiffies) { + lx_log(1, "timeout jiffies %lu", jiffies); + return 0; + } + + Lx::Task *task = Lx::scheduler().current(); + work->task = (void *)task; + task->block_and_schedule(); + } + + if (timeout) + del_timer(&t); + + work->done = 0; + + return j ? j - jiffies : 1; +} + + +int request_module(const char *format, ...) +{ + TRACE; + return 0; +} + + +size_t strlcpy(char *dest, const char *src, size_t size) +{ + size_t ret = Genode::strlen(src); + + if (size) { + size_t len = (ret >= size) ? size - 1 : ret; + Genode::memcpy(dest, src, len); + dest[len] = '\0'; + } + return ret; +} + + +void local_irq_restore(unsigned long f) { } + + +unsigned long local_irq_save(unsigned long flags) { return flags; } + + +int pm_runtime_get_sync(struct device *dev) +{ + return 0; +} + + +void pm_runtime_mark_last_busy(struct device *dev) { } + + +int in_interrupt(void) +{ + return 0; +} + + +int pm_runtime_put_autosuspend(struct device *dev) +{ + return 0; +} + + +int dev_set_name(struct device *dev, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + Genode::String_console sc(dev->name, 32); + sc.vprintf(fmt, args); + + va_end(args); + + new (Lx::Malloc::mem()) Device(dev); + return 0; +} + + +int bus_register(struct bus_type *bus) +{ + TRACE; + return 0; +} + + +struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name) +{ + for (Device *dev = Device::list()->first(); dev; dev = dev->next()) { + if (Genode::strcmp(dev->dev->name, name) == 0) + return dev->dev; + } + return nullptr; +} + + +void netif_napi_add(struct net_device *dev, struct napi_struct *napi, + int (*poll)(struct napi_struct *, int), int weight) +{ + napi->dev = dev; + napi->poll = poll; + napi->state = NAPI_STATE_SCHED; + napi->weight = weight; +} + + +const char *dev_name(const struct device *dev) +{ + return dev->name; +} + + +extern "C" void consume_skb(struct sk_buff *skb); + +void dev_kfree_skb_any(struct sk_buff * sk) +{ + consume_skb(sk); +} + + +void napi_enable(struct napi_struct *n) +{ + clear_bit(NAPI_STATE_SCHED, &n->state); + clear_bit(NAPI_STATE_NPSVC, &n->state); +} + + +void napi_disable(struct napi_struct *n) +{ + set_bit(NAPI_STATE_SCHED, &n->state); + set_bit(NAPI_STATE_NPSVC, &n->state); +} + + +void __napi_schedule(struct napi_struct *n) +{ + if (session) session->unblock_rx_task(n); +} + + +bool napi_schedule_prep(struct napi_struct *n) +{ + return !test_and_set_bit(NAPI_STATE_SCHED, &n->state); +} + + +void napi_complete(struct napi_struct *n) +{ + clear_bit(NAPI_STATE_SCHED, &n->state); +} + + +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) +{ + unsigned long i = offset / BITS_PER_LONG; + offset -= (i * BITS_PER_LONG); + + for (; offset < size; offset++) + if (addr[i] & (1UL << offset)) + return offset + (i * BITS_PER_LONG); + + return size; +} + + +gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +{ + if (session) session->receive(skb); + + dev_kfree_skb(skb); + return GRO_NORMAL; +} + + +void dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) +{ + // FIXME + TRACE; +} + + +bool netif_queue_stopped(const struct net_device *dev) +{ + // FIXME + TRACE; + return 0; +} + + +/********************* + ** DUMMY FUNCTIONS ** + *********************/ + +void clk_disable_unprepare(struct clk * c) +{ + TRACE; +} + +int clk_prepare_enable(struct clk * c) +{ + TRACE; + return 0; +} + +void device_initialize(struct device *dev) +{ + TRACE; +} + +int device_init_wakeup(struct device *dev, bool val) +{ + TRACE; + return 0; +} + +struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id) +{ + TRACE; + return NULL; +} + +struct device_node *of_get_child_by_name( const struct device_node *node, const char *name) +{ + TRACE; + return NULL; +} + +struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, unsigned int index) +{ + TRACE; + return NULL; +} + +const void *of_get_property(const struct device_node *node, const char *name, int *lenp) +{ + TRACE; + return NULL; +} + +struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index) +{ + TRACE; + return NULL; +} + +bool of_phy_is_fixed_link(struct device_node *np) +{ + TRACE; + return 0; +} + +int pinctrl_pm_select_default_state(struct device *dev) +{ + TRACE; + return -1; +} + +int pinctrl_pm_select_sleep_state(struct device *dev) +{ + TRACE; + return -1; +} + +struct resource *platform_get_resource(struct platform_device * d, unsigned r1, unsigned r2) +{ + TRACE; + return NULL; +} + +void pm_runtime_enable(struct device *dev) +{ + TRACE; +} + +void pm_runtime_get_noresume(struct device *dev) +{ + TRACE; +} + +int pm_runtime_set_active(struct device *dev) +{ + TRACE; + return 0; +} + +void pm_runtime_set_autosuspend_delay(struct device *dev, int delay) +{ + TRACE; +} + +void pm_runtime_use_autosuspend(struct device *dev) +{ + TRACE; +} + +struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, struct device *parent) +{ + TRACE; + return NULL; +} + +int regulator_enable(struct regulator * d) +{ + TRACE; + return 0; +} + +int of_driver_match_device(struct device *dev, const struct device_driver *drv) +{ + TRACE; + return 0; +} + +int class_register(struct class_ *cls) +{ + TRACE; + return 0; +} + +int try_module_get(struct module *mod) +{ + TRACE; + return -1; +} + +struct device *get_device(struct device *dev) +{ + TRACE; + return NULL; +} + +int device_bind_driver(struct device *dev) +{ + TRACE; + return 0; +} + +void netif_tx_start_all_queues(struct net_device *dev) +{ + TRACE; +} + +void netif_tx_lock_bh(struct net_device *dev) +{ + TRACE; +} + +int device_set_wakeup_enable(struct device *dev, bool enable) +{ + TRACE; + return 0; +} + +void trace_consume_skb(struct sk_buff * sb) +{ + TRACE; +} + +void trace_kfree_skb(struct sk_buff * sb, void * p) +{ + TRACE; +} + +void netif_tx_unlock_bh(struct net_device *dev) +{ + TRACE; +} + +void netif_wake_queue(struct net_device * d) +{ + TRACE; +} + +bool netdev_uses_dsa(struct net_device *dev) +{ + TRACE; + return false; +} + +void dma_sync_single_for_device(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + TRACE; +} + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, + enum dma_data_direction dir) +{ + TRACE; +} + +} diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h new file mode 100644 index 00000000000..5743821eb34 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h @@ -0,0 +1,1461 @@ +/* + * \brief Freescale ethernet driver Linux emulation environment + * \author Stefan Kalkowski + * \date 2017-11-01 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SRC__DRIVERS__NIC__FEC__LX_EMUL_H_ +#define _SRC__DRIVERS__NIC__FEC__LX_EMUL_H_ + +#include +#include + +#include + +#include +#include +#include + +void lx_backtrace(void); + +#define DEBUG 0 +#if DEBUG +#define TRACE \ + do { \ + lx_printf("%s not implemented\n", __func__); \ + } while (0) +#else +#define TRACE do { ; } while (0) +#endif + +#define TRACE_AND_STOP \ + do { \ + lx_printf("%s not implemented\n", __func__); \ + lx_backtrace(); \ + BUG(); \ + } while (0) + +#define ASSERT(x) \ + do { \ + if (!(x)) { \ + lx_printf("%s:%u assertion failed\n", __func__, __LINE__); \ + BUG(); \ + } \ + } while (0) + +typedef int clockid_t; + +#define PAGE_SIZE 4096UL + +enum { PAGE_SHIFT = 12 }; +enum { HZ = 100UL, }; + +struct list_head; + +typedef __u16 __le16; +typedef __u32 __le32; +typedef __u64 __le64; +typedef __u16 __be16; +typedef __u32 __be32; +typedef __u64 __be64; +typedef __s64 time64_t; + +#define L1_CACHE_BYTES 32 +#define SMP_CACHE_BYTES L1_CACHE_BYTES + +#define __aligned_u64 __u64 __attribute__((aligned(8))) +#define ____cacheline_aligned_in_smp __attribute__((aligned(SMP_CACHE_BYTES))) +#define ____cacheline_aligned __attribute__((aligned(SMP_CACHE_BYTES))) + + +struct iov_iter { }; +size_t iov_iter_count(struct iov_iter *i); + +#define dev_info( dev, format, arg...) lx_printf("dev_info: " format , ## arg) +#define dev_warn( dev, format, arg...) lx_printf("dev_warn: " format , ## arg) +#define dev_WARN( dev, format, arg...) lx_printf("dev_WARN: " format , ## arg) +#define dev_err( dev, format, arg...) lx_printf("dev_error: " format , ## arg) +#define dev_notice(dev, format, arg...) lx_printf("dev_notice: " format , ## arg) +#define dev_crit( dev, format, arg...) lx_printf("dev_crit: " format , ## arg) +#if DEBUG +#define dev_dbg( dev, format, arg...) lx_printf("dev_dbg: " format , ## arg) +#else +#define dev_dbg( dev, format, arg...) +#endif + +#define pr_debug(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_err(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__) +#define pr_warn(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__) +#define pr_info_once(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__) +#define pr_emerg(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) + +#define netdev_err(dev, fmt, args...) lx_printf("netdev_err: " fmt, ##args) +#define netdev_warn(dev, fmt, args...) lx_printf("netdev_warn: " fmt, ##args) +#define netdev_info(dev, fmt, args...) lx_printf("netdev_info: " fmt, ##args) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + ETH_HLEN = 14, + ETH_ALEN = 6, /* octets in one ethernet addr */ + ETH_P_8021Q = 0x8100, /* 802.1Q VLAN Extended Header */ + ETH_P_IP = 0x0800, + ETH_P_IPV6 = 0x86DD, + ETH_P_8021AD = 0x88A8, + VLAN_HLEN = 4, + VLAN_ETH_HLEN = 18, +}; + +typedef int raw_hdlc_proto; +typedef int cisco_proto; +typedef int fr_proto; +typedef int fr_proto_pvc; +typedef int fr_proto_pvc_info; +typedef int sync_serial_settings; +typedef int te1_settings; + +struct callback_head { + struct callback_head *next; + void (*func)(struct callback_head *head); +}; +#define rcu_head callback_head + +#define FIONREAD 0x541B +#define TIOCOUTQ 0x5411 + +struct completion { unsigned int done; void *task; }; +long __wait_completion(struct completion *work, unsigned long timeout); + +enum { + NAPI_STATE_SCHED, + NAPI_STATE_DISABLE, + NAPI_STATE_NPSVC, + NAPI_STATE_HASHED, +}; + +struct napi_struct +{ + struct net_device * dev; + int (*poll)(struct napi_struct *, int); + unsigned long state; + int weight; +}; + +#define writel(value, addr) (*(volatile uint32_t *)(addr) = (value)) +#define readl(addr) (*(volatile uint32_t *)(addr)) + +typedef u64 cycle_t; + +struct timespec64 { + time64_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; + +extern struct timespec64 ns_to_timespec64(const s64 nsec); + +static inline s64 timespec64_to_ns(const struct timespec64 *ts) +{ + return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; +} + +#define ktime_to_ns(kt) ((kt).tv64) + +ktime_t ns_to_ktime(u64 ns); + +struct device_node +{ + const char * full_name; +}; + +struct device; +struct device_driver; + +struct bus_type +{ + const char * name; + const struct attribute_group **dev_groups; + + int (*match)(struct device *dev, struct device_driver *drv); + int (*probe)(struct device *dev); + + const struct dev_pm_ops *pm; +}; + +struct device_driver { + const char * name; + struct bus_type *bus; + struct module *owner; + const struct of_device_id*of_match_table; + const struct dev_pm_ops *pm; + int (*probe)(struct device *dev); + int (*remove) (struct device *dev); +}; + +struct class +{ + const char *name; + void (*dev_release)(struct device *dev); +}; + +struct attribute { + const char *name; +}; + +struct attribute_group +{ + struct attribute ** attrs; +}; + +struct device { + char name[32]; + struct device * parent; + struct device_driver *driver; + void * platform_data; + void * driver_data; + const struct attribute_group **groups; + void (*release)(struct device *dev); + struct bus_type *bus; + struct class *class; + struct device_node *of_node; +}; + +struct platform_device { + const char * name; + struct device dev; + const struct platform_device_id * id_entry; +}; + +#define platform_get_device_id(pdev) ((pdev)->id_entry) + +static inline void *platform_get_drvdata(const struct platform_device *pdev) +{ + return pdev->dev.driver_data; +} + +void udelay(unsigned long usecs); + +enum netdev_tx { + NETDEV_TX_OK = 0x00, + NETDEV_TX_BUSY = 0x10, + NETDEV_TX_LOCKED = 0x20, +}; +typedef enum netdev_tx netdev_tx_t; + +struct sk_buff; +struct ifreq; + +#include + +struct net_device_ops { + int (*ndo_open) (struct net_device *dev); + int (*ndo_stop) (struct net_device *dev); + netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); + void (*ndo_set_rx_mode) (struct net_device *dev); + int (*ndo_change_mtu) (struct net_device *dev, int new_mtu); + int (*ndo_validate_addr) (struct net_device *dev); + void (*ndo_tx_timeout) (struct net_device *dev); + int (*ndo_set_mac_address)(struct net_device *dev, void *addr); + int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); + int (*ndo_set_features)(struct net_device *dev, netdev_features_t features); +}; + +struct net_device_stats { + unsigned long rx_packets; + unsigned long tx_packets; + unsigned long rx_bytes; + unsigned long tx_bytes; + unsigned long collisions; + unsigned long rx_errors; + unsigned long tx_errors; + unsigned long rx_dropped; + unsigned long tx_dropped; + unsigned long rx_length_errors; + unsigned long rx_over_errors; + unsigned long rx_crc_errors; + unsigned long rx_frame_errors; + unsigned long rx_fifo_errors; + unsigned long rx_missed_errors; + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; +}; + +struct netdev_hw_addr { + struct list_head list; + unsigned char addr[32]; +}; + +struct netdev_hw_addr_list { + struct list_head list; + int count; +}; + +enum { NETDEV_ALIGN = 32, GSO_MAX_SEGS = 65535 }; + +enum netdev_state_t { + __LINK_STATE_START, + __LINK_STATE_PRESENT, + __LINK_STATE_NOCARRIER, + __LINK_STATE_LINKWATCH_PENDING, + __LINK_STATE_DORMANT, +}; + +#define MAX_ADDR_LEN 32 + +struct net_device +{ + unsigned long state; + netdev_features_t features; + struct net_device_stats stats; + netdev_features_t hw_features; + const struct net_device_ops *netdev_ops; + const struct ethtool_ops *ethtool_ops; + const struct header_ops *header_ops; + unsigned int flags; + unsigned int priv_flags; + unsigned short hard_header_len; + unsigned long mtu; + unsigned short type; + unsigned char addr_len; + struct netdev_hw_addr_list mc; + unsigned char *dev_addr; + unsigned char broadcast[MAX_ADDR_LEN]; + unsigned long tx_queue_len; + int watchdog_timeo; + struct device dev; + u16 gso_max_segs; + struct phy_device *phydev; +}; + +static inline void *netdev_priv(const struct net_device *dev) { + return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); } + +#define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1) + +static inline u64 div_u64(u64 dividend, u32 divisor) { return dividend / divisor; } + +struct pps_event_time { + struct timespec64 ts_real; +}; + +size_t copy_from_user(void *to, void const *from, size_t len); +size_t copy_to_user(void *dst, void const *src, size_t len); + +int snprintf(char *buf, size_t size, const char *fmt, ...); + +struct clk +{ + const char * name; + unsigned long rate; +}; + +unsigned long clk_get_rate(struct clk * clk); + +#define module_param_array(macaddr, byte, arg1, arg2); + +# define swab32p __swab32p +# define swab32s __swab32s + +u64 local_clock(void); + +#define do_div(n,base) ({ \ + unsigned long __base = (base); \ + unsigned long __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ +}) + +enum { + MSEC_PER_SEC = 1000L, + USEC_PER_SEC = MSEC_PER_SEC * 1000L, +}; + +static inline int rcu_read_lock_held(void) { return 1; } +static inline int rcu_read_lock_bh_held(void) { return 1; } + +unsigned int jiffies_to_usecs(const unsigned long j); + +struct rb_node {}; + +#define __aligned(x) __attribute__((aligned(x))) + +#define kmemcheck_bitfield_begin(name) +#define kmemcheck_bitfield_end(name) + +typedef __u32 __wsum; + +enum { NUMA_NO_NODE = -1 }; + +struct ts_state +{ + char cb[40]; +}; + +struct ts_config +{ + unsigned int (*get_next_block)(unsigned int consumed, + const u8 **dst, + struct ts_config *conf, + struct ts_state *state); + void (*finish)(struct ts_config *conf, + struct ts_state *state); +}; + +struct flow_dissector_key_control +{ + u16 thoff; + u16 addr_type; + u32 flags; +}; + +struct flow_keys +{ + struct flow_dissector_key_control control; +}; + +struct flow_dissector_key {}; + +struct flow_dissector {}; + +extern struct flow_dissector flow_keys_dissector; +extern struct flow_dissector flow_keys_buf_dissector; + +struct flowi4 {}; +struct flowi6 {}; + +__u32 __get_hash_from_flowi6(const struct flowi6 *fl6, struct flow_keys *keys); + +bool flow_keys_have_l4(struct flow_keys *keys); + +__u32 __get_hash_from_flowi4(const struct flowi4 *fl4, struct flow_keys *keys); + +bool gfpflags_allow_blocking(const gfp_t gfp_flags); + +struct lock_class_key { }; + +#define lockdep_set_class(lock, key) + +struct page +{ + atomic_t _count; + void *addr; + dma_addr_t paddr; + unsigned long private; +} __attribute((packed)); + +static inline struct page *compound_head(struct page *page) { return page; } + +bool page_is_pfmemalloc(struct page *page); + +void __free_page_frag(void *addr); + +struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order); + +void get_page(struct page *page); +void put_page(struct page *page); + +static inline void *page_address(struct page *page) { return page->addr; }; + +struct page_frag +{ + struct page *page; + __u16 offset; + __u16 size; +}; + +enum dma_data_direction { DMA_FROM_DEVICE = 2 }; + +dma_addr_t dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir); + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir); + +#define L1_CACHE_BYTES 32 + + +size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); + +__wsum csum_block_add(__wsum csum, __wsum csum2, int offset); +__wsum csum_sub(__wsum csum, __wsum addend); +__wsum csum_partial(const void *buff, int len, __wsum sum); + +typedef struct poll_table_struct { } poll_table; + +size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); +size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); + +struct partial_page +{ + unsigned int offset; + unsigned int len; +}; + +struct splice_pipe_desc +{ + struct page **pages; + struct partial_page *partial; + int nr_pages; + unsigned int nr_pages_max; + unsigned int flags; + const struct pipe_buf_operations *ops; + void (*spd_release)(struct splice_pipe_desc *, unsigned int); +}; + +struct timespec ktime_to_timespec(const ktime_t kt); + +typedef __u16 __sum16; + +__sum16 csum_fold(__wsum csum); +__wsum csum_add(__wsum csum, __wsum addend); +__wsum remcsum_adjust(void *ptr, __wsum csum, int start, int offset); + +#define htons(x) __cpu_to_be16(x) + +struct iphdr { + __u8 ihl:4; + __u8 version:4; + __u8 tos; + __be16 tot_len; + __be16 frag_off; + __u8 ttl; + __u8 protocol; + __sum16 check; + __be32 saddr; + __be32 daddr; +}; + +struct sk_buff; +struct iphdr *ip_hdr(const struct sk_buff *skb); + +typedef unsigned short ushort; + +dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir); + +enum { DMA_TO_DEVICE = 1 }; + +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); + +void dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir); + +void dev_kfree_skb_any(struct sk_buff *); + +int net_ratelimit(void); + +unsigned int tcp_hdrlen(const struct sk_buff *skb); + +struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, unsigned int index); +void netif_tx_stop_queue(struct netdev_queue *dev_queue); +void netif_tx_wake_queue(struct netdev_queue *dev_queue); +bool netif_queue_stopped(const struct net_device *dev); + +#define CONFIG_ARCH_MXC 1 +#define CONFIG_OF_MDIO 1 + +void rtnl_lock(void); +void rtnl_unlock(void); + +int netif_device_present(struct net_device *); +int netif_running(const struct net_device *dev); +void netif_wake_queue(struct net_device *); +void netif_tx_lock_bh(struct net_device *dev); +void netif_tx_unlock_bh(struct net_device *dev); + +void napi_enable(struct napi_struct *n); +void napi_disable(struct napi_struct *n); + +static inline void __read_once_size(const volatile void *p, void *res, int size) +{ + switch (size) { + case 1: *(__u8 *)res = *(volatile __u8 *)p; break; + case 2: *(__u16 *)res = *(volatile __u16 *)p; break; + case 4: *(__u32 *)res = *(volatile __u32 *)p; break; + case 8: *(__u64 *)res = *(volatile __u64 *)p; break; + default: + barrier(); + __builtin_memcpy((void *)res, (const void *)p, size); + barrier(); + } +} + +#define READ_ONCE(x) \ +({ \ + union { typeof(x) __val; char __c[1]; } __u; \ + __read_once_size(&(x), __u.__c, sizeof(x)); \ + __u.__val; \ +}) + +extern unsigned long find_next_bit(const unsigned long *addr, unsigned long + size, unsigned long offset); +#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) + +#define prefetch(x) __builtin_prefetch(x) +#define prefetchw(x) __builtin_prefetch(x,1) + +#define ntohs(x) __be16_to_cpu(x) + +struct vlan_hdr +{ + __be16 h_vlan_TCI; +}; + +__be16 eth_type_trans(struct sk_buff *, struct net_device *); + +void __vlan_hwaccel_put_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); + +enum gro_result { + GRO_MERGED, + GRO_MERGED_FREE, + GRO_HELD, + GRO_NORMAL, + GRO_DROP, +}; +typedef enum gro_result gro_result_t; + +gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); + +void dma_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir); + +bool napi_schedule_prep(struct napi_struct *n); + +void __napi_schedule(struct napi_struct *n); + +void napi_complete(struct napi_struct *n); + +void *dev_get_platdata(const struct device *dev); + +int is_valid_ether_addr(const u8 *); + +const void *of_get_mac_address(struct device_node *np); + +void eth_hw_addr_random(struct net_device *dev); + +int pm_runtime_get_sync(struct device *dev); + +void reinit_completion(struct completion *x); + +void pm_runtime_mark_last_busy(struct device *dev); + +int pm_runtime_put_autosuspend(struct device *dev); + +int clk_prepare_enable(struct clk *); + +void clk_disable_unprepare(struct clk *); + +struct phy_device *of_phy_connect(struct net_device *dev, struct device_node *phy_np, void (*hndlr)(struct net_device *), u32 flags, int iface); + +const char *dev_name(const struct device *dev); + +void *kmalloc(size_t size, gfp_t flags); +void kfree(const void *); +void *kzalloc(size_t size, gfp_t flags); + +struct mii_bus; +struct device_node *of_get_child_by_name( const struct device_node *node, const char *name); +void of_node_put(struct device_node *node); +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np); + +struct resource *platform_get_resource(struct platform_device *, unsigned, unsigned); + +#include +#include +#include +#include +#include +#include +#include + +int ethtool_op_get_ts_info(struct net_device *, struct ethtool_ts_info *); + +int device_set_wakeup_enable(struct device *dev, bool enable); + +bool device_may_wakeup(struct device *dev); + +int enable_irq_wake(unsigned int irq); +int disable_irq_wake(unsigned int irq); + +struct ethtool_ops { + int(*get_settings)(struct net_device *, struct ethtool_cmd *); + int(*set_settings)(struct net_device *, struct ethtool_cmd *); + void(*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); + int(*get_regs_len)(struct net_device *); + void(*get_regs)(struct net_device *, struct ethtool_regs *, void *); + void(*get_wol)(struct net_device *, struct ethtool_wolinfo *); + int(*set_wol)(struct net_device *, struct ethtool_wolinfo *); + int(*nway_reset)(struct net_device *); + u32(*get_link)(struct net_device *); + int(*get_coalesce)(struct net_device *, struct ethtool_coalesce *); + int(*set_coalesce)(struct net_device *, struct ethtool_coalesce *); + void(*get_pauseparam)(struct net_device *, struct ethtool_pauseparam*); + int(*set_pauseparam)(struct net_device *, struct ethtool_pauseparam*); + void(*get_strings)(struct net_device *, u32 stringset, u8 *); + void(*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); + int(*get_sset_count)(struct net_device *, int); + int(*get_ts_info)(struct net_device *, struct ethtool_ts_info *); + int(*get_tunable)(struct net_device *, + const struct ethtool_tunable *, void *); + int(*set_tunable)(struct net_device *, + const struct ethtool_tunable *, const void *); +}; + +u32 ethtool_op_get_link(struct net_device *); + +void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t); +void dma_free_coherent(struct device *, size_t size, void *vaddr, dma_addr_t bus); + +void netif_tx_start_all_queues(struct net_device *dev); + +int pinctrl_pm_select_default_state(struct device *dev); + +int pinctrl_pm_select_sleep_state(struct device *dev); + +void netif_tx_disable(struct net_device *dev); + +#include + +#define rcu_assign_pointer(p, v) (p = v); + +#include + +#define netdev_hw_addr_list_for_each(ha, l) \ + list_for_each_entry(ha, &(l)->list, list) + +#define netdev_for_each_mc_addr(ha, dev) \ + netdev_hw_addr_list_for_each(ha, &(dev)->mc) + +void netif_tx_wake_all_queues(struct net_device *); + +int eth_validate_addr(struct net_device *); + +void *dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); + +int eth_change_mtu(struct net_device *dev, int new_mtu); +int eth_validate_addr(struct net_device *dev); + +void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight); + +bool of_device_is_available(const struct device_node *device); +int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value); + +enum { NAPI_POLL_WEIGHT = 64 }; + +#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) + +struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs); + +void *devm_ioremap_resource(struct device *dev, struct resource *res); + +const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev); + +const void *of_get_property(const struct device_node *node, const char *name, int *lenp); + +void platform_set_drvdata(struct platform_device *pdev, void *data); + +struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index); + +int of_phy_register_fixed_link(struct device_node *np); +bool of_phy_is_fixed_link(struct device_node *np); +struct device_node *of_node_get(struct device_node *node); +int of_get_phy_mode(struct device_node *np); + +struct clk *devm_clk_get(struct device *dev, const char *id); +struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id); + +void pm_runtime_set_autosuspend_delay(struct device *dev, int delay); +void pm_runtime_use_autosuspend(struct device *dev); +void pm_runtime_get_noresume(struct device *dev); +int pm_runtime_set_active(struct device *dev); +void pm_runtime_enable(struct device *dev); + +int regulator_enable(struct regulator *); + +int platform_get_irq(struct platform_device *, unsigned int); + +void netif_carrier_off(struct net_device *dev); + +int register_netdev(struct net_device *); +void unregister_netdev(struct net_device *); + +void free_netdev(struct net_device *); + +int device_init_wakeup(struct device *dev, bool val); + +int regulator_disable(struct regulator *r); + +void *dev_get_drvdata(const struct device *dev); + +void netif_device_attach(struct net_device *); +void netif_device_detach(struct net_device *dev); + +int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id); + +#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) +#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) + +struct platform_driver { + int (*probe)(struct platform_device *); + int (*remove)(struct platform_device *); + struct device_driver driver; + const struct platform_device_id *id_table; +}; + +int platform_driver_register(struct platform_driver *); +void platform_driver_unregister(struct platform_driver *); + +#define module_driver(__driver, __register, __unregister, ...) \ +static int __init __driver##_init(void) \ +{ \ + return __register(&(__driver) , ##__VA_ARGS__); \ +} \ +module_init(__driver##_init); \ +static void __exit __driver##_exit(void) \ +{ \ + __unregister(&(__driver) , ##__VA_ARGS__); \ +} \ +module_exit(__driver##_exit); + +#define module_platform_driver(__platform_driver) \ + module_driver(__platform_driver, platform_driver_register, \ + platform_driver_unregister) + +struct tasklet_struct +{ + void (*func)(unsigned long); + unsigned long data; +}; + +#define PTR_ALIGN(p, a) ({ \ + unsigned long _p = (unsigned long)p; \ + _p = (_p + a - 1) & ~(a - 1); \ + p = (typeof(p))_p; \ + p; \ +}) + +struct kmem_cache; +struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, unsigned long, void (*)(void *)); +void kmem_cache_destroy(struct kmem_cache *); +void *kmem_cache_alloc(struct kmem_cache *, gfp_t); +void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags); +void kmem_cache_free(struct kmem_cache *, void *); +void *kmalloc_node_track_caller(size_t size, gfp_t flags, int node); +void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t flags, int node); + +struct mem_cgroup {}; +typedef int possible_net_t; +typedef int rwlock_t; + +bool gfp_pfmemalloc_allowed(gfp_t); + +struct user_namespace {}; + +struct cred { + struct user_namespace * user_ns; +}; + +struct file { + const struct cred * f_cred; +}; + +struct net; + +struct percpu_counter { + s64 count; +}; + +static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount, gfp_t gfp) +{ + fbc->count = amount; + return 0; +} + +static inline s64 percpu_counter_read(struct percpu_counter *fbc) +{ + return fbc->count; +} + +static inline +void percpu_counter_add(struct percpu_counter *fbc, s64 amount) +{ + fbc->count += amount; +} + +static inline +void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) +{ + percpu_counter_add(fbc, amount); +} + +s64 percpu_counter_sum_positive(struct percpu_counter *fbc); + +static inline void percpu_counter_inc(struct percpu_counter *fbc) +{ + percpu_counter_add(fbc, 1); +} + +static inline void percpu_counter_dec(struct percpu_counter *fbc) +{ + percpu_counter_add(fbc, -1); +} + +static inline +s64 percpu_counter_read_positive(struct percpu_counter *fbc) +{ + return fbc->count; +} + +void percpu_counter_destroy(struct percpu_counter *fbc); + +s64 percpu_counter_sum(struct percpu_counter *fbc); + +void local_bh_disable(void); +void local_bh_enable(void); + +#include +#include + +static inline int net_eq(const struct net *net1, const struct net *net2) { + return net1 == net2; } + +extern struct net init_net; + +struct net *dev_net(const struct net_device *dev); + +#define read_pnet(pnet) (&init_net) + +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] + +void bitmap_fill(unsigned long *dst, int nbits); +void bitmap_zero(unsigned long *dst, int nbits); + +typedef unsigned seqlock_t; + + +enum { LL_MAX_HEADER = 96 }; + +struct hh_cache +{ + u16 hh_len; + u16 __pad; + seqlock_t hh_lock; + +#define HH_DATA_MOD 16 +#define HH_DATA_OFF(__len) \ + (HH_DATA_MOD - (((__len - 1) & (HH_DATA_MOD - 1)) + 1)) +#define HH_DATA_ALIGN(__len) \ + (((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1)) + unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)]; +}; + +struct seq_net_private { + struct net *net; +}; + +struct seq_file; +struct ctl_table; + +typedef int proc_handler (struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos); + +unsigned read_seqbegin(const seqlock_t *sl); +unsigned read_seqretry(const seqlock_t *sl, unsigned start); + +int dev_queue_xmit(struct sk_buff *skb); + +#define raw_smp_processor_id() 0 + +#define rcu_dereference_bh(p) p +#define rcu_dereference_raw(p) p +#define rcu_dereference_check(p, c) p +#define rcu_dereference(p) p + +struct page_counter +{ + atomic_long_t count; + unsigned long limit; +}; + +struct cg_proto +{ + struct page_counter memory_allocated; + struct percpu_counter sockets_allocated; + int memory_pressure; + long sysctl_mem[3]; +}; + +void page_counter_charge(struct page_counter *counter, unsigned long nr_pages); +unsigned long page_counter_read(struct page_counter *counter); +void page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages); + +enum { UNDER_LIMIT, SOFT_LIMIT, OVER_LIMIT }; + +struct inode {}; + +struct vm_area_struct; + +void write_lock_bh(rwlock_t *); +void write_unlock_bh(rwlock_t *); + +struct sock; +struct socket; + +void security_sock_graft(struct sock *, struct socket *); + +u32 prandom_u32(void); + +void rcu_read_lock(void); +void rcu_read_unlock(void); + +bool net_gso_ok(netdev_features_t features, int gso_type); + +size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); + +bool poll_does_not_wait(const poll_table *p); +void poll_wait(struct file *f, wait_queue_head_t *w, poll_table *p); + +struct task_struct +{ + unsigned int flags; + struct page_frag task_frag; +}; + +extern struct task_struct *current; + +int in_softirq(void); + +enum { MAX_SCHEDULE_TIMEOUT = 1000 }; + +#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) + +#define write_pnet(pnet, net) do { (void)(net);} while (0) + +#define smp_load_acquire(p) *(p) +#define smp_store_release(p, v) *(p) = v; + +size_t ksize(void *); + +#define kmemcheck_bitfield_begin(name) +#define kmemcheck_bitfield_end(name) +#define kmemcheck_annotate_bitfield(ptr, name) +#define kmemcheck_annotate_variable(var) + +struct page *virt_to_head_page(const void *x); + +#define DEFINE_PER_CPU(type, name) \ + typeof(type) name +#define this_cpu_ptr(ptr) ptr + +struct page_frag_cache +{ + bool pfmemalloc; +}; + +void *__alloc_page_frag(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask); + +unsigned long local_irq_save(unsigned long flags); +void local_irq_restore(unsigned long); + +int in_irq(void); + +void trace_kfree_skb(struct sk_buff *, void *); +void trace_consume_skb(struct sk_buff *); + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order); + +#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) + +#define page_private(page) ((page)->private) +#define set_page_private(page, v) ((page)->private = (v)) + +void *kmap_atomic(struct page *page); +void kunmap_atomic(void *addr); + +struct page *virt_to_page(const void *x); + +struct pipe_inode_info; + +ssize_t splice_to_pipe(struct pipe_inode_info *, struct splice_pipe_desc *); + +extern const struct pipe_buf_operations nosteal_pipe_buf_ops; + +__wsum csum_partial_ext(const void *buff, int len, __wsum sum); +__wsum csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len); +__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum); +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy((src), (dst), (len), (sum)) + +unsigned int textsearch_find(struct ts_config *, struct ts_state *); + +__be16 skb_network_protocol(struct sk_buff *skb, int *depth); + +bool can_checksum_protocol(netdev_features_t features, __be16 protocol); + +unsigned int skb_gro_offset(const struct sk_buff *skb); + +unsigned int skb_gro_len(const struct sk_buff *skb); + +#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) + +enum { NAPI_GRO_FREE = 1, NAPI_GRO_FREE_STOLEN_HEAD = 2, }; + +struct napi_gro_cb +{ + u16 flush; + u16 count; + u8 same_flow; + u8 free; + struct sk_buff *last; +}; + +enum { + SLAB_HWCACHE_ALIGN = 0x00002000ul, + SLAB_CACHE_DMA = 0x00004000ul, + SLAB_PANIC = 0x00040000ul, + SLAB_LX_DMA = 0x80000000ul, +}; + +void sg_mark_end(struct scatterlist *sg); +void sg_set_buf(struct scatterlist *, const void *, unsigned int); +void sg_set_page(struct scatterlist *, struct page *, unsigned int, unsigned int); + +struct inet_skb_parm { }; + +enum { + IPPROTO_IP = 0, + IPPROTO_TCP = 6, + IPPROTO_UDP = 17, + IPPROTO_AH = 51, +}; + +enum { + IPPROTO_HOPOPTS = 0, + IPPROTO_ROUTING = 43, + IPPROTO_FRAGMENT = 44, + IPPROTO_DSTOPTS = 60, +}; + +void read_lock_bh(rwlock_t *); +void read_unlock_bh(rwlock_t *); + +bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); + +extern struct user_namespace init_user_ns; + +enum { CAP_NET_RAW = 13 }; + +struct tcphdr +{ + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; + __be16 window; + __sum16 check; +}; + +struct tcphdr *tcp_hdr(const struct sk_buff *skb); + +struct udphdr +{ + __sum16 check; +}; + +struct udphdr *udp_hdr(const struct sk_buff *skb); + +struct in6_addr {}; + +struct ipv6hdr +{ + __be16 payload_len; + __u8 nexthdr; + struct in6_addr saddr; + struct in6_addr daddr; +}; + +struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb); + +struct ipv6_opt_hdr +{ + __u8 nexthdr; + __u8 hdrlen; +} __attribute__((packed)); + +struct ip_auth_hdr +{ + __u8 nexthdr; + __u8 hdrlen; +}; + +struct frag_hdr +{ + __u8 nexthdr; + __be16 frag_off; +}; + +#define ipv6_optlen(p) (((p)->hdrlen+1) << 3) +#define ipv6_authlen(p) (((p)->hdrlen+2) << 2) + +enum { IP_OFFSET = 0x1FFF, IP_MF = 0x2000 }; + +enum { IP6_MF = 0x0001, IP6_OFFSET = 0xfff8 }; + +unsigned int ip_hdrlen(const struct sk_buff *skb); + +__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum); + +__sum16 csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, unsigned short proto, __wsum csum); + +void secpath_reset(struct sk_buff *); + +struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb); +unsigned int inner_tcp_hdrlen(const struct sk_buff *skb); + +#define skb_vlan_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) + +void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr); + +#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */ +#define VLAN_TAG_PRESENT VLAN_CFI_MASK + +int __vlan_insert_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); + +#define skb_vlan_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) + +void put_device(struct device *dev); + +typedef void (*dr_release_t)(struct device *dev, void *res); +typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); + +void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp); +void devres_add(struct device *dev, void *res); +void devres_free(void *res); +int devres_release(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); + +int dev_set_name(struct device *dev, const char *fmt, ...); + +int device_register(struct device *dev); + +void device_del(struct device *dev); + +int in_interrupt(void); + +int of_driver_match_device(struct device *dev, const struct device_driver *drv); + +struct device_attribute +{ + struct attribute attr; +}; + +#define __ATTRIBUTE_GROUPS(_name) \ + static const struct attribute_group *_name##_groups[] = { \ + &_name##_group, \ + NULL, \ + } + +#define ATTRIBUTE_GROUPS(_name) \ + static const struct attribute_group _name##_group = { \ + .attrs = _name##_attrs, \ + }; \ +__ATTRIBUTE_GROUPS(_name) + + +int sprintf(char *buf, const char *fmt, ...); + +#define __ATTR_NULL { .attr = { .name = NULL } } + +#define __ATTR_RO(name) __ATTR_NULL + +#define DEVICE_ATTR_RO(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RO(_name) + +int class_register(struct class *cls); +void class_unregister(struct class *cls); + +int bus_register(struct bus_type *bus); +void bus_unregister(struct bus_type *bus); + +#define __stringify(x...) #x + +int request_module(const char *name, ...); + +void device_initialize(struct device *dev); + +extern struct workqueue_struct *system_power_efficient_wq; + +int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev); +void free_irq(unsigned int irq, void *dev_id); +int enable_irq(unsigned int irq); +int disable_irq(unsigned int irq); +int disable_irq_nosync(unsigned int irq); + +void netif_carrier_on(struct net_device *dev); + +typedef struct { + __u8 b[16]; +} uuid_le; + +int device_add(struct device *dev); +struct device *get_device(struct device *dev); + +struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name); + +void msleep(unsigned int); + +int device_bind_driver(struct device *dev); +void device_release_driver(struct device *dev); + +struct device *class_find_device(struct class *cls, struct device *start, const void *data, int (*match)(struct device *, const void *)); + +#define for_each_available_child_of_node(parent, child) BUG(); while (0) + +u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap); +u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv); +u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv); + +int driver_register(struct device_driver *drv); +void driver_unregister(struct device_driver *drv); + +int __init netdev_boot_setup(char *str); + +static inline void eth_broadcast_addr(u8 *addr) { + memset(addr, 0xff, ETH_ALEN); } + +static inline void eth_zero_addr(u8 *addr) { + memset(addr, 0x00, ETH_ALEN); } + +static inline bool is_multicast_ether_addr(const u8 *addr) +{ + return 0x01 & addr[0]; +} + +static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2]) +{ + return is_multicast_ether_addr(addr); +} + +static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], const u8 addr2[6+2]) +{ + u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2); + + return (fold << 16) == 0; +} + +static inline bool eth_proto_is_802_3(__be16 proto) +{ + proto &= htons(0xFF00); + return (u16)proto >= (u16)htons(ETH_P_802_3_MIN); +} + +static inline unsigned long compare_ether_header(const void *a, const void *b) +{ + u32 *a32 = (u32 *)((u8 *)a + 2); + u32 *b32 = (u32 *)((u8 *)b + 2); + + return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | + (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); + +} + +bool netdev_uses_dsa(struct net_device *dev); + +enum { + IFF_LIVE_ADDR_CHANGE = 0x100000, + IFF_TX_SKB_SHARING = 0x10000, +}; + +enum { ARPHRD_ETHER = 1, }; + +struct neighbour; + +struct header_ops +{ + int (*create) (struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len); + int (*parse)(const struct sk_buff *skb, unsigned char *haddr); + int (*rebuild)(struct sk_buff *skb); + int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); + void (*cache_update)(struct hh_cache *hh, + const struct net_device *dev, + const unsigned char *haddr); +}; + +struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs); + +enum { NET_NAME_UNKNOWN = 0 }; + +int scnprintf(char *buf, size_t size, const char *fmt, ...); + +void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset); +void *skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen); +void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset); +void skb_gro_pull(struct sk_buff *skb, unsigned int len); +void skb_gro_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len); + +struct offload_callbacks +{ + struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); + int (*gro_complete)(struct sk_buff *skb, int nhoff); +}; + +struct packet_offload +{ + __be16 type; + u16 priority; + struct offload_callbacks callbacks; +}; + +struct packet_offload *gro_find_receive_by_type(__be16 type); +struct packet_offload *gro_find_complete_by_type(__be16 type); + +#define fs_initcall(x) + +void dev_add_offload(struct packet_offload *po); + +struct net_device * fec_get_my_registered_net_device(void); + +#include + +#endif /* _SRC__DRIVERS__NIC__FEC__LX_EMUL_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/lxc.c b/repos/dde_linux/src/drivers/nic/fec/lxc.c new file mode 100644 index 00000000000..d264b822416 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/lxc.c @@ -0,0 +1,65 @@ +/* + * \brief Linux emulation code + * \author Josef Soentgen + * \date 2014-03-07 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* linux includes */ +#include +#include + +/* local includes */ +#include + + +struct Skb skb_helper(struct sk_buff *skb) +{ + struct Skb helper; + + skb_push(skb, ETH_HLEN); + + helper.packet = skb->data; + helper.packet_size = ETH_HLEN; + helper.frag = 0; + helper.frag_size = 0; + + /** + * If received packets are too large (as of now 128 bytes) the actually + * payload is put into a fragment. Otherwise the payload is stored directly + * in the sk_buff. + */ + if (skb_shinfo(skb)->nr_frags) { + if (skb_shinfo(skb)->nr_frags > 1) + printk("more than 1 fragment in skb: %p nr_frags: %d", skb, + skb_shinfo(skb)->nr_frags); + + skb_frag_t *f = &skb_shinfo(skb)->frags[0]; + helper.frag = skb_frag_address(f); + helper.frag_size = skb_frag_size(f); + } + else + helper.packet_size += skb->len; + + return helper; +} + + +struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom) +{ + struct sk_buff *skb = alloc_skb(len + headroom, GFP_KERNEL | GFP_LX_DMA); + skb_reserve(skb, headroom); + return skb; +} + + +unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len) +{ + return skb_put(skb, len); +} diff --git a/repos/dde_linux/src/drivers/nic/fec/lxc.h b/repos/dde_linux/src/drivers/nic/fec/lxc.h new file mode 100644 index 00000000000..0bdad76ab7e --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/lxc.h @@ -0,0 +1,40 @@ +/* + * \brief Lx C env + * \author Josef Soentgen + * \date 2016-03-04 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LXC_H_ +#define _LXC_H_ + +/* + * The sk_buff struct contains empty array members whose + * size differs between C and C++. Since we want to access + * certain members of the sk_buff from C++ we have to use + * a uniform format useable from both languages.W + * + * Note: we pull struct skb_buff as well as size_t from + * headers included before this one. + */ +struct Skb +{ + void *packet; + size_t packet_size; + void *frag; + size_t frag_size; +}; + +struct Skb skb_helper(struct sk_buff *skb); +bool is_eapol(struct sk_buff *skb); + +struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom); +unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len); + +#endif /* _LXC_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/main.cc b/repos/dde_linux/src/drivers/nic/fec/main.cc new file mode 100644 index 00000000000..12cd0710146 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/main.cc @@ -0,0 +1,111 @@ +/* + * \brief Freescale ethernet driver + * \author Stefan Kalkowski + * \date 2017-10-19 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + +#include + +/* Linux emulation environment includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Linux module functions */ +extern "C" int module_fec_driver_init(); +extern "C" int subsys_phy_init(); +extern "C" void skb_init(); + +static void run_linux(void * m); + +struct workqueue_struct *system_wq; +struct workqueue_struct *system_power_efficient_wq; +unsigned long jiffies; + + +struct Main +{ + Genode::Env &env; + Genode::Entrypoint &ep { env.ep() }; + Genode::Attached_rom_dataspace config { env, "config" }; + Genode::Heap heap { env.ram(), env.rm() }; + Nic::Root root { env, heap }; + + /* Linux task that handles the initialization */ + Genode::Constructible linux; + + Main(Genode::Env &env) : env(env) + { + Genode::log("--- freescale ethernet driver ---"); + + Lx_kit::construct_env(env); + + /* init singleton Lx::Scheduler */ + Lx::scheduler(&env); + + //Lx::pci_init(env, env.ram(), heap); + Lx::malloc_init(env, heap); + + /* init singleton Lx::Timer */ + Lx::timer(&env, &ep, &heap, &jiffies); + + /* init singleton Lx::Irq */ + Lx::Irq::irq(&ep, &heap); + + /* init singleton Lx::Work */ + Lx::Work::work_queue(&heap); + + linux.construct(run_linux, reinterpret_cast(this), + "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); + + /* give all task a first kick before returning */ + Lx::scheduler().schedule(); + } + + void announce() { env.parent().announce(ep.manage(root)); } + + Lx::Task &linux_task() { return *linux; } +}; + + +static void run_linux(void * m) +{ + Main & main = *reinterpret_cast(m); + + system_wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + system_power_efficient_wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + + skb_init(); + subsys_phy_init(); + module_fec_driver_init(); + main.announce(); + + while (1) Lx::scheduler().current()->block_and_schedule(); +} + + +void Component::construct(Genode::Env &env) +{ + /* XXX execute constructors of global statics */ + env.exec_static_constructors(); + + static Main m(env); +} diff --git a/repos/dde_linux/src/drivers/nic/fec/platform.cc b/repos/dde_linux/src/drivers/nic/fec/platform.cc new file mode 100644 index 00000000000..a4a46dc0b79 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/platform.cc @@ -0,0 +1,39 @@ +/* + * \brief Platform driver relevant lx_kit backend functions + * \author Stefan Kalkowski + * \date 2017-11-01 + * + * Taken from the USB driver. + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +#include +#include + + +/**************************** + ** lx_kit/backend_alloc.h ** + ****************************/ + +void backend_alloc_init(Genode::Env&, Genode::Ram_session&, + Genode::Allocator&) +{ + /* intentionally left blank */ +} + + +Genode::Ram_dataspace_capability +Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) { + return Lx_kit::env().env().ram().alloc(size, cached); } + + +void Lx::backend_free(Genode::Ram_dataspace_capability cap) { + return Lx_kit::env().env().ram().free(cap); } diff --git a/repos/dde_linux/src/drivers/nic/fec/target.mk b/repos/dde_linux/src/drivers/nic/fec/target.mk new file mode 100644 index 00000000000..1a1c2eb89b0 --- /dev/null +++ b/repos/dde_linux/src/drivers/nic/fec/target.mk @@ -0,0 +1,49 @@ +REQUIRES = arm_v7 + +TARGET = nic_drv +LIBS = base lx_kit_setjmp fec_nic_include +SRC_CC = main.cc platform.cc lx_emul.cc component.cc +SRC_C += dummy.c lxc.c +INC_DIR += $(PRG_DIR) + +# lx_kit +SRC_CC += env.cc irq.cc malloc.cc scheduler.cc timer.cc work.cc printf.cc +INC_DIR += $(REP_DIR)/src/include +INC_DIR += $(REP_DIR)/src/include/spec/arm +INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 +INC_DIR += $(REP_DIR)/src/lib/usb/include/spec/arm + +# contrib code +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/nic/fec +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/net/ethernet/freescale/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/net/phy/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/net/core/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/net/ethernet/*.c)) +INC_DIR += $(LX_CONTRIB_DIR)/include + +# +# Linux sources are C89 with GNU extensions +# +CC_C_OPT += -std=gnu89 + +# +# Reduce build noise of compiling contrib code +# +CC_OPT_fec_ptp = -Wno-unused-but-set-variable -Wno-unused-variable \ + -Wno-maybe-uninitialized -Wno-uninitialized +CC_OPT_fec_main = -Wno-unused-but-set-variable -Wno-unused-variable \ + -Wno-pointer-sign -Wno-int-conversion -Wno-unused-function \ + -Wno-uninitialized +CC_OPT_skbuff = -Wno-pointer-sign -Wno-int-conversion -Wno-uninitialized +CC_OPT_mdio_bus = -Wno-implicit-int -Wno-unused-function -Wno-pointer-sign +CC_OPT_eth = -Wno-pointer-sign -Wno-unused-function +CC_OPT_phy = -Wno-unused-function -Wno-unused-but-set-variable + +vpath %.c $(LX_CONTRIB_DIR)/drivers/net/ethernet/freescale +vpath %.c $(LX_CONTRIB_DIR)/drivers/net/phy +vpath %.c $(LX_CONTRIB_DIR)/net/core +vpath %.c $(LX_CONTRIB_DIR)/net/ethernet +vpath %.cc $(PRG_DIR) +vpath %.cc $(REP_DIR)/src/lx_kit + +CC_CXX_WARN_STRICT = From 66411c50325faca86b853e30282ec92875950b70 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 28 Mar 2018 14:14:42 +0200 Subject: [PATCH 02/14] sel4: adjust network scenarios for wandboard Issue #2665 --- repos/dde_linux/src/drivers/nic/fec/lx_emul.h | 3 +++ repos/libports/run/lwip.run | 4 ++-- repos/ports/run/netperf.inc | 9 +++++---- repos/ports/run/noux_net_netcat.run | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h index 5743821eb34..12a01b3d48d 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h @@ -25,6 +25,8 @@ void lx_backtrace(void); +#define DEBUG_LINUX_PRINTK 1 + #define DEBUG 0 #if DEBUG #define TRACE \ @@ -359,6 +361,7 @@ struct net_device struct device dev; u16 gso_max_segs; struct phy_device *phydev; + char const *name; }; static inline void *netdev_priv(const struct net_device *dev) { diff --git a/repos/libports/run/lwip.run b/repos/libports/run/lwip.run index ee88787c602..cfa654a5354 100644 --- a/repos/libports/run/lwip.run +++ b/repos/libports/run/lwip.run @@ -102,8 +102,8 @@ append_if $use_usb_driver config { append_platform_drv_config append_if $use_nic_driver config { - - + + } diff --git a/repos/ports/run/netperf.inc b/repos/ports/run/netperf.inc index 5447f0433a6..7029f9eaeac 100644 --- a/repos/ports/run/netperf.inc +++ b/repos/ports/run/netperf.inc @@ -97,7 +97,7 @@ create_boot_directory set lx_ip_addr "10.0.2.55" set config { - + @@ -158,8 +158,9 @@ append_if $use_usb_driver config { } append_if $use_nic_driver config { - - + + + } @@ -222,7 +223,7 @@ append_if $use_wifi_driver config { append_platform_drv_config append config { - + } append config "" append config { diff --git a/repos/ports/run/noux_net_netcat.run b/repos/ports/run/noux_net_netcat.run index e5fadffc93d..c7692a953ed 100644 --- a/repos/ports/run/noux_net_netcat.run +++ b/repos/ports/run/noux_net_netcat.run @@ -103,8 +103,8 @@ append config { } append_if $use_nic_driver config { - - + + } From 7ad2c46858a8e50c5d41ed7281ac63d17348421d Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 26 Mar 2018 14:07:52 +0200 Subject: [PATCH 03/14] wandboard: improve memory usage of ethernet driver Use a 8K slab entry instead of 16K slab entry, per 2K network packet. Issue #2665 --- .../dde_linux/src/drivers/nic/fec/lx_emul.cc | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc index 6705c883a60..641f2e2eb6c 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -403,13 +403,16 @@ void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t, int) } +void get_page(struct page *page) +{ + atomic_inc(&page->_count); +} -struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) + +static struct page *allocate_pages(gfp_t gfp_mask, size_t const size) { struct page *page = (struct page *)kzalloc(sizeof(struct page), 0); - size_t size = PAGE_SIZE << order; - page->addr = Lx::Malloc::dma().alloc(size, 12); if (!page->addr) { @@ -426,17 +429,18 @@ struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) } -void get_page(struct page *page) +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) { - atomic_inc(&page->_count); + size_t const size = PAGE_SIZE << order; + return allocate_pages(gfp_mask, size); } -void *__alloc_page_frag(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask) +void *__alloc_page_frag(struct page_frag_cache *, unsigned int const fragsz, + gfp_t const gfp_mask) { - struct page *page = alloc_pages(GFP_LX_DMA, fragsz / PAGE_SIZE); - if (!page) return nullptr; - return page->addr; + struct page *page = allocate_pages(gfp_mask, fragsz); + return page ? page->addr : page; } From 24807c85453242db45c474e27235460e8ea73f7d Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 9 Apr 2018 14:43:29 +0200 Subject: [PATCH 04/14] dde_linux: enable more platforms for nic_drv In addition to the i.MX6Q SoC, the Freescale network driver works now on i.MX6SX and i.MX53 SoCs. Ref #2749 --- repos/dde_linux/fec.list | 2 + .../dde_linux/patches/fec_tx_bounce_dma.patch | 13 + repos/dde_linux/ports/dde_linux.hash | 2 +- repos/dde_linux/ports/dde_linux.port | 1 + .../src/drivers/nic/fec/component.cc | 20 +- .../dde_linux/src/drivers/nic/fec/component.h | 64 +- repos/dde_linux/src/drivers/nic/fec/dummy.c | 69 -- .../dde_linux/src/drivers/nic/fec/lx_emul.cc | 617 +++++++++++++++--- repos/dde_linux/src/drivers/nic/fec/lx_emul.h | 28 +- repos/dde_linux/src/drivers/nic/fec/main.cc | 16 +- repos/dde_linux/src/drivers/nic/fec/target.mk | 1 + 11 files changed, 630 insertions(+), 203 deletions(-) create mode 100644 repos/dde_linux/patches/fec_tx_bounce_dma.patch diff --git a/repos/dde_linux/fec.list b/repos/dde_linux/fec.list index 90e72bd7206..9f83f66c258 100644 --- a/repos/dde_linux/fec.list +++ b/repos/dde_linux/fec.list @@ -4,6 +4,7 @@ linux-x.x.x/drivers/net/ethernet/freescale/fec_ptp.c linux-x.x.x/drivers/net/phy/mdio_bus.c linux-x.x.x/drivers/net/phy/phy_device.c linux-x.x.x/drivers/net/phy/phy.c +linux-x.x.x/drivers/net/phy/at803x.c linux-x.x.x/net/core/skbuff.c linux-x.x.x/net/ethernet/eth.c linux-x.x.x/include/asm-generic/atomic64.h @@ -15,6 +16,7 @@ linux-x.x.x/include/asm-generic/bitops/fls.h linux-x.x.x/include/asm-generic/bitops/fls64.h linux-x.x.x/include/linux/errqueue.h linux-x.x.x/include/linux/fec.h +linux-x.x.x/include/linux/gpio/consumer.h linux-x.x.x/include/linux/if_ether.h linux-x.x.x/include/linux/list.h linux-x.x.x/include/linux/list_nulls.h diff --git a/repos/dde_linux/patches/fec_tx_bounce_dma.patch b/repos/dde_linux/patches/fec_tx_bounce_dma.patch new file mode 100644 index 00000000000..4b0b4ee7786 --- /dev/null +++ b/repos/dde_linux/patches/fec_tx_bounce_dma.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index b2a3220..18629c6 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -2825,7 +2825,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) + txq = fep->tx_queue[queue]; + bdp = txq->tx_bd_base; + for (i = 0; i < txq->tx_ring_size; i++) { +- txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); ++ txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL | GFP_LX_DMA); + if (!txq->tx_bounce[i]) + goto err_alloc; + diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index f9231242fb5..f9ab7d4ebe8 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -82b2f79a8ecbbfeb42de534b776c6b348573bd60 +7f9bd747fe1d1ca7e19a46100b0f4d125698a5d4 diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index 0453f60ae34..9ea97b483b1 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -207,5 +207,6 @@ PATCH_OPT(patches/intel_fb_export_api.patch) := -p1 -d$(SRC_DIR_INTEL_FB) # Freescale NIC PATCH_OPT(patches/fec_skbuff_cast.patch) := -p1 -d$(SRC_DIR_FEC) +PATCH_OPT(patches/fec_tx_bounce_dma.patch) := -p1 -d$(SRC_DIR_FEC) # vi: set ft=make : diff --git a/repos/dde_linux/src/drivers/nic/fec/component.cc b/repos/dde_linux/src/drivers/nic/fec/component.cc index 13e404e979a..fdac2710e3d 100644 --- a/repos/dde_linux/src/drivers/nic/fec/component.cc +++ b/repos/dde_linux/src/drivers/nic/fec/component.cc @@ -130,8 +130,7 @@ void Session_component::unblock_rx_task(napi_struct * n) Nic::Mac_address Session_component::mac_address() { - net_device * dev = fec_get_my_registered_net_device(); - return dev ? Nic::Mac_address(dev->dev_addr) : Nic::Mac_address(); + return _ndev ? Nic::Mac_address(_ndev->dev_addr) : Nic::Mac_address(); } @@ -170,11 +169,14 @@ void Session_component::link_state(bool link) } -Session_component::Session_component(Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size, - Genode::Allocator & rx_block_md_alloc, - Genode::Env & env) +Session_component::Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env, + Genode::Session_label label) : Nic::Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, env), - _ndev(fec_get_my_registered_net_device()), - _has_link(!(_ndev->state & (1UL << __LINK_STATE_NOCARRIER))) { - _register_session_component(*this); } + _ndev(_register_session_component(*this, label)), + _has_link(_ndev ? !(_ndev->state & (1UL << __LINK_STATE_NOCARRIER)) : false) +{ + if (!_ndev) throw Genode::Service_denied(); +} diff --git a/repos/dde_linux/src/drivers/nic/fec/component.h b/repos/dde_linux/src/drivers/nic/fec/component.h index cf1f0b75905..09ae2891739 100644 --- a/repos/dde_linux/src/drivers/nic/fec/component.h +++ b/repos/dde_linux/src/drivers/nic/fec/component.h @@ -15,7 +15,8 @@ #define _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ /* Genode includes */ -#include +#include +#include #include @@ -47,7 +48,8 @@ class Session_component : public Nic::Session_component static void _run_tx_task(void * args); static void _run_rx_task(void * args); - static void _register_session_component(Session_component &); + static net_device * _register_session_component(Session_component &, + Genode::Session_label); Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task", Lx::Task::PRIORITY_1, Lx::scheduler() }; @@ -60,10 +62,11 @@ class Session_component : public Nic::Session_component public: - Session_component(Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size, - Genode::Allocator & rx_block_md_alloc, - Genode::Env & env); + Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env, + Genode::Session_label label); Nic::Mac_address mac_address() override; bool link_state() override { return _has_link; } @@ -72,4 +75,53 @@ class Session_component : public Nic::Session_component void unblock_rx_task(napi_struct * n); }; + +class Root : public Genode::Root_component +{ + private: + + Genode::Env &_env; + Genode::Allocator &_md_alloc; + + protected: + + Session_component *_create_session(const char *args) + { + using namespace Genode; + + Session_label const label = label_from_args(args); + + size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); + size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + size_t rx_buf_size = Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); + + /* deplete ram quota by the memory needed for the session structure */ + size_t session_size = max(4096UL, (unsigned long)sizeof(Session_component)); + if (ram_quota < session_size) + throw Genode::Insufficient_ram_quota(); + + /* + * Check if donated ram quota suffices for both communication + * buffers and check for overflow + */ + if (tx_buf_size + rx_buf_size < tx_buf_size || + tx_buf_size + rx_buf_size > ram_quota - session_size) { + Genode::error("insufficient 'ram_quota', got ", ram_quota, ", " + "need ", tx_buf_size + rx_buf_size + session_size); + throw Genode::Insufficient_ram_quota(); + } + + return new (Root::md_alloc()) + Session_component(tx_buf_size, rx_buf_size, + _md_alloc, _env, label); + } + + public: + + Root(Genode::Env &env, Genode::Allocator &md_alloc) + : Genode::Root_component(&env.ep().rpc_ep(), &md_alloc), + _env(env), _md_alloc(md_alloc) + { } +}; + #endif /* _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/dummy.c b/repos/dde_linux/src/drivers/nic/fec/dummy.c index b1e3239a15f..05d3a03d1be 100644 --- a/repos/dde_linux/src/drivers/nic/fec/dummy.c +++ b/repos/dde_linux/src/drivers/nic/fec/dummy.c @@ -34,12 +34,6 @@ int disable_irq(unsigned int irq) return -1; } -int disable_irq_nosync(unsigned int irq) -{ - TRACE_AND_STOP; - return -1; -} - int disable_irq_wake(unsigned int irq) { TRACE_AND_STOP; @@ -62,12 +56,6 @@ int enable_irq_wake(unsigned int irq) return -1; } -int enable_irq(unsigned int irq) -{ - TRACE_AND_STOP; - return -1; -} - void eth_hw_addr_random(struct net_device *dev) { TRACE_AND_STOP; @@ -170,53 +158,18 @@ struct timespec64 ns_to_timespec64(const s64 nsec) return ret; } -bool of_device_is_available(const struct device_node *device) -{ - TRACE_AND_STOP; - return -1; -} - -const void *of_get_mac_address(struct device_node *np) -{ - TRACE_AND_STOP; - return NULL; -} - -int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) -{ - TRACE_AND_STOP; - return -1; -} - struct device_node *of_node_get(struct device_node *node) { TRACE_AND_STOP; return NULL; } -void of_node_put(struct device_node *node) -{ - TRACE_AND_STOP; -} - -struct phy_device *of_phy_connect(struct net_device *dev, struct device_node *phy_np, void (*hndlr)(struct net_device *), u32 flags, int iface) -{ - TRACE_AND_STOP; - return NULL; -} - int of_phy_register_fixed_link(struct device_node *np) { TRACE_AND_STOP; return -1; } -int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) -{ - TRACE_AND_STOP; - return -1; -} - void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event) { TRACE_AND_STOP; @@ -246,16 +199,6 @@ resource_size_t resource_size(const struct resource *res) return -1; } -void rtnl_lock(void) -{ - TRACE_AND_STOP; -} - -void rtnl_unlock(void) -{ - TRACE_AND_STOP; -} - bool page_is_pfmemalloc(struct page *page) { TRACE_AND_STOP; @@ -289,12 +232,6 @@ u64 timecounter_cyc2time(struct timecounter *tc, cycle_t cycle_tstamp) return -1; } -u64 timecounter_read(struct timecounter *tc) -{ - TRACE_AND_STOP; - return -1; -} - void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) { TRACE_AND_STOP; @@ -342,12 +279,6 @@ int strcmp(const char *s1, const char *s2) return -1; } -int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) -{ - TRACE_AND_STOP; - return -1; -} - void class_unregister(struct class *cls) { TRACE_AND_STOP; diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc index 641f2e2eb6c..8f8d6b9e945 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -16,8 +16,11 @@ * prevent shenanigans with macro definitions. */ #include +#include #include #include +#include +#include #include #include @@ -40,7 +43,6 @@ class Addr_to_page_mapping : public Genode::List::Element { private: - unsigned long _addr { 0 }; struct page *_page { nullptr }; static Genode::List & _list() @@ -51,14 +53,13 @@ class Addr_to_page_mapping : public Genode::List::Element public: - Addr_to_page_mapping(unsigned long addr, struct page *page) - : _addr(addr), _page(page) { } + Addr_to_page_mapping(struct page *page) + : _page(page) { } static void insert(struct page * page) { Addr_to_page_mapping *m = (Addr_to_page_mapping*) Lx::Malloc::mem().alloc(sizeof (Addr_to_page_mapping)); - m->_addr = (unsigned long)page->addr; m->_page = page; _list().insert(m); } @@ -66,7 +67,7 @@ class Addr_to_page_mapping : public Genode::List::Element static struct page * remove(unsigned long addr) { for (Addr_to_page_mapping *m = _list().first(); m; m = m->next()) - if (m->_addr == addr) { + if ((unsigned long)m->_page->addr == addr) { struct page * ret = m->_page; _list().remove(m); Lx::Malloc::mem().free(m); @@ -75,6 +76,15 @@ class Addr_to_page_mapping : public Genode::List::Element return nullptr; } + + static struct page * find_page(void* addr) + { + for (Addr_to_page_mapping *m = _list().first(); m; m = m->next()) + if ((unsigned long)m->_page->addr <= (unsigned long)addr && + ((unsigned long)m->_page->addr + m->_page->size) > (unsigned long)addr) + return m->_page; + return nullptr; + } }; @@ -145,10 +155,149 @@ class Driver : public Genode::List::Element } }; -static Session_component * session = nullptr; -void Session_component::_register_session_component(Session_component & s) { - session = &s; } +struct Gpio_irq : public Genode::List::Element +{ + unsigned irq_nr; + bool enabled = true; + bool pending = false; + Gpio::Connection gpio; + Genode::Irq_session_client irq; + Genode::Signal_handler sigh; + Lx::Task task; + irq_handler_t ihandler; + void * dev_id; + + /** + * List of all currently registered irqs + */ + static Genode::List *list() + { + static Genode::List _list; + return &_list; + } + + static void run_irq(void *args) + { + Gpio_irq * girq = static_cast(args); + while (1) { + Lx::scheduler().current()->block_and_schedule(); + girq->ihandler(girq->irq_nr, girq->dev_id); + girq->irq.ack_irq(); + } + } + + void unblock() + { + if (enabled) task.unblock(); + + pending = !enabled; + } + + void enable() + { + enabled = true; + if (pending) unblock(); + } + + void disable() + { + enabled = false; + } + + Gpio_irq(Genode::Env &env, unsigned nr, irq_handler_t handler, void * dev_id) + : irq_nr(nr), + gpio(env, nr), + irq(gpio.irq_session(Gpio::Session::LOW_LEVEL)), + sigh(env.ep(), *this, &Gpio_irq::unblock), + task(run_irq, this, "gpio_irq", Lx::Task::PRIORITY_3, Lx::scheduler()), + ihandler(handler), + dev_id(dev_id) + { + list()->insert(this); + + irq.sigh(sigh); + irq.ack_irq(); + } +}; + + +struct Fec +{ + using String = Genode::String<128>; + + struct Mdio + { + struct Phy + { + String name; + String phy_driver; + const unsigned phy_reg; + const unsigned gpio_irq; + struct phy_device * phy_dev { nullptr }; + + Phy(String name, String driver, const unsigned reg, const unsigned irq) + : name(name), phy_driver(driver), phy_reg(reg), gpio_irq(irq) {} + }; + + enum { MAX = 10 }; + Genode::Constructible phys[MAX]; + + template + void for_each(FUNC && f) + { + for (unsigned i = 0; i < MAX; i++) + if (phys[i].constructed()) f(*phys[i]); + } + }; + + String name; + String device; + const unsigned irq; + const size_t mmio; + String phy_mode; + const bool magic_packet; + const int tx_queues; + const int rx_queues; + struct net_device * net_dev { nullptr }; + Session_component * session { nullptr }; + Genode::Attached_io_mem_dataspace io_ds { Lx_kit::env().env(), mmio, 0x4000 }; + Genode::Constructible mdio; + Mdio::Phy * phy { nullptr }; + + Fec(String name, String device, const unsigned irq, + const size_t mmio, String mode, const bool magic = true, + const int tx_queues = 1, const int rx_queues = 1) + : name(name), device(device), irq(irq), mmio(mmio), phy_mode(mode), magic_packet(magic), + tx_queues(tx_queues), rx_queues(rx_queues) {}; +}; + + +static const unsigned FEC_MAX = 2; +static Genode::Constructible fec_devices[FEC_MAX]; + +net_device * Session_component::_register_session_component(Session_component & s, + Genode::Session_label policy) +{ + Genode::Session_label name = policy.last_element(); + + for (unsigned i = 0; i < FEC_MAX; i++) { + + /* No more cards available */ + if (!fec_devices[i].constructed()) return nullptr; + + /* Session does not match cards policy */ + if (fec_devices[i]->name.length() > 1 && + fec_devices[i]->name != name) continue; + + /* Session already in use */ + if (fec_devices[i]->session) return nullptr; + + fec_devices[i]->session = &s; + return fec_devices[i]->net_dev; + } + return nullptr; +} #include @@ -158,18 +307,78 @@ void Session_component::_register_session_component(Session_component & s) { extern "C" { -void lx_backtrace() -{ - Genode::backtrace(); -} - +void lx_backtrace() { Genode::backtrace(); } int platform_driver_register(struct platform_driver * drv) { - static platform_device pd_fec; - static const char * name = "2188000.ethernet"; - pd_fec.name = name; - return drv->probe(&pd_fec); + using String = Fec::String; + + try { + unsigned i = 0; + Genode::Attached_rom_dataspace config { Lx_kit::env().env(), "config" }; + config.xml().for_each_sub_node("card", [&] (Genode::Xml_node const node) { + if (i == FEC_MAX) { + Genode::error("More cards defined than available!"); + return; + } + + String name = node.attribute_value("name", String()); + String type = node.attribute_value("type", String()); + String mdio = node.attribute_value("mii", String()); + String phy = node.attribute_value("phy", String()); + unsigned irq = node.attribute_value("irq", 0UL); + Genode::addr_t mmio = node.attribute_value("mmio", 0UL); + bool magic = node.attribute_value("magic_packet", true); + unsigned txq = node.attribute_value("tx-queues", 1UL); + unsigned rxq = node.attribute_value("rx-queues", 1UL); + fec_devices[i].construct(name, type, irq, mmio, mdio, magic, txq, rxq); + + node.for_each_sub_node("mdio", [&] (Genode::Xml_node const node) { + fec_devices[i]->mdio.construct(); + unsigned j = 0; + node.for_each_sub_node("phy", [&] (Genode::Xml_node const node) { + String name = node.attribute_value("name", String()); + String type = node.attribute_value("type", String()); + unsigned irq = node.attribute_value("gpio_irq", 0UL); + unsigned reg = node.attribute_value("reg_num", 0UL); + fec_devices[i]->mdio->phys[j].construct(name, type, reg, irq); + j++; + }); + }); + + for (unsigned k = 0; k <= i; k++) + if (fec_devices[k]->mdio.constructed()) { + fec_devices[k]->mdio->for_each([&] (Fec::Mdio::Phy & p) { + if (p.name == phy) fec_devices[i]->phy = &p; }); + } + + i++; + }); + } catch(...) { } + + if (!fec_devices[0].constructed()) { + Genode::warning("No valid configuration provided, use default values"); + fec_devices[0].construct(String(), "fsl,imx6q-fec", 150, 0x2188000, "rgmii"); + } + + for (unsigned i = 0; i < FEC_MAX; i++) { + if (!fec_devices[i].constructed()) break; + + platform_device * pd = new (Lx::Malloc::dma()) platform_device(); + pd->name = fec_devices[i]->name.string(); + pd->dev.of_node = (device_node*) &fec_devices[i]; + pd->dev.plat_dev = pd; + drv->probe(pd); + { + net_device * dev = fec_devices[i]->net_dev; + int err = dev ? dev->netdev_ops->ndo_open(dev) : -1; + if (err) { + Genode::error("ndo_open() failed: ", err); + return err; + } + } + } + return 0; } @@ -191,6 +400,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev->gso_max_segs = GSO_MAX_SEGS; + setup(dev); + static const struct ethtool_ops default_ethtool_ops { }; if (!dev->ethtool_ops) dev->ethtool_ops = &default_ethtool_ops; @@ -200,34 +411,45 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, } +bool of_device_is_available(const struct device_node *device) +{ + return device; +} + + const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev) { + Fec * fec = (Fec*) dev->plat_dev->dev.of_node; for (; matches && matches->compatible[0]; matches++) - if (Genode::strcmp(matches->compatible, "fsl,imx6q-fec") == 0) + if (Genode::strcmp(matches->compatible, fec->device.string()) == 0) return matches; - return NULL; + return nullptr; } void * devm_ioremap_resource(struct device *dev, struct resource *res) { - static Genode::Attached_io_mem_dataspace io_ds(Lx_kit::env().env(), - 0x2188000, 0x1000); + Fec * fec = (Fec*) dev->plat_dev->dev.of_node; - return io_ds.local_addr(); + return fec->io_ds.local_addr(); } void platform_set_drvdata(struct platform_device *pdev, void *data) { pdev->dev.driver_data = data; + struct net_device * ndev = (net_device*)data; + ndev->dev.of_node = pdev->dev.of_node; } int of_get_phy_mode(struct device_node *np) { + Fec * fec = (Fec*) np; + for (int i = 0; i < PHY_INTERFACE_MODE_MAX; i++) - if (!Genode::strcmp("rgmii", phy_modes((phy_interface_t)i))) + if (!Genode::strcmp(fec->phy_mode.string(), + phy_modes((phy_interface_t)i))) return i; return -ENODEV; @@ -255,11 +477,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { void *addr = Lx::Malloc::dma().alloc_large(size); + dma_addr_t dma_addr = (dma_addr_t) Lx::Malloc::dma().phys_addr(addr); - static unsigned waechter = 0; - ASSERT(!waechter++); - - *dma_handle = (dma_addr_t) addr; + *dma_handle = (dma_addr_t) dma_addr; return addr; } @@ -267,7 +487,12 @@ void *dma_alloc_coherent(struct device *dev, size_t size, void *dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { dma_addr_t dma_addr; - void *addr = Lx::Malloc::dma().alloc(size, 12, &dma_addr); + void *addr; + if (size > 2048) { + addr = Lx::Malloc::dma().alloc_large(size); + dma_addr = (dma_addr_t) Lx::Malloc::dma().phys_addr(addr); + } else + addr = Lx::Malloc::dma().alloc(size, 12, &dma_addr); *dma_handle = dma_addr; return addr; @@ -279,9 +504,18 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, { dma_addr_t dma_addr = (dma_addr_t) Lx::Malloc::dma().phys_addr(cpu_addr); - if (dma_addr == ~0UL) - Genode::error(__func__, ": virtual address ", cpu_addr, - " not registered for DMA"); + if (dma_addr == ~0UL) { + + struct page * p = Addr_to_page_mapping::find_page(cpu_addr); + if (p) { + dma_addr = (dma_addr_t) Lx::Malloc::dma().phys_addr(p->addr); + dma_addr += (dma_addr_t)cpu_addr - (dma_addr_t)p->addr; + } + + if (dma_addr == ~0UL) + Genode::error(__func__, ": virtual address ", cpu_addr, + " not registered for DMA"); + } return dma_addr; } @@ -308,14 +542,18 @@ int netif_running(const struct net_device *dev) void netif_carrier_on(struct net_device *dev) { dev->state &= ~(1UL << __LINK_STATE_NOCARRIER); - if (session) session->link_state(true); + + Fec * fec = (Fec*) dev->dev.of_node; + if (fec->session) fec->session->link_state(true); } void netif_carrier_off(struct net_device *dev) { dev->state |= 1UL << __LINK_STATE_NOCARRIER; - if (session) session->link_state(false); + + Fec * fec = (Fec*) dev->dev.of_node; + if (fec->session) fec->session->link_state(false); } @@ -331,7 +569,9 @@ int platform_get_irq(struct platform_device * d, unsigned int i) { if (i > 1) return -1; - return 150 + i; + Fec * fec = (Fec*) d->dev.of_node; + + return fec->irq + i; } @@ -346,14 +586,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id) { static struct clk clocks[] { { "ipg", 66*1000*1000 }, - { "ahb", 132*1000*1000 }, - { "enet_clk_ref", 500*1000*1000 } }; + { "ahb", 198*1000*1000 }, + { "ptp", 25*1000*1000 }, + { "enet_out", 25*1000*1000 }, + { "enet_clk_ref", 125*1000*1000 } }; for (unsigned i = 0; i < (sizeof(clocks) / sizeof(struct clk)); i++) if (Genode::strcmp(clocks[i].name, id) == 0) return &clocks[i]; - return NULL; + Genode::error("MISSING CLOCK: ", id); + return nullptr; } @@ -372,31 +615,17 @@ int is_valid_ether_addr(const u8 * a) } -static struct net_device * my_net_device = nullptr; - - int register_netdev(struct net_device * d) { - my_net_device = d; - d->state |= (1 << __LINK_STATE_START) | (1UL << __LINK_STATE_NOCARRIER); - int err = d->netdev_ops->ndo_open(d); - if (err) { - Genode::error("ndo_open() failed: ", err); - return err; - } + Fec * fec = (Fec*) d->dev.of_node; + fec->net_dev = d; return 0; } -struct net_device * fec_get_my_registered_net_device() -{ - return my_net_device; -} - - void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t, int) { return (void*)cache->alloc(); @@ -413,7 +642,8 @@ static struct page *allocate_pages(gfp_t gfp_mask, size_t const size) { struct page *page = (struct page *)kzalloc(sizeof(struct page), 0); - page->addr = Lx::Malloc::dma().alloc(size, 12); + page->addr = Lx::Malloc::dma().alloc_large(size); + page->size = size; if (!page->addr) { Genode::error("alloc_pages: ", size, " failed"); @@ -451,7 +681,7 @@ void __free_page_frag(void *addr) if (!atomic_dec_and_test(&page->_count)) Genode::error("page reference count != 0"); - Lx::Malloc::dma().free(page->addr); + Lx::Malloc::dma().free_large(page->addr); kfree(page); } @@ -513,7 +743,7 @@ long __wait_completion(struct completion *work, unsigned long timeout) if (timeout) { setup_timer(&t, _completion_timeout, (unsigned long)Lx::scheduler().current()); - mod_timer(&t, timeout); + mod_timer(&t, j); } while (!work->done) { @@ -533,14 +763,7 @@ long __wait_completion(struct completion *work, unsigned long timeout) work->done = 0; - return j ? j - jiffies : 1; -} - - -int request_module(const char *format, ...) -{ - TRACE; - return 0; + return (j || j == jiffies) ? 1 : j - jiffies; } @@ -599,13 +822,6 @@ int dev_set_name(struct device *dev, const char *fmt, ...) } -int bus_register(struct bus_type *bus) -{ - TRACE; - return 0; -} - - struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name) { for (Device *dev = Device::list()->first(); dev; dev = dev->next()) { @@ -656,7 +872,8 @@ void napi_disable(struct napi_struct *n) void __napi_schedule(struct napi_struct *n) { - if (session) session->unblock_rx_task(n); + Fec * fec = (Fec*) n->dev->dev.of_node; + if (fec->session) fec->session->unblock_rx_task(n); } @@ -687,7 +904,8 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsig gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { - if (session) session->receive(skb); + Fec * fec = (Fec*) napi->dev->dev.of_node; + if (fec->session) fec->session->receive(skb); dev_kfree_skb(skb); return GRO_NORMAL; @@ -709,6 +927,192 @@ bool netif_queue_stopped(const struct net_device *dev) } +struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index) +{ + Fec * fec = (Fec*) np; + return (device_node*) fec->phy; +} + + +struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), + u32 flags, int iface) +{ + Fec::Mdio::Phy * phy = (Fec::Mdio::Phy*) phy_np; + struct phy_device * phydev = phy ? phy->phy_dev : nullptr; + if (!phydev) return nullptr; + + phydev->dev_flags = flags; + int ret = phy_connect_direct(dev, phydev, hndlr, (phy_interface_t)iface); + return ret ? nullptr : phydev; +} + + +struct device_node *of_get_child_by_name(const struct device_node *node, + const char *name) +{ + if (Genode::strcmp("mdio", name) != 0) return nullptr; + + Fec * fec = (Fec*) node; + return fec->mdio.constructed() ? (device_node*) &*fec->mdio : nullptr; +} + + +static int of_mdiobus_register_phy(Fec::Mdio::Phy & ph, struct mii_bus *mdio) +{ + struct phy_device * phy = get_phy_device(mdio, ph.phy_reg, false); + + if (!phy || IS_ERR(phy)) return 1; + + phy->irq = ph.gpio_irq; + phy->dev.of_node = (device_node*) &ph; + + /* All data is now stored in the phy struct; + * register it */ + int rc = phy_device_register(phy); + if (rc) { + phy_device_free(phy); + return 1; + } + + ph.phy_dev = phy; + + dev_dbg(&mdio->dev, "registered phy at address %i\n", ph.phy_reg); + + return 0; +} + +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +{ + Fec::Mdio * fec_m = (Fec::Mdio*) np; + + mdio->phy_mask = ~0; + + /* Clear all the IRQ properties */ + if (mdio->irq) + for (unsigned i = 0; iirq[i] = PHY_POLL; + + mdio->dev.of_node = np; + + /* Register the MDIO bus */ + int rc = mdiobus_register(mdio); + if (rc) return rc; + + fec_m->for_each([&] (Fec::Mdio::Phy & phy) { + of_mdiobus_register_phy(phy, mdio); }); + return 0; +} + + +int of_driver_match_device(struct device *dev, const struct device_driver *drv) +{ + Fec::Mdio::Phy * phy = (Fec::Mdio::Phy*) dev->of_node; + + return phy ? (Genode::strcmp(drv->name, + phy->phy_driver.string()) == 0) : 0; +} + + +const void *of_get_property(const struct device_node *node, const char *name, int *lenp) +{ + Fec * fec = (Fec*) node; + if (Genode::strcmp("fsl,magic-packet", name) == 0) return (void*)fec->magic_packet; + + TRACE_AND_STOP; + return nullptr; +} + + +int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) +{ + Fec * fec = (Fec*) np; + + if (Genode::strcmp("max-speed", propname) == 0) return 1; + + if ((Genode::strcmp("fsl,num-tx-queues", propname) == 0) && fec->tx_queues) + *out_value = fec->tx_queues; + else if ((Genode::strcmp("fsl,num-rx-queues", propname) == 0) && fec->rx_queues) + *out_value = fec->rx_queues; + else + TRACE_AND_STOP; + + return 0; +} + + +void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) +{ + if (size > 2048) Genode::warning("devm_kzalloc ", size); + return Lx::Malloc::mem().alloc(size); +} + + +int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) +{ + new (Lx::Malloc::mem()) Gpio_irq(Lx_kit::env().env(), irq, handler, dev); + return 0; +} + + +int enable_irq(unsigned int irq) +{ + for (Gpio_irq *girq = Gpio_irq::list()->first(); girq; girq = girq->next()) + if (girq->irq_nr == irq) { + girq->enable(); + return 0; + } + return 1; +} + + +int disable_irq_nosync(unsigned int irq) +{ + for (Gpio_irq *girq = Gpio_irq::list()->first(); girq; girq = girq->next()) + if (girq->irq_nr == irq) { + girq->disable(); + return 0; + } + return 1; +} + + +struct device_node *of_get_next_available_child(const struct device_node *node, struct device_node *prev) +{ + TRACE_AND_STOP; + return nullptr; +} + + +u64 timecounter_read(struct timecounter *tc) +{ + u64 nsec; + + cycle_t cycle_now, cycle_delta; + + /* increment time by nanoseconds since last call */ + { + /* read cycle counter: */ + cycle_now = tc->cc->read(tc->cc); + + /* calculate the delta since the last timecounter_read_delta(): */ + cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask; + + /* convert to nanoseconds: */ + nsec = cyclecounter_cyc2ns(tc->cc, cycle_delta, + tc->mask, &tc->frac); + + /* update time stamp of timecounter_read_delta() call: */ + tc->cycle_last = cycle_now; + } + + nsec += tc->nsec; + tc->nsec = nsec; + + return nsec; +} + /********************* ** DUMMY FUNCTIONS ** *********************/ @@ -738,31 +1142,13 @@ int device_init_wakeup(struct device *dev, bool val) struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id) { TRACE; - return NULL; -} - -struct device_node *of_get_child_by_name( const struct device_node *node, const char *name) -{ - TRACE; - return NULL; + return nullptr; } struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, unsigned int index) { TRACE; - return NULL; -} - -const void *of_get_property(const struct device_node *node, const char *name, int *lenp) -{ - TRACE; - return NULL; -} - -struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index) -{ - TRACE; - return NULL; + return nullptr; } bool of_phy_is_fixed_link(struct device_node *np) @@ -786,7 +1172,7 @@ int pinctrl_pm_select_sleep_state(struct device *dev) struct resource *platform_get_resource(struct platform_device * d, unsigned r1, unsigned r2) { TRACE; - return NULL; + return nullptr; } void pm_runtime_enable(struct device *dev) @@ -818,7 +1204,7 @@ void pm_runtime_use_autosuspend(struct device *dev) struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, struct device *parent) { TRACE; - return NULL; + return (ptp_clock*)0xdeadbeef; } int regulator_enable(struct regulator * d) @@ -827,12 +1213,6 @@ int regulator_enable(struct regulator * d) return 0; } -int of_driver_match_device(struct device *dev, const struct device_driver *drv) -{ - TRACE; - return 0; -} - int class_register(struct class_ *cls) { TRACE; @@ -848,7 +1228,7 @@ int try_module_get(struct module *mod) struct device *get_device(struct device *dev) { TRACE; - return NULL; + return dev; } int device_bind_driver(struct device *dev) @@ -911,4 +1291,37 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, TRACE; } +void of_node_put(struct device_node *node) +{ + TRACE; +} + +const void *of_get_mac_address(struct device_node *np) +{ + TRACE; + return nullptr; +} + +void rtnl_lock(void) +{ + TRACE; +} + +void rtnl_unlock(void) +{ + TRACE; +} + +int request_module(const char *fmt, ...) +{ + TRACE; + return 0; +} + +int bus_register(struct bus_type *bus) +{ + TRACE; + return 0; +} + } diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h index 12a01b3d48d..23ab82de675 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h @@ -25,7 +25,7 @@ void lx_backtrace(void); -#define DEBUG_LINUX_PRINTK 1 +#define DEBUG_LINUX_PRINTK 0 #define DEBUG 0 #if DEBUG @@ -87,7 +87,7 @@ size_t iov_iter_count(struct iov_iter *i); #define dev_notice(dev, format, arg...) lx_printf("dev_notice: " format , ## arg) #define dev_crit( dev, format, arg...) lx_printf("dev_crit: " format , ## arg) #if DEBUG -#define dev_dbg( dev, format, arg...) lx_printf("dev_dbg: " format , ## arg) +#define dev_dbg( dev, format, arg...) printk("dev_dbg: " format , ## arg) #else #define dev_dbg( dev, format, arg...) #endif @@ -240,6 +240,8 @@ struct attribute_group struct attribute ** attrs; }; +struct platform_device; + struct device { char name[32]; struct device * parent; @@ -251,6 +253,7 @@ struct device { struct bus_type *bus; struct class *class; struct device_node *of_node; + struct platform_device * plat_dev; }; struct platform_device { @@ -340,8 +343,9 @@ enum netdev_state_t { struct net_device { - unsigned long state; - netdev_features_t features; + const char * name; + unsigned long state; + netdev_features_t features; struct net_device_stats stats; netdev_features_t hw_features; const struct net_device_ops *netdev_ops; @@ -358,10 +362,10 @@ struct net_device unsigned char broadcast[MAX_ADDR_LEN]; unsigned long tx_queue_len; int watchdog_timeo; + struct timer_list watchdog_timer; struct device dev; u16 gso_max_segs; struct phy_device *phydev; - char const *name; }; static inline void *netdev_priv(const struct net_device *dev) { @@ -479,6 +483,7 @@ struct page void *addr; dma_addr_t paddr; unsigned long private; + unsigned long size; } __attribute((packed)); static inline struct page *compound_head(struct page *page) { return page; } @@ -585,8 +590,10 @@ void netif_tx_stop_queue(struct netdev_queue *dev_queue); void netif_tx_wake_queue(struct netdev_queue *dev_queue); bool netif_queue_stopped(const struct net_device *dev); +#define CONFIG_ARM 1 #define CONFIG_ARCH_MXC 1 #define CONFIG_OF_MDIO 1 +#define CONFIG_PTP_1588_CLOCK 1 void rtnl_lock(void); void rtnl_unlock(void); @@ -1351,7 +1358,11 @@ void device_release_driver(struct device *dev); struct device *class_find_device(struct class *cls, struct device *start, const void *data, int (*match)(struct device *, const void *)); -#define for_each_available_child_of_node(parent, child) BUG(); while (0) +struct device_node *of_get_next_available_child(const struct device_node *node, struct device_node *prev); + +#define for_each_available_child_of_node(parent, child) \ + for (child = of_get_next_available_child(parent, NULL); child != NULL; \ + child = of_get_next_available_child(parent, child)) u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap); u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv); @@ -1457,8 +1468,11 @@ struct packet_offload *gro_find_complete_by_type(__be16 type); void dev_add_offload(struct packet_offload *po); -struct net_device * fec_get_my_registered_net_device(void); +void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); + +struct pm_qos_request {}; +#define dma_wmb() __asm__ __volatile__ ("dmb oshst" : : : "memory") #include #endif /* _SRC__DRIVERS__NIC__FEC__LX_EMUL_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/main.cc b/repos/dde_linux/src/drivers/nic/fec/main.cc index 12cd0710146..122b00a277c 100644 --- a/repos/dde_linux/src/drivers/nic/fec/main.cc +++ b/repos/dde_linux/src/drivers/nic/fec/main.cc @@ -15,7 +15,6 @@ #include #include #include -#include #include @@ -31,6 +30,7 @@ /* Linux module functions */ extern "C" int module_fec_driver_init(); +extern "C" int module_phy_module_init(); extern "C" int subsys_phy_init(); extern "C" void skb_init(); @@ -40,14 +40,12 @@ struct workqueue_struct *system_wq; struct workqueue_struct *system_power_efficient_wq; unsigned long jiffies; - struct Main { - Genode::Env &env; - Genode::Entrypoint &ep { env.ep() }; - Genode::Attached_rom_dataspace config { env, "config" }; - Genode::Heap heap { env.ram(), env.rm() }; - Nic::Root root { env, heap }; + Genode::Env &env; + Genode::Entrypoint &ep { env.ep() }; + Genode::Heap heap { env.ram(), env.rm() }; + Root root { env, heap }; /* Linux task that handles the initialization */ Genode::Constructible linux; @@ -61,7 +59,6 @@ struct Main /* init singleton Lx::Scheduler */ Lx::scheduler(&env); - //Lx::pci_init(env, env.ram(), heap); Lx::malloc_init(env, heap); /* init singleton Lx::Timer */ @@ -95,9 +92,10 @@ static void run_linux(void * m) skb_init(); subsys_phy_init(); + module_phy_module_init(); module_fec_driver_init(); - main.announce(); + main.announce(); while (1) Lx::scheduler().current()->block_and_schedule(); } diff --git a/repos/dde_linux/src/drivers/nic/fec/target.mk b/repos/dde_linux/src/drivers/nic/fec/target.mk index 1a1c2eb89b0..66b9063fbc9 100644 --- a/repos/dde_linux/src/drivers/nic/fec/target.mk +++ b/repos/dde_linux/src/drivers/nic/fec/target.mk @@ -38,6 +38,7 @@ CC_OPT_skbuff = -Wno-pointer-sign -Wno-int-conversion -Wno-uninitialized CC_OPT_mdio_bus = -Wno-implicit-int -Wno-unused-function -Wno-pointer-sign CC_OPT_eth = -Wno-pointer-sign -Wno-unused-function CC_OPT_phy = -Wno-unused-function -Wno-unused-but-set-variable +CC_OPT_at803x = -Wno-unused-variable vpath %.c $(LX_CONTRIB_DIR)/drivers/net/ethernet/freescale vpath %.c $(LX_CONTRIB_DIR)/drivers/net/phy From 873358cf4a57278f315d6f746a898d9308cecdbd Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Wed, 5 Apr 2017 20:23:23 +0200 Subject: [PATCH 05/14] dde_linux: use internal setjmp/longjmp only --- .../lib/mk/spec/arm/lx_kit_setjmp.mk | 3 ++ .../lib/mk/spec/x86_32/lx_kit_setjmp.mk | 3 ++ .../lib/mk/spec/x86_64/lx_kit_setjmp.mk | 3 ++ repos/dde_linux/lib/mk/usb.inc | 2 +- repos/dde_linux/lib/mk/wifi.inc | 4 +- .../src/drivers/framebuffer/intel/target.mk | 2 +- .../src/include/lx_kit/internal/task.h | 5 --- .../spec/arm/lx_kit/internal/arch_execute.h | 2 - .../x86_32/lx_kit/internal/arch_execute.h | 2 - .../x86_64/lx_kit/internal/arch_execute.h | 2 - repos/dde_linux/src/lx_kit/spec/arm/setjmp.S | 39 ++++++++++++++++--- 11 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 repos/dde_linux/lib/mk/spec/arm/lx_kit_setjmp.mk create mode 100644 repos/dde_linux/lib/mk/spec/x86_32/lx_kit_setjmp.mk create mode 100644 repos/dde_linux/lib/mk/spec/x86_64/lx_kit_setjmp.mk diff --git a/repos/dde_linux/lib/mk/spec/arm/lx_kit_setjmp.mk b/repos/dde_linux/lib/mk/spec/arm/lx_kit_setjmp.mk new file mode 100644 index 00000000000..ba31c4917be --- /dev/null +++ b/repos/dde_linux/lib/mk/spec/arm/lx_kit_setjmp.mk @@ -0,0 +1,3 @@ +SRC_S += setjmp.S + +vpath %.S $(REP_DIR)/src/lx_kit/spec/arm diff --git a/repos/dde_linux/lib/mk/spec/x86_32/lx_kit_setjmp.mk b/repos/dde_linux/lib/mk/spec/x86_32/lx_kit_setjmp.mk new file mode 100644 index 00000000000..d084e7d92dd --- /dev/null +++ b/repos/dde_linux/lib/mk/spec/x86_32/lx_kit_setjmp.mk @@ -0,0 +1,3 @@ +SRC_S += setjmp.S + +vpath %.S $(REP_DIR)/src/lx_kit/spec/x86_32 diff --git a/repos/dde_linux/lib/mk/spec/x86_64/lx_kit_setjmp.mk b/repos/dde_linux/lib/mk/spec/x86_64/lx_kit_setjmp.mk new file mode 100644 index 00000000000..04cbf390fe2 --- /dev/null +++ b/repos/dde_linux/lib/mk/spec/x86_64/lx_kit_setjmp.mk @@ -0,0 +1,3 @@ +SRC_S += setjmp.S + +vpath %.S $(REP_DIR)/src/lx_kit/spec/x86_64 diff --git a/repos/dde_linux/lib/mk/usb.inc b/repos/dde_linux/lib/mk/usb.inc index 24166d056f1..c6025980704 100644 --- a/repos/dde_linux/lib/mk/usb.inc +++ b/repos/dde_linux/lib/mk/usb.inc @@ -1,7 +1,7 @@ LIB_DIR = $(REP_DIR)/src/lib/usb LIB_INC_DIR = $(LIB_DIR)/include -LIBS += usb_include libc-setjmp config +LIBS += usb_include lx_kit_setjmp config SRC_CC += main.cc lx_emul.cc storage.cc \ input_component.cc evdev.cc nic.cc raw.cc SRC_C += dummies.c scsi.c raw_driver.c diff --git a/repos/dde_linux/lib/mk/wifi.inc b/repos/dde_linux/lib/mk/wifi.inc index 8c54803d4eb..e59d48f9a56 100644 --- a/repos/dde_linux/lib/mk/wifi.inc +++ b/repos/dde_linux/lib/mk/wifi.inc @@ -11,17 +11,15 @@ SHARED_LIB = yes # wifi_include *must* be the first library, otherwise the include # order is wrong # -LIBS += wifi_include libc +LIBS += wifi_include lx_kit_setjmp libc LD_OPT += --version-script=$(LIB_DIR)/symbol.map SRC_CC += dummies.cc init.cc lxcc_emul.cc nic.cc socket_call.cc # lx_kit -CC_OPT += -DUSE_INTERNAL_SETJMP SRC_CC += mapped_io_mem_range.cc irq.cc pci.cc malloc.cc scheduler.cc \ work.cc timer.cc printf.cc env.cc -SRC_S += setjmp.S SRC_C += lxc_emul.c diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/target.mk b/repos/dde_linux/src/drivers/framebuffer/intel/target.mk index 8561229efc5..c30c0c8e426 100644 --- a/repos/dde_linux/src/drivers/framebuffer/intel/target.mk +++ b/repos/dde_linux/src/drivers/framebuffer/intel/target.mk @@ -1,7 +1,7 @@ REQUIRES = x86 TARGET = intel_fb_drv -LIBS = base intel_fb_drv intel_fb_include libc-setjmp blit +LIBS = base intel_fb_drv intel_fb_include lx_kit_setjmp blit SRC_CC = main.cc lx_emul.cc SRC_C = dummies.c i915_params.c lx_emul_c.c diff --git a/repos/dde_linux/src/include/lx_kit/internal/task.h b/repos/dde_linux/src/include/lx_kit/internal/task.h index 3a195e66897..66eac6b4f42 100644 --- a/repos/dde_linux/src/include/lx_kit/internal/task.h +++ b/repos/dde_linux/src/include/lx_kit/internal/task.h @@ -25,11 +25,6 @@ #include #include -#if !defined(USE_INTERNAL_SETJMP) -/* libc includes */ -#include -#endif /* USE_INTERNAL_SETJMP */ - namespace Lx { diff --git a/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h b/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h index e93ba77f555..899ad288b2b 100644 --- a/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h +++ b/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h @@ -14,7 +14,6 @@ #ifndef _ARCH_EXECUTE_H_ #define _ARCH_EXECUTE_H_ -#if defined(USE_INTERNAL_SETJMP) #ifdef __cplusplus extern "C" { #endif @@ -28,7 +27,6 @@ int _setjmp(jmp_buf); #ifdef __cplusplus } #endif -#endif /* USE_INTERNAL_SETJMP */ static inline diff --git a/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h index 541742842f5..0e8424d3f38 100644 --- a/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h +++ b/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h @@ -14,7 +14,6 @@ #ifndef _ARCH_EXECUTE_H_ #define _ARCH_EXECUTE_H_ -#if defined(USE_INTERNAL_SETJMP) #ifdef __cplusplus extern "C" { #endif @@ -28,7 +27,6 @@ int _setjmp(jmp_buf); #ifdef __cplusplus } #endif -#endif /* USE_INTERNAL_SETJMP */ static inline diff --git a/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h index ea4a6a68793..d0ee75aac2b 100644 --- a/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h +++ b/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h @@ -15,7 +15,6 @@ #ifndef _ARCH_EXECUTE_H_ #define _ARCH_EXECUTE_H_ -#if defined(USE_INTERNAL_SETJMP) #ifdef __cplusplus extern "C" { #endif @@ -29,7 +28,6 @@ extern "C" { #ifdef __cplusplus } #endif -#endif /* USE_INTERNAL_SETJMP */ static inline diff --git a/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S b/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S index 4e84fb23f36..a3cc4791c3d 100644 --- a/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S +++ b/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S @@ -32,8 +32,18 @@ * SUCH DAMAGE. */ -//#include -__FBSDID("$FreeBSD$"); +/* needed parts from */ +#define __FBSDID(x) +#define ENTRY(x) .text; .align 0; .globl x; .type x,#function; x:; +#define WEAK_ALIAS(x,y) +#define RET mov pc, lr +#define _JB_MAGIC__SETJMP 0x4278f500 + +#define __SOFTFP__ 1 +#define _STANDALONE +/* end of */ + +__FBSDID("$FreeBSD: release/8.2.0/lib/libc/arm/gen/_setjmp.S 193145 2009-05-31 02:03:40Z marcel $"); /* * C library -- _setjmp, _longjmp @@ -51,9 +61,15 @@ __FBSDID("$FreeBSD$"); ENTRY(_setjmp) ldr r1, .L_setjmp_magic str r1, [r0], #4 - - /* SOFTFP */ +#ifdef __SOFTFP__ add r0, r0, #52 +#else + /* Store fp registers */ + sfm f4, 4, [r0], #48 + /* Store fpsr */ + rfs r1 + str r1, [r0], #0x0004 +#endif /* __SOFTFP__ */ /* Store integer registers */ stmia r0, {r4-r14} @@ -70,8 +86,15 @@ ENTRY(_longjmp) teq r2, r3 bne botch - /* SOFTFP */ +#ifdef __SOFTFP__ add r0, r0, #52 +#else + /* Restore fp registers */ + lfm f4, 4, [r0], #48 + /* Restore fpsr */ + ldr r4, [r0], #0x0004 + wfs r4 +#endif /* __SOFTFP__ */ /* Restore integer registers */ ldmia r0, {r4-r14} @@ -88,4 +111,10 @@ ENTRY(_longjmp) /* validation failed, die die die. */ botch: +#if !defined(_STANDALONE) + bl PIC_SYM(_C_LABEL(longjmperror), PLT) + bl PIC_SYM(_C_LABEL(abort), PLT) + b . - 8 /* Cannot get here */ +#else b . +#endif From a90de7cd2f88fe77c2720f30fe2fc42c5985fa0e Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 12:42:53 +0200 Subject: [PATCH 06/14] Update dde_linux hash --- repos/dde_linux/ports/dde_linux.hash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index f9ab7d4ebe8..d22fd91bdf4 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -7f9bd747fe1d1ca7e19a46100b0f4d125698a5d4 +471e996102aff6b81e92a525661df0ff28ef7afe From 3299de769be56ab0ad868eed0578694720fcf714 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 12:43:14 +0200 Subject: [PATCH 07/14] Add base/session_label include --- repos/dde_linux/src/drivers/nic/fec/component.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/repos/dde_linux/src/drivers/nic/fec/component.h b/repos/dde_linux/src/drivers/nic/fec/component.h index 09ae2891739..c99fc64b2af 100644 --- a/repos/dde_linux/src/drivers/nic/fec/component.h +++ b/repos/dde_linux/src/drivers/nic/fec/component.h @@ -20,6 +20,8 @@ #include +#include + extern "C" { struct net_device; struct napi_struct; From fcd39da1579b9abe133808e99dc7b5462b965828 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 12:47:51 +0200 Subject: [PATCH 08/14] Add Insufficient_ram_quota definition from 18.02 --- repos/dde_linux/src/drivers/nic/fec/component.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/component.h b/repos/dde_linux/src/drivers/nic/fec/component.h index c99fc64b2af..e30d53a16c6 100644 --- a/repos/dde_linux/src/drivers/nic/fec/component.h +++ b/repos/dde_linux/src/drivers/nic/fec/component.h @@ -91,6 +91,8 @@ class Root : public Genode::Root_component { using namespace Genode; + struct Insufficient_ram_quota : Exception { }; + Session_label const label = label_from_args(args); size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); @@ -100,7 +102,7 @@ class Root : public Genode::Root_component /* deplete ram quota by the memory needed for the session structure */ size_t session_size = max(4096UL, (unsigned long)sizeof(Session_component)); if (ram_quota < session_size) - throw Genode::Insufficient_ram_quota(); + throw Insufficient_ram_quota(); /* * Check if donated ram quota suffices for both communication @@ -110,7 +112,7 @@ class Root : public Genode::Root_component tx_buf_size + rx_buf_size > ram_quota - session_size) { Genode::error("insufficient 'ram_quota', got ", ram_quota, ", " "need ", tx_buf_size + rx_buf_size + session_size); - throw Genode::Insufficient_ram_quota(); + throw Insufficient_ram_quota(); } return new (Root::md_alloc()) From bfe7b30003740702d2aee3f5092cc8cf40d88c36 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 12:56:35 +0200 Subject: [PATCH 09/14] Adapt Session_component call --- repos/dde_linux/src/drivers/nic/fec/component.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/component.cc b/repos/dde_linux/src/drivers/nic/fec/component.cc index fdac2710e3d..f53974cb2f3 100644 --- a/repos/dde_linux/src/drivers/nic/fec/component.cc +++ b/repos/dde_linux/src/drivers/nic/fec/component.cc @@ -174,9 +174,9 @@ Session_component::Session_component(Genode::size_t const tx_buf_size, Genode::Allocator & rx_block_md_alloc, Genode::Env & env, Genode::Session_label label) -: Nic::Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, env), +: Nic::Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, env.ram(), env.ep()), _ndev(_register_session_component(*this, label)), _has_link(_ndev ? !(_ndev->state & (1UL << __LINK_STATE_NOCARRIER)) : false) { - if (!_ndev) throw Genode::Service_denied(); + if (!_ndev) throw Genode::Parent::Service_denied(); } From 1d1a1e50873e4e35a5922cc9b1368629dd4f2c46 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 12:58:56 +0200 Subject: [PATCH 10/14] Add reconstructible.h from 18.02 --- repos/base/include/util/reconstructible.h | 171 ++++++++++++++++++ .../dde_linux/src/drivers/nic/fec/lx_emul.cc | 2 + 2 files changed, 173 insertions(+) create mode 100644 repos/base/include/util/reconstructible.h diff --git a/repos/base/include/util/reconstructible.h b/repos/base/include/util/reconstructible.h new file mode 100644 index 00000000000..771ff09b361 --- /dev/null +++ b/repos/base/include/util/reconstructible.h @@ -0,0 +1,171 @@ +/* + * \brief Utility for in-place (re-)construction of objects + * \author Norman Feske + * \date 2014-01-10 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__UTIL__RECONSTRUCTIBLE_H_ +#define _INCLUDE__UTIL__RECONSTRUCTIBLE_H_ + +#include +#include +#include + +namespace Genode { + template class Reconstructible; + template class Constructible; +} + + +/** + * Place holder for an object to be repeatedly constructed and destructed + * + * This class template acts as a smart pointer that refers to an object + * contained within the smart pointer itself. The contained object may be + * repeatedly constructed and destructed while staying in the same place. This + * is useful for replacing aggregated members during the lifetime of a compound + * object. + * + * \param MT type + */ +template +class Genode::Reconstructible : Noncopyable +{ + private: + + /** + * Static reservation of memory for the embedded object + */ + char _space[sizeof(MT)] __attribute__((aligned(sizeof(addr_t)))); + + /** + * True if the volatile object contains a constructed object + */ + bool _constructed = false; + + template void _do_construct(ARGS &&... args) + { + construct_at(_space, args...); + _constructed = true; + } + + MT *_ptr() { return reinterpret_cast(_space); } + MT const *_const_ptr() const { return reinterpret_cast(_space); } + + void _check_constructed() const + { + if (!_constructed) + throw Deref_unconstructed_object(); + } + + protected: + + /** + * Dummy type used as a hook for 'Constructible' to bypass the + * default constructor by invoking the 'Reconstructible(Lazy *)' + * constructor. + */ + struct Lazy { }; + + /** + * Constructor that omits the initial construction of the object + */ + Reconstructible(Lazy *) { } + + public: + + class Deref_unconstructed_object { }; + + /** + * Constructor + * + * The arguments are forwarded to the constructor of the embedded + * object. + */ + template + Reconstructible(ARGS &&... args) + { + _do_construct(args...); + } + + ~Reconstructible() { destruct(); } + + /** + * Construct new object in place + * + * If the 'Reconstructible' already hosts a constructed object, the old + * object will be destructed first. + */ + template + void construct(ARGS &&... args) + { + destruct(); + _do_construct(args...); + } + + /** + * Destruct object + */ + void destruct() + { + if (!_constructed) + return; + + /* invoke destructor */ + _ptr()->~MT(); + + _constructed = false; + } + + /** + * Return true of volatile object contains a constructed object + */ + bool constructed() const { return _constructed; } + + /** + * Return true of volatile object contains a constructed object + * + * \deprecated use 'constructed' instead + */ + bool is_constructed() const { return constructed(); } + + /** + * Access contained object + */ + MT *operator -> () { _check_constructed(); return _ptr(); } + MT const *operator -> () const { _check_constructed(); return _const_ptr(); } + + MT &operator * () { _check_constructed(); return *_ptr(); } + MT const &operator * () const { _check_constructed(); return *_const_ptr(); } + + void print(Output &out) const + { + if (_constructed) + _const_ptr()->print(out); + else + out.out_string(""); + } +}; + + +/** + * Reconstructible object that holds no initially constructed object + */ +template +struct Genode::Constructible : Reconstructible +{ + template + Constructible(ARGS &&...) + : + Reconstructible((typename Reconstructible::Lazy *)nullptr) + { } +}; + +#endif /* _INCLUDE__UTIL__RECONSTRUCTIBLE_H_ */ diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc index 8f8d6b9e945..459e0ea04e5 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -37,6 +37,8 @@ #include #include +#include + extern "C" { struct page; } class Addr_to_page_mapping : public Genode::List::Element From 496f42c0a4aad6c8909d1fd06bcd2c0e95ee515a Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 13:09:35 +0200 Subject: [PATCH 11/14] Add missing lx_kit/env.h include and adapt Device::create call --- repos/dde_linux/src/drivers/nic/fec/lx_emul.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc index 459e0ea04e5..801f1b8237a 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -579,7 +580,7 @@ int platform_get_irq(struct platform_device * d, unsigned int i) int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) { - Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev_id); + Lx::Irq::irq().request_irq(Platform::Device::create(irq), handler, dev_id); return 0; } From fc89e332287d86592e622c54f3dd36fcfb538dd8 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 13:13:41 +0200 Subject: [PATCH 12/14] Adapt main.cc file - Add missing include for constructible - Adapt scheduler and timer function calls - Comment out malloc_init and exec_static_constructors calls --- repos/dde_linux/src/drivers/nic/fec/main.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/main.cc b/repos/dde_linux/src/drivers/nic/fec/main.cc index 122b00a277c..0bd33ec24ae 100644 --- a/repos/dde_linux/src/drivers/nic/fec/main.cc +++ b/repos/dde_linux/src/drivers/nic/fec/main.cc @@ -28,6 +28,8 @@ #include #include +#include + /* Linux module functions */ extern "C" int module_fec_driver_init(); extern "C" int module_phy_module_init(); @@ -57,12 +59,12 @@ struct Main Lx_kit::construct_env(env); /* init singleton Lx::Scheduler */ - Lx::scheduler(&env); + Lx::scheduler(); - Lx::malloc_init(env, heap); + //Lx::malloc_init(env, heap); /* init singleton Lx::Timer */ - Lx::timer(&env, &ep, &heap, &jiffies); + Lx::timer(&ep, &jiffies); /* init singleton Lx::Irq */ Lx::Irq::irq(&ep, &heap); @@ -103,7 +105,7 @@ static void run_linux(void * m) void Component::construct(Genode::Env &env) { /* XXX execute constructors of global statics */ - env.exec_static_constructors(); + //env.exec_static_constructors(); static Main m(env); } From 8baa4d1c568546056f1e0c656a3bee331886fb32 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 13:16:56 +0200 Subject: [PATCH 13/14] Adapt include file --- repos/dde_linux/src/drivers/nic/fec/platform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repos/dde_linux/src/drivers/nic/fec/platform.cc b/repos/dde_linux/src/drivers/nic/fec/platform.cc index a4a46dc0b79..cb093c87ab7 100644 --- a/repos/dde_linux/src/drivers/nic/fec/platform.cc +++ b/repos/dde_linux/src/drivers/nic/fec/platform.cc @@ -13,7 +13,7 @@ * version 2. */ -#include +#include #include #include From e49420dc6fdf38c8a3b7ba9d5157659c943f9182 Mon Sep 17 00:00:00 2001 From: Alexander Weidinger Date: Thu, 3 May 2018 14:56:47 +0200 Subject: [PATCH 14/14] Add config section to nic_drv in lwip.run --- repos/libports/run/lwip.run | 1 + 1 file changed, 1 insertion(+) diff --git a/repos/libports/run/lwip.run b/repos/libports/run/lwip.run index cfa654a5354..cc4b9fa179e 100644 --- a/repos/libports/run/lwip.run +++ b/repos/libports/run/lwip.run @@ -105,6 +105,7 @@ append_if $use_nic_driver config { + } append config {