wifi: update iwlwifi to 4.16.3

This commit is contained in:
Josef Söntgen
2018-04-23 15:45:47 +02:00
committed by Christian Helmuth
parent eb62d9cc04
commit 870505bcd9
34 changed files with 2756 additions and 1257 deletions

View File

@ -2,7 +2,8 @@ REQUIRES = x86
TARGET = wifi_drv
SRC_CC = main.cc
LIBS = base wifi iwl_firmware wpa_supplicant
LIBS = base wifi iwl_firmware
LIBS += wpa_supplicant
# needed for firmware.h
INC_DIR += $(REP_DIR)/src/lib/wifi/include

View File

@ -393,17 +393,20 @@ int setsockopt(int sockfd, int level, int optname, const void *optval,
if (!s)
return -1;
/* FIXME optval values */
int const err = socket_call.setsockopt(s,
sockopt_level(level),
sockopt_name(level, optname),
optval, optlen);
if (err < 0) {
errno = -err;
return 1;
}
try {
/* FIXME optval values */
int const err =
socket_call.setsockopt(s,
sockopt_level(level),
sockopt_name(level, optname),
optval, optlen);
if (err < 0) {
errno = -err;
return 1;
}
} catch (Invalid_arg) { return -1; }
return err;
return 0;
}

View File

@ -78,6 +78,7 @@ DUMMY_RET(1, ns_capable)
DUMMY_RET(0, sock_tx_timestamp)
/* not needed */
DUMMY_SKIP(0, module_put_and_exit)
DUMMY_SKIP(-1, might_sleep)
DUMMY_SKIP(-1, read_lock_bh)
DUMMY_SKIP(-1, read_unlock_bh)
@ -173,7 +174,6 @@ DUMMY(-1, raw_notifier_chain_unregister)
DUMMY(-1, vlan_do_receive)
DUMMY(-1, vlan_untag)
DUMMY(-1, yield)
DUMMY(0, IS_ERR)
DUMMY(0, __raise_softirq_irqoff)
DUMMY(0, __this_cpu_read)
DUMMY(-1, add_device_randomness)
@ -201,13 +201,10 @@ DUMMY(0, genlmsg_multicast_netns)
DUMMY(0, genlmsg_reply)
DUMMY(0, genlmsg_unicast)
DUMMY(0, get_cpu)
DUMMY(0, get_random_bytes)
DUMMY(0, get_seconds)
DUMMY(0, hweight16)
DUMMY(0, hweight64)
DUMMY(0, idr_alloc)
DUMMY(0, idr_destroy)
DUMMY(0, idr_find)
DUMMY(0, idr_for_each)
DUMMY(0, idr_init)
DUMMY(0, idr_remove)
@ -313,7 +310,7 @@ DUMMY(0, atomic_notifier_chain_register)
DUMMY(0, __get_free_pages)
DUMMY(0, __get_free_page)
DUMMY(0, __set_current_state)
DUMMY(0, add_wait_queue)
// DUMMY(0, add_wait_queue)
DUMMY(0, add_wait_queue_exclusive)
DUMMY(0, atomic_notifier_call_chain)
DUMMY(0, cond_resched)
@ -342,7 +339,6 @@ DUMMY(-1, __this_cpu_write)
DUMMY(-1, csum_block_add_ext)
DUMMY(-1, csum_partial_ext)
DUMMY(-1, genl_register_family_with_ops_groups)
DUMMY(-1, ktime_sub)
DUMMY(-1, sg_init_one)
DUMMY(-1, vlan_hw_offload_capable)
DUMMY(-1, vlan_tx_tag_get_id)
@ -427,7 +423,6 @@ DUMMY(0, csum_sub)
DUMMY(0, csum_tcpudp_nofold)
DUMMY(0, devm_clk_get)
DUMMY(0, devm_gpiod_get_index)
DUMMY(0, devm_kzalloc)
DUMMY(0, file_inode)
DUMMY(0, gpiod_direction_output)
DUMMY(0, gpiod_set_value)
@ -443,8 +438,6 @@ DUMMY(0, input_unregister_handler)
DUMMY(0, ip_hdrlen)
DUMMY(0, ipv6_authlen)
DUMMY(0, ipv6_optlen)
DUMMY(0, ktime_to_timespec)
DUMMY(0, ktime_to_timeval)
DUMMY(0, misc_deregister)
DUMMY(0, net_gso_ok)
DUMMY(0, nosteal_pipe_buf_ops)
@ -496,7 +489,6 @@ DUMMY(0, ethtool_cmd_speed)
DUMMY(0, flush_dcache_page)
DUMMY(0, getnstimeofday)
DUMMY(0, ip_check_defrag)
DUMMY(0, ktime_to_timespec_cond)
DUMMY(0, netdev_get_tx_queue)
DUMMY(0, offset_in_page)
DUMMY(0, prandom_u32_max)
@ -541,8 +533,7 @@ DUMMY(0, release_pages)
DUMMY(0, sk_busy_loop)
DUMMY(0, sk_can_busy_loop)
DUMMY_SKIP(0, complete_all)
DUMMY_SKIP(0, module_put_and_exit)
// DUMMY_SKIP(0, complete_all)
DUMMY_SKIP(0, simple_strtol)
DUMMY_SKIP(0, alg_test)
@ -559,13 +550,13 @@ DUMMY(0, config_enabled)
DUMMY(0, dev_change_proto_down)
DUMMY(0, dev_get_iflink)
DUMMY(0, dev_get_phys_port_name)
DUMMY(0, device_create_with_groups)
DUMMY(-1, device_create_with_groups)
DUMMY(0, device_enable_async_suspend)
DUMMY(0, fatal_signal_pending)
DUMMY_RET(1, file_ns_capable)
DUMMY(0, flow_keys_dissector)
DUMMY(0, get_net_ns_by_id)
DUMMY(0, gfpflags_allow_blocking)
DUMMY_SKIP(0, gfpflags_allow_blocking)
DUMMY(0, init_dummy_netdev)
DUMMY(0, napi_gro_flush)
DUMMY(0, netdev_start_xmit)

View File

@ -0,0 +1,515 @@
/*
* \brief Dummy functions
* \author Josef Soentgen
* \date 2018-04-26
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* local includes */
#include <lx_emul.h>
#if 1
#define TRACE \
do { \
lx_printf("%s not implemented from: %p\n", __func__, \
__builtin_return_address(0)); \
} while (0)
#define TRACE_OK \
do { \
lx_printf("%s not implemented but OK\n", __func__); \
} while (0)
#else
#define TRACE do { ; } while (0)
#define TRACE_OK do { ; } while (0)
#endif
void __dev_xdp_query(struct net_device *dev, bpf_op_t xdp_op, struct netdev_bpf *xdp)
{
TRACE;
}
int __ethtool_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *link_ksettings)
{
TRACE;
return -1;
}
u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
{
TRACE;
return 0;
}
// typedef int (*bpf_op_t)(struct net_device *dev, struct netdev_bpf *bpf);
// struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
// {
// TRACE;
// return NULL;
// }
struct sk_buff **call_gro_receive(gro_receive_t cb, struct sk_buff **head, struct sk_buff *skb)
{
TRACE;
return NULL;
}
struct user_struct *current_user()
{
TRACE;
return NULL;
}
int dev_change_tx_queue_len(struct net_device *dev, unsigned long d)
{
TRACE;
return -1;
}
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
int fd, u32 flags)
{
TRACE;
return -1;
}
int dev_get_alias(const struct net_device *dev, char *p, size_t n)
{
TRACE;
return -1;
}
int dev_recursion_level(void)
{
TRACE;
return 0;
}
bool dev_validate_header(const struct net_device *dev, char *ll_header, int len)
{
TRACE;
return false;
}
void free_uid(struct user_struct *user)
{
TRACE;
}
void iov_iter_revert(struct iov_iter *i, size_t bytes)
{
TRACE;
}
kuid_t make_kuid(struct user_namespace *from, uid_t uid)
{
TRACE;
return 0;
}
void memalloc_noreclaim_restore(unsigned int flags)
{
TRACE;
}
unsigned int memalloc_noreclaim_save(void)
{
TRACE;
return 0;
}
u64 ktime_get_ns(void)
{
TRACE;
return 0;
}
struct fq_flow *fq_flow_classify(struct fq *fq, struct fq_tin *tin,
struct sk_buff *skb,
fq_flow_get_default_t get_default_func)
{
TRACE;
return 0;
}
void fq_flow_init(struct fq_flow *flow)
{
TRACE;
}
int fq_init(struct fq *fq, int flows_cnt)
{
TRACE;
return -1;
}
void fq_recalc_backlog(struct fq *fq, struct fq_tin *tin, struct fq_flow *flow)
{
TRACE;
}
void fq_reset(struct fq *fq, fq_skb_free_t free_func)
{
TRACE;
}
void fq_tin_enqueue(struct fq *fq, struct fq_tin *tin, struct sk_buff *skb,
fq_skb_free_t free_func, fq_flow_get_default_t get_default_func)
{
TRACE;
}
void fq_tin_filter(struct fq *fq, struct fq_tin *tin, fq_skb_filter_t filter_func,
void *filter_data, fq_skb_free_t free_func)
{
TRACE;
}
void fq_tin_init(struct fq_tin *tin)
{
TRACE;
}
void fq_tin_reset(struct fq *fq, struct fq_tin *tin, fq_skb_free_t free_func)
{
TRACE;
}
int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
{
TRACE;
return 0;
}
struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
TRACE;
return NULL;
}
void netdev_rss_key_fill(void *buffer, size_t len)
{
TRACE;
/* XXX get_random_once() to fill cmd.secret_key */
}
const void *of_get_mac_address(struct device_node *np)
{
TRACE;
return NULL;
}
struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev)
{
TRACE;
return NULL;
}
int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
int minvec, int maxvec)
{
TRACE;
return -1;
}
int pci_find_ext_capability(struct pci_dev *dev, int cap)
{
TRACE;
return -1;
}
int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
{
// TRACE_OK;
return 0;
}
int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
{
// TRACE_OK;
return 0;
}
struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
{
TRACE;
return NULL;
}
int pcim_enable_device(struct pci_dev *pdev)
{
TRACE;
return 0;
}
bool pm_runtime_active(struct device *dev)
{
TRACE;
return true;
}
void pm_runtime_allow(struct device *dev)
{
TRACE;
}
void pm_runtime_forbid(struct device *dev)
{
TRACE;
}
int pm_runtime_get(struct device *dev)
{
TRACE;
return 1;
}
void pm_runtime_mark_last_busy(struct device *dev)
{
TRACE;
}
int pm_runtime_put_autosuspend(struct device *dev)
{
TRACE;
return -1;
}
int pm_runtime_resume(struct device *dev)
{
TRACE;
return 1;
}
int pm_runtime_set_active(struct device *dev)
{
TRACE;
return 0;
}
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
{
TRACE;
}
bool pm_runtime_suspended(struct device *dev)
{
// TRACE_OK;
return false;
}
void pm_runtime_use_autosuspend(struct device *dev)
{
TRACE;
}
void pm_wakeup_event(struct device *dev, unsigned int msec)
{
TRACE;
}
void reuseport_detach_sock(struct sock *sk)
{
TRACE;
}
int sg_nents(struct scatterlist *sg)
{
TRACE;
return -1;
}
size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
const void *buf, size_t buflen, off_t skip)
{
TRACE;
return 0;
}
int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
{
TRACE;
return -1;
}
int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk)
{
TRACE;
return -1;
}
void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush)
{
TRACE;
}
void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset)
{
TRACE;
return NULL;
}
int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
{
TRACE;
return 0; // XXX
}
void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset)
{
TRACE;
return NULL;
}
void skb_gro_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len)
{
TRACE;
}
void skb_gro_pull(struct sk_buff *skb, unsigned int len)
{
TRACE;
}
u64 sock_gen_cookie(struct sock *sk)
{
TRACE;
return 0;
}
unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
{
// TRACE;
return 0;
}
unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
{
// TRACE;
return 0;
}
bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp, unsigned int start)
{
// TRACE;
return false;
}
bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp, unsigned int start)
{
// TRACE;
return false;
}
void u64_stats_init(struct u64_stats_sync *syncp)
{
// TRACE;
}
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev,
bool *again)
{
TRACE;
return NULL;
}
int virtio_net_hdr_from_skb(const struct sk_buff *skb, struct virtio_net_hdr *hdr,
bool little_endian, bool has_data_valid)
{
TRACE;
return -1;
}
int virtio_net_hdr_to_skb(struct sk_buff *skb, const struct virtio_net_hdr *hdr,
bool little_endian)
{
TRACE;
return -1;
}
void wireless_nlevent_flush(void)
{
TRACE;
}
bool wq_has_sleeper(struct wait_queue_head *wq_head)
{
TRACE;
return true;
}

View File

@ -0,0 +1,107 @@
/*
* \brief Linux wireless stack
* \author Josef Soentgen
* \date 2018-06-29
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include <lx_kit/env.h>
#include <firmware_list.h>
#include <lx_emul.h>
Firmware_list fw_list[] = {
{ "regulatory.db", 4144, nullptr },
{ "iwlwifi-1000-5.ucode", 337520, nullptr },
{ "iwlwifi-3160-17.ucode", 918268, nullptr },
{ "iwlwifi-6000-4.ucode", 454608, nullptr },
{ "iwlwifi-6000-6.ucode", 454608, "iwlwifi-6000-4.ucode" },
{ "iwlwifi-6000g2a-6.ucode", 677296, nullptr },
{ "iwlwifi-6000g2b-6.ucode", 679436, nullptr },
{ "iwlwifi-7260-17.ucode", 1049340, nullptr },
{ "iwlwifi-7265-16.ucode", 1180412, nullptr },
{ "iwlwifi-7265D-22.ucode", 1028376, nullptr },
{ "iwlwifi-7265D-29.ucode", 1036432, nullptr },
{ "iwlwifi-8000C-22.ucode", 2120860, nullptr },
{ "iwlwifi-8000C-36.ucode", 2486572, nullptr },
{ "iwlwifi-8265-22.ucode", 1811984, nullptr },
{ "iwlwifi-8265-36.ucode", 2498044, nullptr }
};
size_t fw_list_len = sizeof(fw_list) / sizeof(fw_list[0]);
/**********************
** linux/firmware.h **
**********************/
int request_firmware_nowait(struct module *module, bool uevent,
const char *name, struct device *device,
gfp_t gfp, void *context,
void (*cont)(const struct firmware *, void *))
{
/* only try to load known firmware images */
Firmware_list *fwl = 0;
for (size_t i = 0; i < fw_list_len; i++) {
if (Genode::strcmp(name, fw_list[i].requested_name) == 0) {
fwl = &fw_list[i];
break;
}
}
if (!fwl) {
Genode::error("firmware '", name, "' is not in the firmware white list");
return -1;
}
char const *fw_name = fwl->available_name
? fwl->available_name : fwl->requested_name;
Genode::Rom_connection rom(Lx_kit::env().env(), fw_name);
Genode::Dataspace_capability ds_cap = rom.dataspace();
if (!ds_cap.valid()) {
Genode::error("could not get firmware ROM dataspace");
return -1;
}
struct firmware *fw = (struct firmware *)kzalloc(sizeof(struct firmware), 0);
if (!fw) {
Genode::error("could not allocate memory for firmware metadata");
return -1;
}
/* use allocator because fw is too big for slab */
if (!Lx_kit::env().heap().alloc(fwl->size, (void**)&fw->data)) {
Genode::error("Could not allocate memory for firmware image");
kfree(fw);
return -1;
}
void const *image = Lx_kit::env().env().rm().attach(ds_cap);
Genode::memcpy((void*)fw->data, image, fwl->size);
Lx_kit::env().env().rm().detach(image);
fw->size = fwl->size;
cont(fw, context);
return 0;
}
void release_firmware(const struct firmware *fw)
{
Lx_kit::env().heap().free(const_cast<u8 *>(fw->data), fw->size);
kfree(fw);
}

File diff suppressed because it is too large Load Diff

View File

@ -34,15 +34,15 @@ extern "C" void core_sock_init(void);
extern "C" void module_packet_init(void);
extern "C" void subsys_genl_init(void);
extern "C" void subsys_rfkill_init(void);
extern "C" void subsys_cfg80211_init(void);
extern "C" void fs_cfg80211_init(void);
extern "C" void subsys_ieee80211_init(void);
extern "C" void module_iwl_drv_init(void);
extern "C" int module_iwl_drv_init(void);
extern "C" void subsys_cryptomgr_init(void);
extern "C" void module_crypto_ccm_module_init(void);
extern "C" void module_crypto_ctr_module_init(void);
extern "C" void module_aes_init(void);
extern "C" void module_arc4_init(void);
extern "C" void module_chainiv_module_init(void);
// extern "C" void module_chainiv_module_init(void);
extern "C" void module_krng_mod_init(void);
extern "C" unsigned int *module_param_11n_disable;
@ -56,55 +56,10 @@ struct net init_net;
LIST_HEAD(net_namespace_list);
Firmware_list fw_list[] = {
{ "iwlwifi-1000-3.ucode", 335056, nullptr },
{ "iwlwifi-1000-5.ucode", 337520, nullptr },
{ "iwlwifi-105-6.ucode", 689680, nullptr },
{ "iwlwifi-135-6.ucode", 701228, nullptr },
{ "iwlwifi-2000-6.ucode", 695876, nullptr },
{ "iwlwifi-2030-6.ucode", 707392, nullptr },
{ "iwlwifi-3160-7.ucode", 670484, nullptr },
{ "iwlwifi-3160-8.ucode", 667284, nullptr },
{ "iwlwifi-3160-9.ucode", 666792, nullptr },
{ "iwlwifi-3945-2.ucode", 150100, nullptr },
{ "iwlwifi-4965-2.ucode", 187972, nullptr },
{ "iwlwifi-5000-1.ucode", 345008, nullptr },
{ "iwlwifi-5000-2.ucode", 353240, nullptr },
{ "iwlwifi-5000-5.ucode", 340696, nullptr },
{ "iwlwifi-5150-2.ucode", 337400, nullptr },
{ "iwlwifi-6000-4.ucode", 454608, nullptr },
/**
* Actually, there is no -6 firmware. The last one is revision 4,
* but certain devices support up to revision 6 and want to use
* this one. To make things simple we refer to the available
* firmware under the requested name.
*/
{ "iwlwifi-6000-6.ucode", 454608, "iwlwifi-6000-4.ucode" },
{ "iwlwifi-6000g2a-5.ucode", 444128, nullptr },
{ "iwlwifi-6000g2a-6.ucode", 677296, nullptr },
{ "iwlwifi-6000g2b-5.ucode", 460236, nullptr },
{ "iwlwifi-6000g2b-6.ucode", 679436, nullptr },
{ "iwlwifi-6050-4.ucode", 463692, nullptr },
{ "iwlwifi-6050-5.ucode", 469780, nullptr },
{ "iwlwifi-7260-16.ucode", 1049284, nullptr },
{ "iwlwifi-7260-17.ucode", 1049284, "iwlwifi-7260-16.ucode" },
{ "iwlwifi-7265-16.ucode", 1180356, nullptr },
{ "iwlwifi-7265D-16.ucode", 1384500, nullptr },
{ "iwlwifi-7265D-19.ucode", 1384500, "iwlwifi-7265D-16.ucode" },
{ "iwlwifi-8000C-16.ucode", 2351636, nullptr },
{ "iwlwifi-8000C-19.ucode", 2351636, "iwlwifi-8000C-16.ucode" },
{ "iwlwifi-3160-16.ucode", 918212, nullptr },
{ "iwlwifi-3160-17.ucode", 918212, "iwlwifi-3160-16.ucode" }
};
size_t fw_list_len = sizeof(fw_list) / sizeof(fw_list[0]);
static Genode::Lock *_wpa_lock;
static void run_linux(void *)
static void run_linux(void *args)
{
system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0);
system_wq = alloc_workqueue("system_wq", 0, 0);
@ -114,7 +69,7 @@ static void run_linux(void *)
module_packet_init();
subsys_genl_init();
subsys_rfkill_init();
subsys_cfg80211_init();
fs_cfg80211_init();
subsys_ieee80211_init();
subsys_cryptomgr_init();
@ -122,9 +77,17 @@ static void run_linux(void *)
module_crypto_ctr_module_init();
module_aes_init();
module_arc4_init();
module_chainiv_module_init();
// module_chainiv_module_init();
module_iwl_drv_init();
try {
int const err = module_iwl_drv_init();
if (err) { throw -1; }
} catch (...) {
Genode::Env &env = *(Genode::Env*)args;
env.parent().exit(1);
Genode::sleep_forever();
}
_wpa_lock->unlock();
@ -166,7 +129,7 @@ void wifi_init(Genode::Env &env, Genode::Lock &lock, bool disable_11n)
}
/* Linux task (handles the initialization only currently) */
static Lx::Task linux(run_linux, nullptr, "linux",
static Lx::Task linux(run_linux, &env, "linux",
Lx::Task::PRIORITY_0, Lx::scheduler());
/* give all task a first kick before returning */

View File

@ -80,22 +80,6 @@ unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len)
}
/****************************
** asm-generic/getorder.h **
****************************/
int get_order(unsigned long size)
{
int order;
size--;
size >>= PAGE_SHIFT;
order = __builtin_ctzl(size);
return order;
}
/****************************
** asm-generic/atomic64.h **
****************************/
@ -111,6 +95,57 @@ long long atomic64_add_return(long long i, atomic64_t *p)
}
/**********************
** linux/refcount.h **
**********************/
void refcount_add(unsigned int i, refcount_t *r)
{
atomic_add(i, &r->refs);
}
void refcount_dec(refcount_t *r)
{
atomic_dec(&r->refs);
}
bool refcount_dec_and_test(refcount_t *r)
{
return atomic_dec_and_test(&r->refs);
}
void refcount_inc(refcount_t *r)
{
atomic_inc(&r->refs);
}
bool refcount_inc_not_zero(refcount_t *r)
{
return atomic_add_unless(&r->refs, 1, 0);
}
unsigned int refcount_read(const refcount_t *r)
{
return atomic_read(&r->refs);
}
void refcount_set(refcount_t *r, unsigned int n)
{
atomic_set(&r->refs, n);
}
bool refcount_sub_and_test(unsigned int i, refcount_t *r)
{
return atomic_sub_and_test(i, &r->refs);
}
/**********************************
** linux/bitops.h, asm/bitops.h **
**********************************/
@ -217,6 +252,12 @@ void netdev_run_todo() {
}
void netif_set_gso_max_size(struct net_device *dev, unsigned int size)
{
dev->gso_max_size = size;
}
/********************
** linux/kernel.h **
********************/
@ -394,3 +435,47 @@ static void sock_init(void)
core_initcall(sock_init);
/*****************
** net/codel.h **
*****************/
codel_time_t codel_get_time(void)
{
u64 ns = ktime_get_ns();
return ns >> CODEL_SHIFT;
}
/**********************
** net/codel_impl.h **
**********************/
void codel_params_init(struct codel_params *params)
{
params->interval = MS2TIME(100);
params->target = MS2TIME(5);
params->ce_threshold = CODEL_DISABLED_THRESHOLD;
params->ecn = false;
}
void codel_vars_init(struct codel_vars *vars)
{
memset(vars, 0, sizeof(*vars));
}
void codel_stats_init(struct codel_stats *stats)
{
// stats->maxpacket = 0;
}
/*************************
** linux/timekeeping.h **
*************************/
u64 ktime_get_boot_ns(void)
{
return (u64)ktime_get();
}

View File

@ -15,16 +15,17 @@
#include <base/allocator_avl.h>
#include <base/env.h>
#include <base/log.h>
#include <base/registry.h>
#include <base/snprintf.h>
#include <base/sleep.h>
#include <dataspace/client.h>
#include <timer_session/connection.h>
#include <region_map/client.h>
#include <rom_session/connection.h>
#include <util/bit_allocator.h>
#include <util/string.h>
/* local includes */
#include <firmware_list.h>
#include <lx.h>
#include <lx_emul.h>
@ -300,6 +301,24 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
}
bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
{
if (bytes > i->count)
return false;
if (bytes == 0)
return true;
size_t const copied = copy_from_iter(addr, bytes, i);
if (copied != bytes) {
Genode::error(__func__, ":", __LINE__, " could not copy all bytes");
return false;
}
return true;
}
size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i)
{
if (bytes > i->count)
@ -375,6 +394,11 @@ extern "C" int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov
#include <lx_emul/impl/slab.h>
void *kvmalloc(size_t size, gfp_t flags)
{
return kmalloc(size, flags);
}
void *kmalloc_array(size_t n, size_t size, gfp_t flags)
{
@ -389,6 +413,12 @@ void kvfree(const void *p)
}
void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
{
return kzalloc(size, gfp | GFP_LX_DMA);
}
/*********************
** linux/vmalloc.h **
*********************/
@ -583,40 +613,15 @@ int strict_strtoul(const char *s, unsigned int base, unsigned long *res)
** linux/delay.h **
*******************/
static Timer::Connection &timer_for_msleep()
{
static Timer::Connection inst(Lx_kit::env().env());
return inst;
}
void udelay(unsigned long usecs)
{
timer_for_msleep().usleep(usecs);
Lx::scheduler().current()->schedule();
}
#include <lx_emul/impl/delay.h>
void usleep_range(unsigned long min, unsigned long max)
{
timer_for_msleep().usleep(min);
Lx::scheduler().current()->schedule();
udelay(min);
}
void msleep(unsigned int msecs)
{
timer_for_msleep().msleep(msecs);
Lx::scheduler().current()->schedule();
}
void mdelay(unsigned long msecs) { msleep(msecs); }
/*******************
** linux/timer.h **
*******************/
@ -669,7 +674,49 @@ unsigned long round_jiffies_relative(unsigned long j)
ktime_t ktime_get_real(void)
{
return (ktime_t) { .tv64 = (s64)(jiffies * (1000 / HZ) * NSEC_PER_MSEC) };
return (ktime_t) (s64)(jiffies * (1000 / HZ) * NSEC_PER_MSEC);
}
ktime_t ktime_sub(ktime_t const lhs, ktime_t const rhs)
{
return lhs - rhs;
}
struct timespec ktime_to_timespec(ktime_t const nsec)
{
struct timespec ts;
if (!nsec) { return (struct timespec) {0, 0}; }
/* XXX check nsec < NSEC_PER_SEC */
ts.tv_sec = nsec / NSEC_PER_SEC;
ts.tv_nsec = (nsec % NSEC_PER_SEC) * (1000*1000);
return ts;
}
bool ktime_to_timespec_cond(ktime_t const kt, struct timespec *ts)
{
if (kt) {
*ts = ktime_to_timespec(kt);
return true;
}
return false;
}
struct timeval ns_to_timeval(ktime_t const nsec)
{
struct timespec ts = ktime_to_timespec(nsec);
struct timeval tv;
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
return tv;
}
@ -705,90 +752,25 @@ struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
}
/**********************
** linux/firmware.h **
**********************/
extern Firmware_list fw_list[];
extern size_t fw_list_len;
int request_firmware_nowait(struct module *module, bool uevent,
const char *name, struct device *device,
gfp_t gfp, void *context,
void (*cont)(const struct firmware *, void *))
{
/* only try to load known firmware images */
Firmware_list *fwl = 0;
for (size_t i = 0; i < fw_list_len; i++) {
if (Genode::strcmp(name, fw_list[i].requested_name) == 0) {
fwl = &fw_list[i];
break;
}
}
if (!fwl) {
Genode::error("firmware '", name, "' is not in the firmware white list");
return -1;
}
char const *fw_name = fwl->available_name
? fwl->available_name : fwl->requested_name;
Genode::Rom_connection rom(Lx_kit::env().env(), fw_name);
Genode::Dataspace_capability ds_cap = rom.dataspace();
if (!ds_cap.valid()) {
Genode::error("could not get firmware ROM dataspace");
return -1;
}
struct firmware *fw = (struct firmware *)kzalloc(sizeof(struct firmware), 0);
if (!fw) {
Genode::error("could not allocate memory for firmware metadata");
return -1;
}
/* use allocator because fw is too big for slab */
if (!Lx_kit::env().heap().alloc(fwl->size, (void**)&fw->data)) {
Genode::error("Could not allocate memory for firmware image");
kfree(fw);
return -1;
}
void const *image = Lx_kit::env().env().rm().attach(ds_cap);
Genode::memcpy((void*)fw->data, image, fwl->size);
Lx_kit::env().env().rm().detach(image);
fw->size = fwl->size;
cont(fw, context);
return 0;
}
void release_firmware(const struct firmware *fw)
{
Lx_kit::env().heap().free(const_cast<u8 *>(fw->data), fw->size);
kfree(fw);
}
/*************************
** linux/dma-mapping.h **
*************************/
/* use a smaller limit then possible to cover potential overhead */
enum { DMA_LARGE_ALLOC_SIZE = 60u << 10, };
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
dma_addr_t dma_addr;
void *addr = Lx::Malloc::dma().alloc(size, 12, &dma_addr);
bool const large_alloc = size >= DMA_LARGE_ALLOC_SIZE;
dma_addr_t dma_addr = 0;
void *addr = large_alloc ? Lx::Malloc::dma().alloc_large(size)
: Lx::Malloc::dma().alloc(size, 12, &dma_addr);
if (!addr) {
return 0;
if (addr) {
*dma_handle = large_alloc ? Lx::Malloc::dma().phys_addr(addr)
: dma_addr;
}
*dma_handle = dma_addr;
return addr;
}
@ -808,6 +790,11 @@ void *dma_zalloc_coherent(struct device *dev, size_t size,
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
if (size >= DMA_LARGE_ALLOC_SIZE) {
Lx::Malloc::dma().free_large(vaddr);
return;
}
if (Lx::Malloc::dma().inside((Genode::addr_t)vaddr)) {
Lx::Malloc::dma().free(vaddr);
} else {
@ -841,7 +828,8 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
if (dma_addr == ~0UL) {
Genode::error(__func__, ": virtual address ", cpu_addr,
" not registered for DMA");
" not registered for DMA ", __builtin_return_address(0));
BUG();
}
return dma_addr;
@ -983,6 +971,18 @@ void *__alloc_page_frag(struct page_frag_cache *nc,
}
void *page_frag_alloc(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask)
{
return __alloc_page_frag(nc, fragsz, gfp_mask);
}
void page_frag_free(void *addr)
{
__free_page_frag(addr);
}
void __free_page_frag(void *addr)
{
struct page *page = virt_to_head_page(addr);
@ -1150,12 +1150,55 @@ void *__alloc_percpu(size_t size, size_t align)
}
/**********************
** net/ns/generic.h **
**********************/
void *net_generic(const struct net *net, unsigned int id)
{
if (id >= MAX_NET_GENERIC_PTR) {
Genode::error(__func__, ":", " id ", id, " invalid");
return NULL;
}
struct net_generic *ng = net->gen;
void *ptr = ng->ptr[id];
if (!ptr) {
Genode::error(__func__, ":", " cannot get ptr");
BUG();
}
return ptr;
}
/*******************************
** net/core/net/namespace.h **
*******************************/
int register_pernet_subsys(struct pernet_operations *ops)
{
if (!init_net.gen) {
init_net.gen = (struct net_generic*)kzalloc(
offsetof(struct net_generic, ptr[MAX_NET_GENERIC_PTR]), 0);
if (!init_net.gen) {
Genode::error("could not allocate net_generic memory");
return -1;
}
}
if (ops->id && ops->size) {
/* XXX AFAICS there is only netlink_tap_net_ops that requires it */
unsigned int id = *ops->id;
if (id >= MAX_NET_GENERIC_PTR) {
Genode::error(__func__, ":", " id ", id, " invalid");
return -1;
}
void *data = kzalloc(ops->size, 0);
init_net.gen->ptr[id] = data;
}
if (ops->init)
ops->init(&init_net);
@ -1232,114 +1275,7 @@ int request_module(char const* format, ...)
** kernel/locking/mutex.c **
****************************/
/*
* XXX We have to create the waiters list lazy because the way
* DEFINE_MUTEX is currently implemented does not work w/o
* a global Env that was constructed before the static ctors
* are called
*/
static inline void __check_or_initialize_mutex(struct mutex *m)
{
if (!m->waiters) {
m->waiters = new (&Lx_kit::env().heap()) Lx::Task::List;
}
}
enum { MUTEX_UNLOCKED = 1, MUTEX_LOCKED = 0, MUTEX_WAITERS = -1 };
void mutex_init(struct mutex *m)
{
static unsigned id = 0;
m->state = MUTEX_UNLOCKED;
m->holder = nullptr;
m->waiters = nullptr;
m->id = ++id;
}
void mutex_destroy(struct mutex *m)
{
/* FIXME potentially blocked tasks are not unblocked */
Genode::destroy(&Lx_kit::env().heap(),
static_cast<Lx::Task::List *>(m->waiters));
m->holder = nullptr;
m->waiters = nullptr;
m->id = 0;
}
void mutex_lock(struct mutex *m)
{
__check_or_initialize_mutex(m);
while (1) {
if (m->state == MUTEX_UNLOCKED) {
m->state = MUTEX_LOCKED;
m->holder = Lx::scheduler().current();
break;
}
Lx::Task *t = reinterpret_cast<Lx::Task *>(m->holder);
if (t == Lx::scheduler().current()) {
Genode::error("BUG: mutex does not support recursive locking");
Genode::sleep_forever();
}
/* notice that a task waits for the mutex to be released */
m->state = MUTEX_WAITERS;
/* block until the mutex is released (and retry then) */
Lx::scheduler().current()->mutex_block(static_cast<Lx::Task::List *>(m->waiters));
Lx::scheduler().current()->schedule();
}
}
void mutex_unlock(struct mutex *m)
{
__check_or_initialize_mutex(m);
if (m->state == MUTEX_UNLOCKED) {
Genode::error("BUG: multiple mutex unlock detected");
Genode::sleep_forever();
}
if (m->holder != Lx::scheduler().current()) {
Genode::error("BUG: mutex unlock by task not holding the mutex");
Genode::sleep_forever();
}
Lx::Task::List *waiters = static_cast<Lx::Task::List *>(m->waiters);
if (m->state == MUTEX_WAITERS)
while (Lx::Task::List_element *le = waiters->first())
le->object()->mutex_unblock(waiters);
m->state = MUTEX_UNLOCKED;
m->holder = nullptr;
}
int mutex_is_locked(struct mutex *m)
{
return m->state != MUTEX_UNLOCKED;
}
int mutex_trylock(struct mutex *m)
{
if (mutex_is_locked(m))
return false;
mutex_lock(m);
return true;
}
#include <lx_emul/impl/mutex.h>
/******************
@ -1383,6 +1319,30 @@ void pci_set_drvdata(struct pci_dev *pdev, void *data)
}
static struct pcim_iomap_devres {
void *table[6];
} _devres_table;
int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask, const char *name)
{
/* XXX iwlwifi just want to map the first BAR */
void *addr = pci_ioremap_bar(pdev, 0);
if (!addr) { return -1; }
printk("%s:%d from: %p addr: %p\n", __func__, __LINE__, __builtin_return_address(0), addr);
_devres_table.table[0] = addr;
return 0;
}
void * const *pcim_iomap_table(struct pci_dev *pdev)
{
return _devres_table.table;
}
/***********************
** linux/interrupt.h **
***********************/
@ -1423,22 +1383,10 @@ void pci_dev_put(struct pci_dev *pci_dev)
#include <lx_emul/impl/work.h>
static void execute_delayed_work(unsigned long dwork)
{
Lx::Work::work_queue().schedule_delayed((struct delayed_work *)dwork, 0);
Lx::Work::work_queue().unblock();
}
bool mod_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork,
unsigned long delay)
{
/* treat delayed work without delay like any other work */
if (delay == 0) {
execute_delayed_work((unsigned long)dwork);
} else {
mod_timer(&dwork->timer, jiffies + delay);
}
queue_delayed_work(wq, dwork, delay);
return true;
}
@ -1520,3 +1468,138 @@ int wake_up_process(struct task_struct *tsk) { return 0; }
*******************/
#include <lx_emul/impl/sched.h>
/*****************
** linux/idr.h **
*****************/
struct Idr
{
enum { INVALID_ENTRY = ~0ul, };
enum { MAX_ENTRIES = 1024, };
Genode::Bit_array<MAX_ENTRIES> _barray { };
addr_t _ptr[MAX_ENTRIES] { };
void *_idp { nullptr };
bool _check(addr_t index) { return index < MAX_ENTRIES ? true : false; }
Idr(struct idr *idp) : _idp(idp) { }
virtual ~Idr() { }
bool handles(void *ptr) { return _idp == ptr; }
bool set_id(addr_t index, void *ptr)
{
if (_barray.get(index, 1)) { return false; }
_barray.set(index, 1);
_ptr[index] = ptr;
return true;
}
addr_t alloc(addr_t start, void *ptr)
{
addr_t index = INVALID_ENTRY;
for (addr_t i = start; i < MAX_ENTRIES; i++) {
if (_barray.get(i, 1)) { continue; }
index = i;
break;
}
if (index == INVALID_ENTRY) { return INVALID_ENTRY; }
_barray.set(index, 1);
_ptr[index] = ptr;
return index;
}
void clear(addr_t index)
{
if (!_check(index)) { return; }
_barray.clear(index, 1);
_ptr[index] = 0;
}
addr_t next(addr_t index)
{
for (addr_t i = index; i < MAX_ENTRIES; i++) {
if (_barray.get(i, 1)) { return i; }
}
return INVALID_ENTRY;
}
void *get_ptr(addr_t index)
{
if (!_check(index)) { return NULL; }
return (void*)_ptr[index];
}
};
static Genode::Registry<Genode::Registered<Idr>> _idr_registry;
static Idr &idp_to_idr(struct idr *idp)
{
Idr *idr = nullptr;
auto lookup = [&](Idr &i) {
if (i.handles(idp)) { idr = &i; }
};
_idr_registry.for_each(lookup);
if (!idr) {
Genode::Registered<Idr> *i = new (&Lx_kit::env().heap())
Genode::Registered<Idr>(_idr_registry, idp);
idr = &*i;
}
return *idr;
}
int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask)
{
Idr &idr = idp_to_idr(idp);
if ((end - start) > 1) {
addr_t const id = idr.alloc(start, ptr);
return id != Idr::INVALID_ENTRY ? id : -1;
} else {
if (idr.set_id(start, ptr)) { return start; }
}
return -1;
}
void *idr_find(struct idr *idp, int id)
{
Idr &idr = idp_to_idr(idp);
return idr.get_ptr(id);
}
void *idr_get_next(struct idr *idp, int *nextid)
{
Idr &idr = idp_to_idr(idp);
addr_t i = idr.next(*nextid);
if (i == Idr::INVALID_ENTRY) { return NULL; }
*nextid = i;
return idr.get_ptr(i);
}
/****************************
** asm-generic/getorder.h **
****************************/
int get_order(unsigned long size)
{
if (size < PAGE_SIZE) { return 0; }
return Genode::log2(size) - PAGE_SHIFT;
}

View File

@ -26,6 +26,8 @@
#include <lx.h>
#include <lx_emul.h>
#include <lx_kit/env.h>
#include <lx_emul/extern_c_begin.h>
# include <linux/skbuff.h>
# include <net/cfg80211.h>
@ -38,6 +40,66 @@ enum {
};
struct Tx_data
{
net_device *ndev;
struct sk_buff *skb;
Lx::Task *task;
int err;
};
static Lx::Task *_tx_task;
static Tx_data _tx_data;
static void _run_tx_task(void *args)
{
Tx_data *data = static_cast<Tx_data*>(args);
while (1) {
Lx::scheduler().current()->block_and_schedule();
net_device *ndev = data->ndev;
struct sk_buff *skb = data->skb;
data->err = ndev->netdev_ops->ndo_start_xmit(skb, ndev);
if (data->err) {
Genode::warning("xmit failed: ", data->err, " skb: ", skb);
}
data->skb = nullptr;
if (data->task) {
data->task->unblock();
data->task = nullptr;
}
}
}
bool tx_task_send(struct sk_buff *skb)
{
if (_tx_data.skb) {
Genode::error("skb: ", skb, " already queued");
return false;
}
if (!_tx_task) {
Genode::error("no TX task available");
return false;
}
_tx_data.ndev = skb->dev;
_tx_data.skb = skb;
_tx_data.task = Lx::scheduler().current();
_tx_task->unblock();
Lx::scheduler().current()->block_and_schedule();
return true;
}
/**
* Nic::Session implementation
*/
@ -48,29 +110,6 @@ class Wifi_session_component : public Nic::Session_component
net_device *_ndev;
bool _has_link = !(_ndev->state & 1UL << __LINK_STATE_NOCARRIER);
struct Tx_data
{
net_device *ndev;
struct sk_buff *skb;
} _tx_data;
static void _run_tx_task(void *args)
{
Tx_data *data = static_cast<Tx_data*>(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);
}
}
Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task",
Lx::Task::PRIORITY_1, Lx::scheduler() };
protected:
bool _send()
@ -86,6 +125,15 @@ class Wifi_session_component : public Nic::Session_component
return false;
}
/* XXX enable as soon as the other stack plays along
if (!_has_link) {
Packet_descriptor packet = _tx.sink()->get_packet();
_tx.sink()->acknowledge_packet(packet);
Genode::warning("no link, drop packet");
return true;
}
*/
if (!_tx.sink()->ready_to_ack()) { return false; }
if (!_tx.sink()->packet_avail()) { return false; }
@ -97,13 +145,15 @@ class Wifi_session_component : public Nic::Session_component
struct sk_buff *skb = lxc_alloc_skb(packet.size() + HEAD_ROOM, HEAD_ROOM);
skb->dev = _ndev;
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();
_tx_task->unblock();
Lx::scheduler().schedule();
_tx.sink()->acknowledge_packet(packet);
@ -180,7 +230,6 @@ class Wifi_session_component : public Nic::Session_component
}
}
/*****************************
** NIC-component interface **
*****************************/
@ -264,17 +313,10 @@ class Root : public Genode::Root_component<Wifi_session_component,
Root *Root::instance;
static Genode::Env *_env;
static Genode::Allocator *_alloc;
void Lx::nic_init(Genode::Env &env, Genode::Allocator &alloc)
{
static Root root(env, alloc);
Root::instance = &root;
_env = &env;
_alloc = &alloc;
}
@ -288,6 +330,7 @@ namespace Lx {
class Notifier;
}
class Lx::Notifier
{
private:
@ -302,9 +345,19 @@ class Lx::Notifier
Lx_kit::List<Block> _list;
Genode::Tslab<Block, 32 * sizeof(Block)> _block_alloc;
void *_ptr;
public:
Notifier() : _block_alloc(_alloc) { }
Notifier(Genode::Allocator &alloc, void *ptr)
: _block_alloc(&alloc), _ptr(ptr) { }
virtual ~Notifier() { };
bool handles(void *ptr)
{
return _ptr == ptr;
}
void register_block(struct notifier_block *nb)
{
@ -335,29 +388,46 @@ class Lx::Notifier
};
static Genode::Registry<Genode::Registered<Lx::Notifier>> _blocking_notifier_registry;
/* XXX move blocking_notifier_call to proper location */
/**********************
** linux/notifier.h **
**********************/
static Lx::Notifier &blocking_notifier()
static Lx::Notifier &blocking_notifier(struct blocking_notifier_head *nh)
{
static Lx::Notifier inst;
return inst;
Lx::Notifier *notifier = nullptr;
auto lookup = [&](Lx::Notifier &n) {
if (!n.handles(nh)) { return; }
notifier = &n;
};
_blocking_notifier_registry.for_each(lookup);
if (!notifier) {
Genode::Registered<Lx::Notifier> *n = new (&Lx_kit::env().heap())
Genode::Registered<Lx::Notifier>(_blocking_notifier_registry,
Lx_kit::env().heap(), nh);
notifier = &*n;
}
return *notifier;
}
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *nb)
{
blocking_notifier().register_block(nb);
blocking_notifier(nh).register_block(nb);
return 0;
}
int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
struct notifier_block *nb)
{
blocking_notifier().unregister_block(nb);
blocking_notifier(nh).unregister_block(nb);
return 0;
}
@ -365,7 +435,7 @@ int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v)
{
return blocking_notifier().call_all_blocks(val, v);
return blocking_notifier(nh).call_all_blocks(val, v);
}
@ -375,7 +445,7 @@ int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
static Lx::Notifier &net_notifier()
{
static Lx::Notifier inst;
static Lx::Notifier inst(Lx_kit::env().heap(), NULL);
return inst;
}
@ -446,7 +516,7 @@ class Proto_hook_list
static Proto_hook_list& proto_hook_list()
{
static Proto_hook_list inst(*_alloc);
static Proto_hook_list inst(Lx_kit::env().heap());
return inst;
}
@ -512,15 +582,12 @@ extern "C" int dev_queue_xmit(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct net_device_ops const *ops = dev->netdev_ops;
int rv = NETDEV_TX_OK;
if (skb->next) {
Genode::warning("more skb's queued");
}
rv = ops->ndo_start_xmit(skb, dev);
return rv;
return tx_task_send(skb) ? NETDEV_TX_OK : -1;
}
@ -568,10 +635,15 @@ extern "C" int register_netdevice(struct net_device *ndev)
int err = ndev->netdev_ops->ndo_open(ndev);
if (err) {
Genode::error("ndo_open() failed: ", err);
Genode::error("Initializing device failed");
throw -1;
return err;
}
static Lx::Task tx_task { _run_tx_task, &_tx_data, "tx_task",
Lx::Task::PRIORITY_1, Lx::scheduler() };
_tx_task = &tx_task;
if (ndev->netdev_ops->ndo_set_rx_mode)
ndev->netdev_ops->ndo_set_rx_mode(ndev);
@ -693,7 +765,7 @@ extern "C" struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name
/* ensure 32-byte alignment of whole construct */
alloc_size += NETDEV_ALIGN - 1;
p = (net_device *)kzalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
p = (net_device *)kzalloc(alloc_size, GFP_KERNEL);
if (!p)
return NULL;

View File

@ -0,0 +1,104 @@
/*
* \brief Linux random emulation code
* \author Josef Soentgen
* \date 2016-10-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/fixed_stdint.h>
#include <util/string.h>
using Genode::uint64_t;
/*
* Xoroshiro128+ written in 2014-2016 by Sebastiano Vigna (vigna@acm.org)
*
* (see http://xoroshiro.di.unimi.it/xorshift128plus.c and
* http://xoroshiro.di.unimi.it/splitmix64.c)
*/
struct Xoroshiro
{
uint64_t seed;
uint64_t splitmix64()
{
uint64_t z = (seed += __UINT64_C(0x9E3779B97F4A7C15));
z = (z ^ (z >> 30)) * __UINT64_C(0xBF58476D1CE4E5B9);
z = (z ^ (z >> 27)) * __UINT64_C(0x94D049BB133111EB);
return z ^ (z >> 31);
}
Xoroshiro(uint64_t seed) : seed(seed)
{
s[0] = splitmix64();
s[1] = splitmix64();
}
uint64_t s[2];
static uint64_t rotl(uint64_t const x, int k) {
return (x << k) | (x >> (64 - k));
}
uint64_t get()
{
uint64_t const s0 = s[0];
uint64_t s1 = s[1];
uint64_t const result = s0 + s1;
s1 ^= s0;
s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
s[1] = rotl(s1, 36);
return result;
}
};
static Xoroshiro xoroshiro(0x636864324d766931);
/********************
** linux/random.h **
********************/
extern "C" void get_random_bytes(void *buf, int nbytes)
{
if (nbytes <= 0) {
return;
}
char *p = reinterpret_cast<char*>(buf);
int const rounds = nbytes / 8;
for (int i = 0; i < rounds; i++) {
uint64_t const v = xoroshiro.get();
Genode::memcpy(p, &v, 8);
p += 8;
}
int const remain = nbytes - rounds * 8;
if (!remain) {
return;
}
uint64_t const v = xoroshiro.get();
Genode::memcpy(p, &v, remain);
}
extern "C" unsigned int prandom_u32(void)
{
return xoroshiro.get();
}

View File

@ -100,4 +100,8 @@ int linux_br_del_if(int sock, const char *brname, const char *ifname) {
int linux_br_get(char *brname, const char *ifname) { return -1; }
int linux_master_get(char *master_ifname, const char *ifname) {
return -1; }
} /* extern "C" */

View File

@ -0,0 +1,96 @@
/*
* WPA Supplicant / UNIX domain socket -based control interface
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/list.h"
#include "common/ctrl_iface_common.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "config.h"
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
};
struct ctrl_iface_global_priv {
struct wpa_global *global;
};
struct ctrl_iface_msg {
struct wpa_supplicant *wpa_s;
};
struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
printf("%s:%d\n", __func__, __LINE__);
struct ctrl_iface_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
if (wpa_s->conf->ctrl_interface == NULL)
return priv;
return priv;
}
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
{
printf("%s:%d\n", __func__, __LINE__);
struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg;
struct ctrl_iface_global_priv *gpriv;
os_free(priv);
}
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
printf("%s:%d\n", __func__, __LINE__);
}
struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{
printf("%s:%d\n", __func__, __LINE__);
struct ctrl_iface_global_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
if (global->params.ctrl_interface == NULL)
return priv;
return priv;
}
void wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
printf("%s:%d\n", __func__, __LINE__);
struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg;
os_free(priv);
}

View File

@ -63,6 +63,7 @@ int wpa_main(int debug_msg, int interval)
memset(&params, 0, sizeof(params));
params.wpa_debug_level = debug_msg ? MSG_DEBUG : MSG_INFO;
params.ctrl_interface = "GENODE";
global = wpa_supplicant_init(&params);
if (global == NULL)
@ -73,7 +74,7 @@ int wpa_main(int debug_msg, int interval)
iface.ifname = "wlan0";
iface.confname = conf_file;
if (wpa_supplicant_add_iface(global, &iface) == NULL)
if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL)
exitcode = -1;
if (connected_scan_interval > 0)

View File

@ -43,7 +43,7 @@ extern "C" void wpa_reporter_init(void *env)
}
enum { SSID_MAX_LEN = 32 + 1, MAC_STR_LEN = 6*2 + 5 + 1};
enum { SSID_STRING_MAX_LEN = 32 + 1, MAC_STR_LEN = 6*2 + 5 + 1};
static inline void mac2str(char *buf, u8 const *mac)
@ -60,7 +60,7 @@ extern "C" void wpa_report_connect_event(struct wpa_supplicant *wpa_s)
struct wpa_ssid *wpa_ssid = wpa_s->current_ssid;
/* FIXME ssid may contain any characters, even NUL */
Genode::String<SSID_MAX_LEN>
Genode::String<SSID_STRING_MAX_LEN>
ssid(Genode::Cstring((char *)wpa_ssid->ssid, wpa_ssid->ssid_len));
char bssid_buf[MAC_STR_LEN];

View File

@ -17,6 +17,9 @@
os_*;
wpa_*;
wpabuf_*;
sha1_vector*;
get_ie*;
fc2str*;
local: