mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-23 09:15:36 +00:00
committed by
Christian Helmuth
parent
0106045bad
commit
b9e7fb1edf
@ -231,10 +231,12 @@ struct Main
|
||||
:
|
||||
_ep(ep)
|
||||
{
|
||||
Genode::Xml_node config = Genode::config()->xml_node();
|
||||
try {
|
||||
config_verbose = Genode::config()->xml_node().attribute("verbose").has_value("yes");
|
||||
config_verbose = config.attribute("verbose").has_value("yes");
|
||||
} catch (...) { }
|
||||
_wpa = new (Genode::env()->heap()) Wpa_thread(wpa_startup_lock());
|
||||
|
||||
_wpa = new (Genode::env()->heap()) Wpa_thread(wpa_startup_lock(), config_verbose);
|
||||
|
||||
_wpa->start();
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* entry function */
|
||||
extern "C" int wpa_main(void);
|
||||
extern "C" int wpa_main(int);
|
||||
extern "C" void wpa_conf_reload(void);
|
||||
|
||||
class Wpa_thread : public Genode::Thread_deprecated<8 * 1024 * sizeof(long)>
|
||||
@ -26,18 +26,21 @@ class Wpa_thread : public Genode::Thread_deprecated<8 * 1024 * sizeof(long)>
|
||||
private:
|
||||
|
||||
Genode::Lock &_lock;
|
||||
int _exit;
|
||||
int _exit;
|
||||
bool _debug_msg;
|
||||
|
||||
public:
|
||||
|
||||
Wpa_thread(Genode::Lock &lock)
|
||||
: Thread_deprecated("wpa_supplicant"), _lock(lock), _exit(-1) { }
|
||||
Wpa_thread(Genode::Lock &lock, bool debug_msg)
|
||||
:
|
||||
Thread_deprecated("wpa_supplicant"),
|
||||
_lock(lock), _exit(-1), _debug_msg(debug_msg) { }
|
||||
|
||||
void entry()
|
||||
{
|
||||
/* wait until the wifi driver is up and running */
|
||||
_lock.lock();
|
||||
_exit = wpa_main();
|
||||
_exit = wpa_main(_debug_msg);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
};
|
||||
|
@ -180,6 +180,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
|
||||
w_msg.msg_iovlen = 1;
|
||||
w_msg.msg_iov[0].iov_base = buf;
|
||||
w_msg.msg_iov[0].iov_len = len;
|
||||
w_msg.msg_count = len;
|
||||
|
||||
/* FIXME convert to/from Sockaddr */
|
||||
/* FIXME flags values */
|
||||
@ -221,6 +222,7 @@ ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
|
||||
for (unsigned i = 0; i < w_msg.msg_iovlen; ++i) {
|
||||
w_msg.msg_iov[i].iov_base = msg->msg_iov[i].iov_base;
|
||||
w_msg.msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
|
||||
w_msg.msg_count += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
|
||||
w_msg.msg_control = msg->msg_control;
|
||||
@ -279,6 +281,7 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
|
||||
for (unsigned i = 0; i < w_msg.msg_iovlen; ++i) {
|
||||
w_msg.msg_iov[i].iov_base = msg->msg_iov[i].iov_base;
|
||||
w_msg.msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
|
||||
w_msg.msg_count += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
|
||||
int const err = socket_call.sendmsg(s, &w_msg, Wifi::WIFI_F_NONE);
|
||||
@ -306,6 +309,7 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
||||
w_msg.msg_iovlen = 1;
|
||||
w_msg.msg_iov[0].iov_base = const_cast<void*>(buf);
|
||||
w_msg.msg_iov[0].iov_len = len;
|
||||
w_msg.msg_count = len;
|
||||
|
||||
/* FIXME convert to/from Sockaddr */
|
||||
/* FIXME flags values */
|
||||
|
@ -5,19 +5,20 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
extern "C" {
|
||||
typedef long DUMMY;
|
||||
|
||||
enum {
|
||||
SHOW_DUMMY = 0,
|
||||
SHOW_DUMMY = 1,
|
||||
SHOW_SKIP = 0,
|
||||
SHOW_RET = 0,
|
||||
};
|
||||
@ -36,6 +37,15 @@ enum {
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define DUMMY_STOP(retval, name) \
|
||||
DUMMY name(void) { \
|
||||
do { \
|
||||
PWRN( #name " called (from %p) stopped", __builtin_return_address(0)); \
|
||||
Genode::sleep_forever(); \
|
||||
} while (0); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define DUMMY_RET(retval, name) \
|
||||
DUMMY name(void) { \
|
||||
if (SHOW_RET) \
|
||||
@ -114,8 +124,8 @@ DUMMY_SKIP(0, local_bh_disable)
|
||||
DUMMY_SKIP(0, local_bh_enable)
|
||||
DUMMY_SKIP(0, dma_unmap_page)
|
||||
|
||||
/*FIXME*/DUMMY(0, dma_set_coherent_mask)
|
||||
/*FIXME*/DUMMY(0, dma_set_mask)
|
||||
DUMMY_SKIP(0, dma_set_coherent_mask) /* we set the mask always to ~0UL */
|
||||
DUMMY_SKIP(0, dma_set_mask) /* in the PCI driver */
|
||||
DUMMY(-1, dma_sync_single_for_cpu)
|
||||
DUMMY(-1, dma_sync_single_for_device)
|
||||
|
||||
@ -148,11 +158,9 @@ DUMMY(-1, generic_pipe_buf_confirm)
|
||||
DUMMY(-1, generic_pipe_buf_map)
|
||||
DUMMY(-1, generic_pipe_buf_unmap)
|
||||
DUMMY(-1, linkwatch_fire_event)
|
||||
DUMMY(-1, mod_delayed_work)
|
||||
DUMMY(-1, need_resched)
|
||||
DUMMY(-1, open_softirq)
|
||||
DUMMY(-1, raw_notifier_chain_unregister)
|
||||
DUMMY(-1, system_wq)
|
||||
DUMMY(-1, vlan_do_receive)
|
||||
DUMMY(-1, vlan_untag)
|
||||
DUMMY(-1, yield)
|
||||
@ -163,7 +171,7 @@ DUMMY(-1, add_device_randomness)
|
||||
DUMMY(0, add_uevent_var)
|
||||
DUMMY(0, atomic64_read)
|
||||
DUMMY(0, bitmap_empty)
|
||||
DUMMY(0, call_rcu)
|
||||
DUMMY_SKIP(0, call_rcu)
|
||||
DUMMY(0, csum_block_add)
|
||||
DUMMY(0, csum_fold)
|
||||
DUMMY(0, csum_partial)
|
||||
@ -194,7 +202,6 @@ DUMMY(0, idr_find)
|
||||
DUMMY(0, idr_for_each)
|
||||
DUMMY(0, idr_init)
|
||||
DUMMY(0, idr_remove)
|
||||
DUMMY(0, init_timer_deferrable)
|
||||
DUMMY(0, ip_hdr)
|
||||
DUMMY(0, ipv4_get_dsfield)
|
||||
DUMMY(0, ipv6_get_dsfield)
|
||||
@ -209,7 +216,7 @@ DUMMY(0, kstrtoul)
|
||||
DUMMY(0, linkwatch_init_dev)
|
||||
DUMMY(0, local_softirq_pending)
|
||||
DUMMY(0, mb)
|
||||
DUMMY(0, misc_register)
|
||||
DUMMY_SKIP(0, misc_register)
|
||||
DUMMY(0, mmiowb)
|
||||
DUMMY(0, net_dmaengine_put)
|
||||
DUMMY(0, net_info_ratelimited)
|
||||
@ -256,8 +263,6 @@ DUMMY(0, poll_wait)
|
||||
DUMMY(0, preempt_disable)
|
||||
DUMMY(0, preempt_enable)
|
||||
DUMMY(0, put_cpu)
|
||||
DUMMY(0, put_unaligned_be16)
|
||||
DUMMY(0, put_unaligned_le16)
|
||||
DUMMY(0, put_unaligned_le64)
|
||||
DUMMY(0, qdisc_all_tx_empty)
|
||||
DUMMY(0, raise_softirq_irqoff)
|
||||
@ -287,7 +292,7 @@ DUMMY(0, this_cpu_inc)
|
||||
DUMMY(0, toupper)
|
||||
DUMMY(0, wait_event_interruptible)
|
||||
DUMMY(0, work_busy)
|
||||
DUMMY(0, class_register)
|
||||
DUMMY_SKIP(0, class_register)
|
||||
DUMMY(0, class_unregister)
|
||||
DUMMY(0, debugfs_remove)
|
||||
DUMMY(0, dev_set_uevent_suppress)
|
||||
@ -312,14 +317,13 @@ DUMMY(0, kernel_sendmsg)
|
||||
DUMMY(0, put_cmsg)
|
||||
DUMMY(0, put_cred)
|
||||
DUMMY(0, put_pid)
|
||||
DUMMY(0, remove_wait_queue)
|
||||
DUMMY(0, schedule)
|
||||
DUMMY(-1, security_sk_free)
|
||||
DUMMY(0, set_current_state)
|
||||
DUMMY(0, signal_pending)
|
||||
DUMMY(0, smp_wmb)
|
||||
DUMMY(0, sock_update_classid)
|
||||
DUMMY(0, sock_update_netprioidx)
|
||||
DUMMY_SKIP(0, sock_update_classid)
|
||||
DUMMY_SKIP(0, sock_update_netprioidx)
|
||||
DUMMY(0, sock_wake_async)
|
||||
DUMMY(0, static_key_slow_dec)
|
||||
DUMMY(0, task_tgid_vnr)
|
||||
@ -332,8 +336,6 @@ DUMMY(-1, csum_partial_ext)
|
||||
DUMMY(-1, genl_register_family_with_ops_groups)
|
||||
DUMMY(-1, ktime_sub)
|
||||
DUMMY(-1, sg_init_one)
|
||||
DUMMY(-1, sg_init_table)
|
||||
DUMMY(-1, sg_set_buf)
|
||||
DUMMY(-1, vlan_hw_offload_capable)
|
||||
DUMMY(-1, vlan_tx_tag_get_id)
|
||||
DUMMY(-1, vzalloc)
|
||||
@ -363,26 +365,19 @@ DUMMY(-1, unregister_pernet_device)
|
||||
DUMMY(0, __hw_addr_init)
|
||||
DUMMY(0, __hw_addr_sync)
|
||||
DUMMY(0, __hw_addr_unsync)
|
||||
DUMMY(0, dev_alloc_name)
|
||||
DUMMY_SKIP(0, dev_alloc_name)
|
||||
DUMMY(0, dev_change_net_namespace)
|
||||
DUMMY(0, dev_close)
|
||||
DUMMY(0, dev_kfree_skb_any)
|
||||
DUMMY(0, dev_net_set)
|
||||
DUMMY_SKIP(0, dev_net_set)
|
||||
DUMMY(0, dev_open)
|
||||
DUMMY_SKIP(0, dev_hold)
|
||||
DUMMY_SKIP(0, dev_put)
|
||||
DUMMY(0, dst_release)
|
||||
DUMMY(0, free_netdev)
|
||||
DUMMY(0, net_disable_timestamp)
|
||||
DUMMY(0, netdev_set_default_ethtool_ops)
|
||||
DUMMY(0, netif_rx_ni)
|
||||
DUMMY(0, netif_start_subqueue)
|
||||
DUMMY(0, netif_stop_subqueue)
|
||||
DUMMY(0, netif_tx_start_all_queues)
|
||||
DUMMY(0, netif_tx_stop_all_queues)
|
||||
DUMMY(0, netif_wake_subqueue)
|
||||
DUMMY(0, next_net_device)
|
||||
DUMMY(0, synchronize_net)
|
||||
DUMMY_SKIP(0, synchronize_net)
|
||||
DUMMY(0, unregister_netdevice_many)
|
||||
DUMMY(0, unregister_netdevice_notifier)
|
||||
DUMMY(0, unregister_netdevice_queue)
|
||||
@ -404,11 +399,8 @@ DUMMY(0, device_can_wakeup)
|
||||
DUMMY(0, device_reprobe)
|
||||
DUMMY(0, device_set_wakeup_enable)
|
||||
DUMMY(0, ip_fast_csum)
|
||||
DUMMY(0, iwl_mvm_sf_update)
|
||||
DUMMY(0, prandom_u32)
|
||||
DUMMY(0, request_firmware)
|
||||
DUMMY(0, tcp_v4_check)
|
||||
DUMMY(0, netif_rx)
|
||||
DUMMY(0, sk_attach_filter)
|
||||
|
||||
DUMMY(0, __class_create)
|
||||
@ -464,8 +456,6 @@ DUMMY(0, rfkill_remove_epo_lock)
|
||||
DUMMY(0, rfkill_restore_states)
|
||||
DUMMY(0, rfkill_switch_all)
|
||||
DUMMY(0, send_sigurg)
|
||||
DUMMY(0, sg_mark_end)
|
||||
DUMMY(0, sg_set_page)
|
||||
DUMMY(0, simple_strtoul)
|
||||
DUMMY(0, skb_gro_len)
|
||||
DUMMY(0, skb_gro_offset)
|
||||
@ -482,12 +472,9 @@ DUMMY(0, xfrm_sk_free_policy)
|
||||
DUMMY(0, strncpy)
|
||||
|
||||
DUMMY(0, __ethtool_get_settings)
|
||||
DUMMY(0, __netif_tx_lock_bh)
|
||||
DUMMY(0, __netif_tx_unlock_bh)
|
||||
DUMMY(0, __skb_get_hash)
|
||||
DUMMY(0, __sock_recv_ts_and_drops)
|
||||
DUMMY(0, cpu_relax)
|
||||
DUMMY(0, dev_get_by_index_rcu)
|
||||
DUMMY(0, dev_get_by_name)
|
||||
DUMMY(0, dev_get_by_name_rcu)
|
||||
DUMMY(0, dev_mc_add)
|
||||
@ -504,9 +491,6 @@ DUMMY(0, getnstimeofday)
|
||||
DUMMY(0, ip_check_defrag)
|
||||
DUMMY(0, ktime_to_timespec_cond)
|
||||
DUMMY(0, netdev_get_tx_queue)
|
||||
DUMMY(0, netif_skb_features)
|
||||
DUMMY(0, netif_supports_nofcs)
|
||||
DUMMY(0, netif_xmit_frozen_or_stopped)
|
||||
DUMMY(0, offset_in_page)
|
||||
DUMMY(0, prandom_u32_max)
|
||||
DUMMY(0, raw_smp_processor_id)
|
||||
@ -541,23 +525,72 @@ DUMMY(0, netdev_boot_setup)
|
||||
DUMMY(0, netdev_master_upper_dev_get)
|
||||
DUMMY(0, netdev_state_change)
|
||||
DUMMY(0, netdev_unregistering_wq)
|
||||
DUMMY(0, netif_dormant)
|
||||
|
||||
DUMMY(0, autoremove_wake_function)
|
||||
DUMMY(0, get_user_pages_fast)
|
||||
DUMMY(0, iov_length)
|
||||
DUMMY(0, memcpy_toiovecend)
|
||||
DUMMY(0, netdev_rx_csum_fault)
|
||||
DUMMY(0, release_pages)
|
||||
DUMMY(0, sk_busy_loop)
|
||||
DUMMY(0, sk_can_busy_loop)
|
||||
|
||||
DUMMY(0, sg_next)
|
||||
DUMMY(0, complete_all)
|
||||
DUMMY(0, module_put_and_exit)
|
||||
DUMMY(0, simple_strtol)
|
||||
DUMMY(0, alg_test)
|
||||
DUMMY_SKIP(0, complete_all)
|
||||
DUMMY_SKIP(0, module_put_and_exit)
|
||||
DUMMY_SKIP(0, simple_strtol)
|
||||
DUMMY_SKIP(0, alg_test)
|
||||
|
||||
DUMMY(0, alloc_workqueue)
|
||||
DUMMY(0, __cfg80211_leave_ocb)
|
||||
DUMMY(0, __skb_flow_dissect)
|
||||
DUMMY(0, __sock_tx_timestamp)
|
||||
DUMMY(0, bpf_prog_create_from_user)
|
||||
DUMMY(0, bpf_prog_destroy)
|
||||
DUMMY(0, bpf_prog_run_clear_cb)
|
||||
DUMMY(0, cfg80211_join_ocb)
|
||||
DUMMY(0, cfg80211_leave_ocb)
|
||||
DUMMY(0, class_find_device)
|
||||
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(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(0, init_dummy_netdev)
|
||||
DUMMY(0, napi_gro_flush)
|
||||
DUMMY(0, netdev_start_xmit)
|
||||
DUMMY_RET(0, netdev_uses_dsa)
|
||||
DUMMY_RET(0, page_is_pfmemalloc)
|
||||
DUMMY_RET(0, peernet2id)
|
||||
DUMMY(0, pr_err_once)
|
||||
DUMMY(0, sk_attach_bpf)
|
||||
DUMMY(0, sk_filter_uncharge)
|
||||
DUMMY(0, skb_checksum_help)
|
||||
DUMMY(0, skb_get_tx_queue)
|
||||
DUMMY(0, skb_gso_segment)
|
||||
DUMMY(0, skb_vlan_tag_get)
|
||||
DUMMY(0, skb_vlan_tag_present)
|
||||
DUMMY(0, smp_mb__before_atomic)
|
||||
DUMMY(0, sock_diag_broadcast_destroy)
|
||||
DUMMY(0, sock_diag_has_destroy_listeners)
|
||||
DUMMY(0, switchdev_port_attr_get)
|
||||
|
||||
DUMMY_RET(0, netif_dormant)
|
||||
DUMMY(0, netif_napi_add)
|
||||
DUMMY(0, netif_napi_del)
|
||||
DUMMY_STOP(0, netif_rx)
|
||||
DUMMY(0, netif_skb_features)
|
||||
DUMMY(0, netif_supports_nofcs)
|
||||
DUMMY(0, netif_xmit_frozen_or_drv_stopped)
|
||||
DUMMY(0, netif_xmit_frozen_or_stopped)
|
||||
DUMMY_STOP(0, netif_rx_ni)
|
||||
DUMMY_STOP(0, netif_tx_start_all_queues)
|
||||
DUMMY_STOP(0, netif_tx_stop_all_queues)
|
||||
|
||||
DUMMY(0, peernet_has_id)
|
||||
DUMMY(0, peernet2id_alloc)
|
||||
|
||||
} /* extern "C" */
|
||||
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* \brief Completions and events
|
||||
* \author Christian Helmuth
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
#include <scheduler.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
static bool const verbose = false;
|
||||
#define PWRNV(...) do { if (verbose) PWRN(__VA_ARGS__); } while (0)
|
||||
|
||||
extern "C" {
|
||||
|
||||
/************************
|
||||
** linux/completion.h **
|
||||
************************/
|
||||
|
||||
typedef Lx::Task::List_element Wait_le;
|
||||
typedef Lx::Task::List Wait_list;
|
||||
|
||||
void init_waitqueue_head(wait_queue_head_t *wq)
|
||||
{
|
||||
wq->list = new (Genode::env()->heap()) Wait_list;
|
||||
}
|
||||
|
||||
|
||||
int waitqueue_active(wait_queue_head_t *wq)
|
||||
{
|
||||
Wait_list *list = static_cast<Wait_list*>(wq->list);
|
||||
if (!list)
|
||||
return 0;
|
||||
|
||||
return list->first() ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
void __wake_up(wait_queue_head_t *wq, bool all)
|
||||
{
|
||||
Wait_list *list = static_cast<Wait_list *>(wq->list);
|
||||
if (!list) {
|
||||
PWRNV("wait_queue_head_t is empty, wq: %p called from: %p", wq, __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
|
||||
Wait_le *le = list->first();
|
||||
do {
|
||||
if (!le)
|
||||
return;
|
||||
|
||||
le->object()->unblock();
|
||||
} while (all && (le = le->next()));
|
||||
}
|
||||
|
||||
|
||||
void wake_up_interruptible_sync_poll(wait_queue_head_t *wq, int)
|
||||
{
|
||||
__wake_up(wq, false);
|
||||
}
|
||||
|
||||
|
||||
void __wait_event(wait_queue_head_t wq)
|
||||
{
|
||||
Wait_list *list = static_cast<Wait_list *>(wq.list);
|
||||
if (!list) {
|
||||
PERR("__wait_event(): empty list in wq: %p", &wq);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
Lx::Task *task = Lx::scheduler().current();
|
||||
|
||||
task->wait_enqueue(list);
|
||||
task->block_and_schedule();
|
||||
task->wait_dequeue(list);
|
||||
}
|
||||
|
||||
|
||||
void init_completion(struct completion *work)
|
||||
{
|
||||
work->done = 0;
|
||||
}
|
||||
|
||||
|
||||
void complete(struct completion *work)
|
||||
{
|
||||
work->done = 1;
|
||||
}
|
||||
|
||||
|
||||
static void __wait_completion(struct completion *work)
|
||||
{
|
||||
// PERR("%s:%d: FIXME", __func__, __LINE__);
|
||||
}
|
||||
|
||||
|
||||
unsigned long wait_for_completion_timeout(struct completion *work,
|
||||
unsigned long timeout)
|
||||
{
|
||||
__wait_completion(work);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int wait_for_completion_interruptible(struct completion *work)
|
||||
{
|
||||
__wait_completion(work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long wait_for_completion_interruptible_timeout(struct completion *work,
|
||||
unsigned long timeout)
|
||||
{
|
||||
__wait_completion(work);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void wait_for_completion(struct completion *work)
|
||||
{
|
||||
__wait_completion(work);
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
** linux/wait.h **
|
||||
******************/
|
||||
|
||||
void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *w, int state)
|
||||
{
|
||||
if (!q) {
|
||||
PWRNV("prepare_to_wait: wait_queue_head_t is 0, ignore, called from: %p",
|
||||
__builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
|
||||
Wait_list *list = static_cast<Wait_list *>(q->list);
|
||||
Lx::Task *task = Lx::scheduler().current();
|
||||
|
||||
task->wait_enqueue(list);
|
||||
}
|
||||
|
||||
|
||||
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *w, int state)
|
||||
{
|
||||
prepare_to_wait(q, w, state);
|
||||
}
|
||||
|
||||
|
||||
void finish_wait(wait_queue_head_t *q, wait_queue_t *w)
|
||||
{
|
||||
if (!q) {
|
||||
PWRNV("finish_wait: wait_queue_head_t is 0, ignore, called from: %p",
|
||||
__builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
|
||||
Wait_list *list = static_cast<Wait_list *>(q->list);
|
||||
Lx::Task *task = Lx::scheduler().current();
|
||||
|
||||
task->wait_dequeue(list);
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** linux/timer.h **
|
||||
*******************/
|
||||
|
||||
signed long schedule_timeout_uninterruptible(signed long timeout)
|
||||
{
|
||||
// PERR("%s:%d: FIXME", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wake_up_process(struct task_struct *tsk)
|
||||
{
|
||||
// PERR("%s:%d: FIXME does task: %p needs to be woken up?", __func__, __LINE__, tsk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* \brief Include before including Linux headers in C++
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-08-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#define extern_c_begin
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* some warnings should only be switched of for Linux headers */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-arith"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/* deal with C++ keywords used for identifiers etc. */
|
||||
#define private private_
|
||||
#define class class_
|
||||
#define new new_
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* \brief Include after including Linux headers in C++
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-08-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#undef new
|
||||
#undef class
|
||||
#undef private
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} /* extern "C" */
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -18,9 +18,9 @@ typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
struct Firmware_list
|
||||
{
|
||||
char const *name;
|
||||
char const *requested_name;
|
||||
size_t size;
|
||||
char const *available_name;
|
||||
};
|
||||
|
||||
#endif /* _FIRMWARE_LIST_H_ */
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* \brief Slightly improved list
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-09-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
#include <util/list.h>
|
||||
|
||||
|
||||
namespace Lx {
|
||||
template <typename> class List;
|
||||
template <typename> class List_element;
|
||||
}
|
||||
|
||||
template <typename LT>
|
||||
class Lx::List : private Genode::List<LT>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::List<LT> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::Element;
|
||||
|
||||
void append(LT const *le)
|
||||
{
|
||||
LT *at = nullptr;
|
||||
|
||||
for (LT *l = first(); l; l = l->next())
|
||||
at = l;
|
||||
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
void prepend(LT const *le)
|
||||
{
|
||||
Base::insert(le);
|
||||
}
|
||||
|
||||
void insert_before(LT const *le, LT const *at)
|
||||
{
|
||||
if (at == first()) {
|
||||
prepend(le);
|
||||
return;
|
||||
} else if (!at) {
|
||||
append(le);
|
||||
return;
|
||||
}
|
||||
|
||||
for (LT *l = first(); l; l = l->next())
|
||||
if (l->next() == at)
|
||||
at = l;
|
||||
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
** Genode::List interface **
|
||||
****************************/
|
||||
|
||||
LT *first() { return Base::first(); }
|
||||
LT const *first() const { return Base::first(); }
|
||||
|
||||
void insert(LT const *le, LT const *at = 0)
|
||||
{
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
void remove(LT const *le)
|
||||
{
|
||||
Base::remove(le);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class Lx::List_element : public Lx::List<List_element<T> >::Element
|
||||
{
|
||||
private:
|
||||
|
||||
T *_object;
|
||||
|
||||
public:
|
||||
|
||||
List_element(T *object) : _object(object) { }
|
||||
|
||||
T *object() const { return _object; }
|
||||
};
|
||||
|
||||
#endif /* _LIST_H_ */
|
File diff suppressed because it is too large
Load Diff
6
repos/dde_linux/src/lib/wifi/include/net/protocol.h
Normal file
6
repos/dde_linux/src/lib/wifi/include/net/protocol.h
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
* net/core/sock.c needs <net/inet_sock.h> but it does not
|
||||
* include this header directly. <net/protocol.h> is normally
|
||||
* provided by lx_emul.h and is included by sock.c.
|
||||
*/
|
||||
#include <net/inet_sock.h>
|
@ -1,249 +0,0 @@
|
||||
/*
|
||||
* \brief User-level scheduling
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Christian Helmuth
|
||||
* \date 2012-04-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SCHEDULER_H_
|
||||
#define _SCHEDULER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <setjmp.h>
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
|
||||
|
||||
namespace Lx {
|
||||
class Scheduler;
|
||||
class Task;
|
||||
|
||||
Scheduler &scheduler();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allows pseudo-parallel execution of functions
|
||||
*/
|
||||
class Lx::Task : public Lx::List<Lx::Task>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* TODO generalize - higher is more important
|
||||
*/
|
||||
enum Priority { PRIORITY_0, PRIORITY_1, PRIORITY_2, PRIORITY_3 };
|
||||
|
||||
/**
|
||||
* Runtime state
|
||||
*
|
||||
* INIT
|
||||
* |
|
||||
* [run]
|
||||
* v
|
||||
* BLOCKED <--[block]--- RUNNING ---[mutex_block]--> MUTEX_BLOCKED
|
||||
* --[unblock]-> <-[mutex_unblock]--
|
||||
*
|
||||
* Transitions between BLOCKED and MUTEX_BLOCKED are not possible.
|
||||
*/
|
||||
enum State { STATE_INIT, STATE_RUNNING, STATE_BLOCKED, STATE_MUTEX_BLOCKED, STATE_WAIT_BLOCKED };
|
||||
|
||||
/**
|
||||
* List element type
|
||||
*/
|
||||
typedef Lx::List_element<Lx::Task> List_element;
|
||||
|
||||
/**
|
||||
* List type
|
||||
*/
|
||||
typedef Lx::List<List_element> List;
|
||||
|
||||
private:
|
||||
|
||||
State _state = STATE_INIT;
|
||||
|
||||
/* sub-classes may overwrite the runnable condition */
|
||||
virtual bool _runnable() const;
|
||||
|
||||
void *_stack = nullptr; /* stack pointer */
|
||||
jmp_buf _env; /* execution state */
|
||||
jmp_buf _saved_env; /* saved state of thread calling run() */
|
||||
|
||||
Priority _priority;
|
||||
Scheduler &_scheduler; /* scheduler this task is attached to */
|
||||
|
||||
void (*_func)(void *); /* function to call*/
|
||||
void *_arg; /* argument for function */
|
||||
char const *_name; /* name of task */
|
||||
|
||||
List_element _mutex_le { this }; /* list element for mutex_blocked state */
|
||||
|
||||
List *_wait_list { 0 };
|
||||
List_element _wait_le { this };
|
||||
bool _wait_le_enqueued { false };
|
||||
|
||||
public:
|
||||
|
||||
Task(void (*func)(void*), void *arg, char const *name,
|
||||
Priority priority, Scheduler &scheduler);
|
||||
virtual ~Task();
|
||||
|
||||
State state() const { return _state; }
|
||||
Priority priority() const { return _priority; }
|
||||
|
||||
void wait_enqueue(List *list)
|
||||
{
|
||||
if (_wait_le_enqueued) {
|
||||
PERR("%p already queued in %p", this, _wait_list);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
_wait_le_enqueued = true;
|
||||
_wait_list = list;
|
||||
_wait_list->append(&_wait_le);
|
||||
}
|
||||
|
||||
void wait_dequeue(List *list)
|
||||
{
|
||||
if (!_wait_le_enqueued) {
|
||||
PERR("%p not queued", this);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
if (_wait_list != list) {
|
||||
PERR("especially not in list %p", list);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
_wait_list->remove(&_wait_le);
|
||||
_wait_list = 0;
|
||||
_wait_le_enqueued = false;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
** Runtime state transitions **
|
||||
*******************************/
|
||||
|
||||
void block()
|
||||
{
|
||||
if (_state == STATE_RUNNING) {
|
||||
_state = STATE_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
void unblock()
|
||||
{
|
||||
if (_state == STATE_BLOCKED) {
|
||||
_state = STATE_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void mutex_block(List *list)
|
||||
{
|
||||
if (_state == STATE_RUNNING) {
|
||||
_state = STATE_MUTEX_BLOCKED;
|
||||
list->append(&_mutex_le);
|
||||
}
|
||||
}
|
||||
|
||||
void mutex_unblock(List *list)
|
||||
{
|
||||
if (_state == STATE_MUTEX_BLOCKED) {
|
||||
_state = STATE_RUNNING;
|
||||
list->remove(&_mutex_le);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run task until next preemption point
|
||||
*
|
||||
* \return true if run, false if not runnable
|
||||
*/
|
||||
bool run();
|
||||
|
||||
/**
|
||||
* Request scheduling (of other tasks)
|
||||
*
|
||||
* Note, this task may not be blocked when calling schedule() depending
|
||||
* on the use case.
|
||||
*/
|
||||
void schedule();
|
||||
|
||||
/**
|
||||
* Shortcut to enter blocking state and request scheduling
|
||||
*/
|
||||
void block_and_schedule()
|
||||
{
|
||||
block();
|
||||
schedule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the task (mainly for debugging purposes)
|
||||
*/
|
||||
char const *name() { return _name; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scheduler
|
||||
*
|
||||
* FIXME The old mechanism for removal via check_dead() was removed and has to
|
||||
* be reimplemented later.
|
||||
*/
|
||||
class Lx::Scheduler
|
||||
{
|
||||
private:
|
||||
|
||||
Lx::List<Lx::Task> _present_list;
|
||||
Genode::Lock _present_list_mutex;
|
||||
|
||||
Task *_current = nullptr; /* currently scheduled task */
|
||||
|
||||
bool _run_task(Task *);
|
||||
|
||||
public:
|
||||
|
||||
Scheduler();
|
||||
~Scheduler();
|
||||
|
||||
/**
|
||||
* Return currently scheduled task
|
||||
*/
|
||||
Task *current();
|
||||
|
||||
/**
|
||||
* Add new task to the present list
|
||||
*/
|
||||
void add(Task *);
|
||||
|
||||
/**
|
||||
* Schedule all present tasks
|
||||
*
|
||||
* Returns if no task is runnable.
|
||||
*/
|
||||
void schedule();
|
||||
|
||||
/**
|
||||
* Log current state of tasks in present list (debug)
|
||||
*
|
||||
* Log lines are prefixed with 'prefix'
|
||||
*/
|
||||
void log_state(char const *prefix);
|
||||
};
|
||||
|
||||
#endif /* _SCHEDULER_H_ */
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* \brief Platform specific types
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _X86_32__TYPES_H_
|
||||
#define _X86_32__TYPES_H_
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif /* _X86_32__TYPES_H_ */
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* \brief Platform specific types
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _X86_64__TYPES_H_
|
||||
#define _X86_64__TYPES_H_
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif /* _X86_64__TYPES_H_ */
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -19,9 +19,12 @@
|
||||
#include <firmware_list.h>
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <lx_kit/irq.h>
|
||||
#include <lx_kit/work.h>
|
||||
#include <lx_kit/timer.h>
|
||||
|
||||
|
||||
extern "C" void core_netlink_proto_init(void);
|
||||
extern "C" void core_sock_init(void);
|
||||
@ -39,6 +42,9 @@ extern "C" void module_arc4_init(void);
|
||||
extern "C" void module_chainiv_module_init(void);
|
||||
extern "C" void module_krng_mod_init(void);
|
||||
|
||||
struct workqueue_struct *system_power_efficient_wq;
|
||||
struct workqueue_struct *system_wq;
|
||||
|
||||
static bool mac80211_only = false;
|
||||
|
||||
struct pernet_operations loopback_net_ops;
|
||||
@ -48,40 +54,41 @@ LIST_HEAD(net_namespace_list);
|
||||
|
||||
|
||||
Firmware_list fw_list[] = {
|
||||
{ "iwlwifi-1000-3.ucode", 335056 },
|
||||
{ "iwlwifi-1000-5.ucode", 337520 },
|
||||
{ "iwlwifi-105-6.ucode", 689680 },
|
||||
{ "iwlwifi-135-6.ucode", 701228 },
|
||||
{ "iwlwifi-2000-6.ucode", 695876 },
|
||||
{ "iwlwifi-2030-6.ucode", 707392 },
|
||||
{ "iwlwifi-3160-7.ucode", 670484 },
|
||||
{ "iwlwifi-3160-8.ucode", 667284 },
|
||||
{ "iwlwifi-3160-9.ucode", 666792 },
|
||||
{ "iwlwifi-3945-2.ucode", 150100 },
|
||||
{ "iwlwifi-4965-2.ucode", 187972 },
|
||||
{ "iwlwifi-5000-1.ucode", 345008 },
|
||||
{ "iwlwifi-5000-2.ucode", 353240 },
|
||||
{ "iwlwifi-5000-5.ucode", 340696 },
|
||||
{ "iwlwifi-5150-2.ucode", 337400 },
|
||||
{ "iwlwifi-6000-4.ucode", 454608 },
|
||||
{ "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. Our fw loading mechanism sadly will not work in this
|
||||
* case, therefore we add -6 to the fw whitelist have to provide
|
||||
* a renamed image.
|
||||
* this one. To make things simple we refer to the available
|
||||
* firmware under the requested name.
|
||||
*/
|
||||
{ "iwlwifi-6000-6.ucode", 454608 }, /* XXX same as -4 */
|
||||
{ "iwlwifi-6000g2a-5.ucode", 444128 },
|
||||
{ "iwlwifi-6000g2a-6.ucode", 677296 },
|
||||
{ "iwlwifi-6000g2b-5.ucode", 460236 },
|
||||
{ "iwlwifi-6000g2b-6.ucode", 679436 },
|
||||
{ "iwlwifi-6050-4.ucode", 463692 },
|
||||
{ "iwlwifi-6050-5.ucode", 469780 },
|
||||
{ "iwlwifi-7260-7.ucode", 683236 },
|
||||
{ "iwlwifi-7260-8.ucode", 679780 },
|
||||
{ "iwlwifi-7260-9.ucode", 679380 },
|
||||
{ "iwlwifi-7265-8.ucode", 690452 }
|
||||
{ "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-8000C-16.ucode", 2351636, nullptr },
|
||||
{ "iwlwifi-8000C-19.ucode", 2351636, "iwlwifi-8000C-16.ucode" }
|
||||
};
|
||||
|
||||
|
||||
@ -93,6 +100,9 @@ static Genode::Lock *_wpa_lock;
|
||||
|
||||
static void run_linux(void *)
|
||||
{
|
||||
system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0);
|
||||
system_wq = alloc_workqueue("system_wq", 0, 0);
|
||||
|
||||
core_sock_init();
|
||||
core_netlink_proto_init();
|
||||
module_packet_init();
|
||||
@ -107,7 +117,7 @@ static void run_linux(void *)
|
||||
module_aes_init();
|
||||
module_arc4_init();
|
||||
module_chainiv_module_init();
|
||||
module_krng_mod_init();
|
||||
// module_krng_mod_init();
|
||||
|
||||
if (!mac80211_only) {
|
||||
module_iwl_drv_init();
|
||||
@ -120,6 +130,8 @@ static void run_linux(void *)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long jiffies;
|
||||
|
||||
|
||||
void wifi_init(Server::Entrypoint &ep, Genode::Lock &lock)
|
||||
{
|
||||
@ -138,9 +150,13 @@ void wifi_init(Server::Entrypoint &ep, Genode::Lock &lock)
|
||||
/* add init_net namespace to namespace list */
|
||||
list_add_tail_rcu(&init_net.list, &net_namespace_list);
|
||||
|
||||
Lx::timer_init(ep);
|
||||
Lx::irq_init(ep);
|
||||
Lx::work_init(ep);
|
||||
Lx::scheduler();
|
||||
|
||||
Lx::timer(&ep, &jiffies);
|
||||
|
||||
Lx::Irq::irq(&ep, Genode::env()->heap());
|
||||
Lx::Work::work_queue(Genode::env()->heap());
|
||||
|
||||
Lx::socket_init(ep);
|
||||
Lx::nic_init(ep);
|
||||
|
||||
|
@ -1,290 +0,0 @@
|
||||
/*
|
||||
* \brief Signal context for IRQ's
|
||||
* \author Josef Soentgen
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-10-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/tslab.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <platform_device/client.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Helper utilty for composing IRQ related names
|
||||
*/
|
||||
struct Name_composer
|
||||
{
|
||||
char name[16];
|
||||
Name_composer(unsigned irq) {
|
||||
Genode::snprintf(name, sizeof(name), "irq_%02x", irq); }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Task for interrupts
|
||||
*
|
||||
* Allows flagging of IRQs from other threads.
|
||||
*/
|
||||
struct Irq_task
|
||||
{
|
||||
private:
|
||||
|
||||
Lx::Task _task;
|
||||
|
||||
public:
|
||||
|
||||
Irq_task(void (*func)(void *), void *args, char const *name)
|
||||
: _task(func, args, name, Lx::Task::PRIORITY_3, Lx::scheduler()) { }
|
||||
|
||||
void unblock() { _task.unblock(); }
|
||||
|
||||
char const *name() { return _task.name(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This contains the Linux-driver handlers
|
||||
*/
|
||||
struct Lx_irq_handler : public Lx::List<Lx_irq_handler>::Element
|
||||
{
|
||||
void *dev; /* Linux device */
|
||||
irq_handler_t handler; /* Linux handler */
|
||||
irq_handler_t thread_fn; /* Linux thread function */
|
||||
|
||||
Lx_irq_handler(void *dev, irq_handler_t handler, irq_handler_t thread_fn)
|
||||
: dev(dev), handler(handler), thread_fn(thread_fn) { }
|
||||
};
|
||||
|
||||
|
||||
namespace Lx {
|
||||
class Irq;
|
||||
}
|
||||
|
||||
static void run_irq(void *args);
|
||||
|
||||
extern "C" Platform::Device_capability pci_device_cap;
|
||||
|
||||
/**
|
||||
* Lx::Irq
|
||||
*/
|
||||
class Lx::Irq
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Context encapsulates the handling of an IRQ
|
||||
*/
|
||||
class Context : public Lx::List<Context>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Name_composer _name;
|
||||
|
||||
unsigned int _irq; /* IRQ number */
|
||||
Genode::Irq_session_client _irq_sess;
|
||||
Lx::List<Lx_irq_handler> _handler; /* List of registered handlers */
|
||||
Irq_task _task;
|
||||
|
||||
Genode::Signal_transmitter _sender;
|
||||
Genode::Signal_rpc_member<Context> _dispatcher;
|
||||
|
||||
/**
|
||||
* Call one IRQ handler
|
||||
*/
|
||||
bool _handle_one(Lx_irq_handler *h)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
/* XXX the handler as well as the thread_fn are called in a synchronouse fashion */
|
||||
switch (h->handler(_irq, h->dev)) {
|
||||
case IRQ_WAKE_THREAD:
|
||||
{
|
||||
h->thread_fn(_irq, h->dev);
|
||||
}
|
||||
case IRQ_HANDLED:
|
||||
handled = true;
|
||||
break;
|
||||
case IRQ_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal handler
|
||||
*/
|
||||
void _handle(unsigned)
|
||||
{
|
||||
_task.unblock();
|
||||
|
||||
/* kick off scheduling */
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Context(Server::Entrypoint &ep, unsigned irq,
|
||||
Platform::Device_capability pci_dev)
|
||||
:
|
||||
_name(irq),
|
||||
_irq(irq),
|
||||
_irq_sess(Platform::Device_client(pci_dev).irq(0)),
|
||||
_task(run_irq, this, _name.name),
|
||||
_dispatcher(ep, *this, &Context::_handle)
|
||||
{
|
||||
_irq_sess.sigh(_dispatcher);
|
||||
|
||||
/* initial ack to receive further IRQ signals */
|
||||
_irq_sess.ack_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return IRQ number
|
||||
*/
|
||||
unsigned irq() { return _irq; }
|
||||
|
||||
/**
|
||||
* Handle IRQ
|
||||
*/
|
||||
void handle_irq()
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
/* report IRQ to all clients */
|
||||
for (Lx_irq_handler *h = _handler.first(); h; h = h->next()) {
|
||||
if ((handled = _handle_one(h)))
|
||||
break;
|
||||
}
|
||||
|
||||
_irq_sess.ack_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add linux handler to context
|
||||
*/
|
||||
void add_handler(Lx_irq_handler *h) { _handler.append(h); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Server::Entrypoint &_ep;
|
||||
Lx::List<Context> _list;
|
||||
|
||||
Genode::Tslab<Context,
|
||||
3 * sizeof(Context)> _context_alloc;
|
||||
Genode::Tslab<Lx_irq_handler,
|
||||
3 * sizeof(Lx_irq_handler)> _handler_alloc;
|
||||
|
||||
/**
|
||||
* Find context for given IRQ number
|
||||
*/
|
||||
Context *_find_context(unsigned int irq)
|
||||
{
|
||||
for (Context *i = _list.first(); i; i = i->next())
|
||||
if (i->irq() == irq)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Irq(Server::Entrypoint &ep)
|
||||
:
|
||||
_ep(ep),
|
||||
_context_alloc(Genode::env()->heap()),
|
||||
_handler_alloc(Genode::env()->heap())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Request an IRQ
|
||||
*/
|
||||
void request_irq(unsigned int irq, irq_handler_t handler, void *dev,
|
||||
irq_handler_t thread_fn = 0)
|
||||
{
|
||||
Context *ctx = _find_context(irq);
|
||||
|
||||
/* if this IRQ is not registered */
|
||||
if (!ctx)
|
||||
ctx = new (&_context_alloc) Context(_ep, irq, pci_device_cap);
|
||||
|
||||
/* register Linux handler */
|
||||
Lx_irq_handler *h = new (&_handler_alloc)
|
||||
Lx_irq_handler(dev, handler, thread_fn);
|
||||
ctx->add_handler(h);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Lx::Irq *_lx_irq;
|
||||
|
||||
|
||||
void Lx::irq_init(Server::Entrypoint &ep)
|
||||
{
|
||||
static Lx::Irq irq_context(ep);
|
||||
_lx_irq = &irq_context;
|
||||
}
|
||||
|
||||
|
||||
static void run_irq(void *args)
|
||||
{
|
||||
Lx::Irq::Context *ctx = static_cast<Lx::Irq::Context*>(args);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
ctx->handle_irq();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
/***********************
|
||||
** linux/interrupt.h **
|
||||
***********************/
|
||||
|
||||
int request_irq(unsigned int irq, irq_handler_t handler,
|
||||
unsigned long flags, const char *name, void *dev)
|
||||
{
|
||||
_lx_irq->request_irq(irq, handler, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
|
||||
irq_handler_t thread_fn,
|
||||
unsigned long flags, const char *name,
|
||||
void *dev)
|
||||
{
|
||||
_lx_irq->request_irq(irq, handler, dev, thread_fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
@ -18,47 +18,23 @@
|
||||
#include <os/server.h>
|
||||
|
||||
/* local includes */
|
||||
#include <scheduler.h>
|
||||
#include <lx_kit/scheduler.h>
|
||||
|
||||
|
||||
#define DEBUG_COMPLETION 0
|
||||
#define DEBUG_DMA 0
|
||||
#define DEBUG_DRIVER 0
|
||||
#define DEBUG_IRQ 0
|
||||
#define DEBUG_KREF 0
|
||||
#define DEBUG_PRINTK 1
|
||||
#define DEBUG_DEV_DBG 1
|
||||
#define DEBUG_PCI 0
|
||||
#define DEBUG_SKB 0
|
||||
#define DEBUG_SLAB 0
|
||||
#define DEBUG_TIMER 0
|
||||
#define DEBUG_THREAD 0
|
||||
#define DEBUG_TRACE 0
|
||||
#define DEBUG_MUTEX 0
|
||||
#define DEBUG_SCHEDULING 0
|
||||
#define DEBUG_WORK 0
|
||||
|
||||
|
||||
namespace Lx
|
||||
{
|
||||
void timer_init(Server::Entrypoint &);
|
||||
void timer_update_jiffies();
|
||||
|
||||
void work_init(Server::Entrypoint &);
|
||||
|
||||
void socket_init(Server::Entrypoint &);
|
||||
|
||||
void nic_init(Server::Entrypoint &);
|
||||
|
||||
void irq_init(Server::Entrypoint &);
|
||||
|
||||
Genode::Ram_dataspace_capability backend_alloc(Genode::addr_t, Genode::Cache_attribute);
|
||||
void backend_free(Genode::Ram_dataspace_capability);
|
||||
|
||||
void printf(char const *fmt, ...);
|
||||
void debug_printf(int level, char const *fmt, ...);
|
||||
|
||||
|
||||
void get_mac_address(unsigned char *);
|
||||
}
|
||||
|
||||
|
40
repos/dde_linux/src/lib/wifi/lxc.h
Normal file
40
repos/dde_linux/src/lib/wifi/lxc.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Lx C env
|
||||
* \author Josef Soentgen
|
||||
* \date 2016-03-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which 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_ */
|
@ -5,15 +5,79 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* linux includes */
|
||||
#include <asm-generic/atomic64.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lxc.h>
|
||||
|
||||
|
||||
/*************************************
|
||||
** private Lx C env implementation **
|
||||
*************************************/
|
||||
|
||||
bool is_eapol(struct sk_buff *skb)
|
||||
{
|
||||
return ntohs(skb->protocol) == ETH_P_PAE;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
extern int verbose_alloc;
|
||||
|
||||
|
||||
struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom)
|
||||
{
|
||||
struct sk_buff *skb = alloc_skb(len + headroom, GFP_KERNEL);
|
||||
skb_reserve(skb, headroom);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len)
|
||||
{
|
||||
return skb_put(skb, len);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
@ -60,6 +124,24 @@ unsigned int hweight32(unsigned int w)
|
||||
}
|
||||
|
||||
|
||||
unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
if (size) {
|
||||
unsigned long val = BITMAP_LAST_WORD_MASK(size);
|
||||
unsigned long idx = (size-1) / BITS_PER_LONG;
|
||||
|
||||
do {
|
||||
val &= addr[idx];
|
||||
if (val)
|
||||
return idx * BITS_PER_LONG + __fls(val);
|
||||
|
||||
val = ~0ul;
|
||||
} while (idx--);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
** linux/platform_device.h **
|
||||
*****************************/
|
||||
@ -126,3 +208,182 @@ pdev_out:
|
||||
void netdev_run_todo() {
|
||||
__rtnl_unlock();
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** linux/kernel.h **
|
||||
********************/
|
||||
|
||||
unsigned long int_sqrt(unsigned long x)
|
||||
{
|
||||
unsigned long b, m, y = 0;
|
||||
|
||||
if (x <= 1) return x;
|
||||
|
||||
m = 1UL << (BITS_PER_LONG - 2);
|
||||
while (m != 0) {
|
||||
b = y + m;
|
||||
y >>= 1;
|
||||
|
||||
if (x >= b) {
|
||||
x -= b;
|
||||
y += m;
|
||||
}
|
||||
m >>= 2;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** linux/scatterlist.h **
|
||||
*************************/
|
||||
|
||||
void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
|
||||
struct scatterlist *sgl)
|
||||
{
|
||||
prv[prv_nents - 1].offset = 0;
|
||||
prv[prv_nents - 1].length = 0;
|
||||
prv[prv_nents - 1].page_link = (unsigned long)sgl;
|
||||
|
||||
prv[prv_nents - 1].page_flags |= 0x01;
|
||||
prv[prv_nents - 1].page_flags &= ~0x02;
|
||||
}
|
||||
|
||||
|
||||
void sg_init_table(struct scatterlist *sgl, unsigned int nents)
|
||||
{
|
||||
memset(sgl, 0, sizeof(*sgl) * nents);
|
||||
sg_mark_end(&sgl[nents -1]);
|
||||
}
|
||||
|
||||
|
||||
void sg_mark_end(struct scatterlist *sg)
|
||||
{
|
||||
sg->page_flags |= 0x02;
|
||||
sg->page_flags &= ~0x01;
|
||||
}
|
||||
|
||||
|
||||
struct scatterlist *sg_next(struct scatterlist *sg)
|
||||
{
|
||||
if (sg_is_last(sg))
|
||||
return NULL;
|
||||
|
||||
sg++;
|
||||
|
||||
if (sg_is_chain(sg))
|
||||
sg = sg_chain_ptr(sg);
|
||||
|
||||
return sg;
|
||||
}
|
||||
|
||||
|
||||
void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen)
|
||||
{
|
||||
struct page *page = &sg->page_dummy;
|
||||
sg->page_dummy.addr = (void*)buf;
|
||||
sg_set_page(sg, page, buflen, 0);
|
||||
}
|
||||
|
||||
|
||||
void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset)
|
||||
{
|
||||
sg->page_link = (unsigned long) page;
|
||||
sg->offset = offset;
|
||||
sg->length = len;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** net/sock.h **
|
||||
****************/
|
||||
|
||||
static const struct net_proto_family *net_families[NPROTO];
|
||||
|
||||
int sock_register(const struct net_proto_family *ops)
|
||||
{
|
||||
if (ops->family >= NPROTO) {
|
||||
printk("protocol %d >= NPROTO (%d)\n", ops->family, NPROTO);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_families[ops->family] = ops;
|
||||
pr_info("NET: Registered protocol family %d\n", ops->family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct socket *sock_alloc(void)
|
||||
{
|
||||
return (struct socket *)kmalloc(sizeof(struct socket), 0);
|
||||
}
|
||||
|
||||
|
||||
int sock_create_lite(int family, int type, int protocol, struct socket **res)
|
||||
|
||||
{
|
||||
struct socket *sock = sock_alloc();
|
||||
|
||||
if (!sock) return -ENOMEM;
|
||||
|
||||
sock->type = type;
|
||||
*res = sock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sock_create_kern(struct net *net, int family, int type, int proto,
|
||||
struct socket **res)
|
||||
{
|
||||
struct socket *sock;
|
||||
const struct net_proto_family *pf;
|
||||
int err;
|
||||
|
||||
if (family < 0 || family > NPROTO)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (type < 0 || type > SOCK_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
pf = net_families[family];
|
||||
|
||||
if (!pf) {
|
||||
printk("No protocol found for family %d\n", family);
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
if (!(sock = (struct socket *)kzalloc(sizeof(struct socket), 0))) {
|
||||
printk("Could not allocate socket\n");
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
sock->type = type;
|
||||
|
||||
err = pf->create(&init_net, sock, proto, 1);
|
||||
if (err) {
|
||||
kfree(sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
*res = sock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void log_sock(struct socket *socket)
|
||||
{
|
||||
printk("\nNEW socket %p sk %p fsk %lx &sk %p &fsk %p\n\n",
|
||||
socket, socket->sk, socket->flags, &socket->sk, &socket->flags);
|
||||
}
|
||||
|
||||
|
||||
static void sock_init(void)
|
||||
{
|
||||
skb_init();
|
||||
}
|
||||
|
||||
|
||||
core_initcall(sock_init);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -24,11 +24,13 @@
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
#include <lx_emul.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
# include <linux/skbuff.h>
|
||||
# include <net/cfg80211.h>
|
||||
# include <lxc.h>
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
extern bool config_verbose;
|
||||
|
||||
@ -36,6 +38,7 @@ enum {
|
||||
HEAD_ROOM = 128, /* XXX guessed value but works */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Nic::Session implementation
|
||||
*/
|
||||
@ -64,14 +67,9 @@ class Wifi_session_component : public Nic::Session_component
|
||||
return true;
|
||||
}
|
||||
|
||||
struct sk_buff *skb = ::alloc_skb(packet.size() + HEAD_ROOM, GFP_KERNEL);
|
||||
if (skb == nullptr) {
|
||||
PERR("Could not allocate new sk_buff");
|
||||
return false;
|
||||
}
|
||||
skb_reserve(skb, HEAD_ROOM);
|
||||
struct sk_buff *skb = lxc_alloc_skb(packet.size() + HEAD_ROOM, HEAD_ROOM);
|
||||
|
||||
unsigned char *data = skb_put(skb, packet.size());
|
||||
unsigned char *data = lxc_skb_put(skb, packet.size());
|
||||
Genode::memcpy(data, _tx.sink()->packet_content(packet), packet.size());
|
||||
|
||||
_ndev->netdev_ops->ndo_start_xmit(skb, _ndev);
|
||||
@ -123,44 +121,24 @@ class Wifi_session_component : public Nic::Session_component
|
||||
{
|
||||
_handle_packet_stream();
|
||||
|
||||
if (!_rx.source()->ready_to_submit())
|
||||
if (!_rx.source()->ready_to_submit()) {
|
||||
PWRN("Not ready to receive packet");
|
||||
return;
|
||||
|
||||
/* get mac header back */
|
||||
skb_push(skb, ETH_HLEN);
|
||||
|
||||
void *packet = skb->data;
|
||||
size_t packet_size = ETH_HLEN;
|
||||
void *frag = 0;
|
||||
size_t 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)
|
||||
PERR("more than 1 fragment in skb");
|
||||
|
||||
skb_frag_t *f = &skb_shinfo(skb)->frags[0];
|
||||
frag = skb_frag_address(f);
|
||||
frag_size = skb_frag_size(f);
|
||||
}
|
||||
else
|
||||
packet_size += skb->len;
|
||||
|
||||
Skb s = skb_helper(skb);
|
||||
|
||||
try {
|
||||
Nic::Packet_descriptor p = _rx.source()->alloc_packet(packet_size + frag_size);
|
||||
Nic::Packet_descriptor p = _rx.source()->alloc_packet(s.packet_size + s.frag_size);
|
||||
void *buffer = _rx.source()->packet_content(p);
|
||||
memcpy(buffer, packet, packet_size);
|
||||
if (frag_size)
|
||||
memcpy((char *)buffer + packet_size, frag, frag_size);
|
||||
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 (...) {
|
||||
PDBG("failed to process received packet");
|
||||
PWRN("failed to process received packet");
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +248,7 @@ class Lx::Notifier
|
||||
Block(struct notifier_block *nb) : nb(nb) { }
|
||||
};
|
||||
|
||||
Lx::List<Block> _list;
|
||||
Lx_kit::List<Block> _list;
|
||||
Genode::Tslab<Block, 32 * sizeof(Block)> _block_alloc;
|
||||
|
||||
public:
|
||||
@ -379,7 +357,7 @@ extern "C" struct net_device * netdev_notifier_info_to_dev(struct netdev_notifie
|
||||
}
|
||||
|
||||
|
||||
struct Proto_hook : public Lx::List<Proto_hook>::Element
|
||||
struct Proto_hook : public Lx_kit::List<Proto_hook>::Element
|
||||
{
|
||||
struct packet_type &pt;
|
||||
|
||||
@ -391,7 +369,7 @@ class Proto_hook_list
|
||||
{
|
||||
private:
|
||||
|
||||
Lx::List<Proto_hook> _list;
|
||||
Lx_kit::List<Proto_hook> _list;
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
public:
|
||||
@ -445,6 +423,12 @@ extern "C" struct net_device *__dev_get_by_index(struct net *net, int ifindex)
|
||||
}
|
||||
|
||||
|
||||
extern "C" struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex)
|
||||
{
|
||||
return __dev_get_by_index(net, ifindex);
|
||||
}
|
||||
|
||||
|
||||
extern "C" struct net_device *dev_get_by_index(struct net *net, int ifindex)
|
||||
{
|
||||
return __dev_get_by_index(net, ifindex);
|
||||
@ -589,7 +573,7 @@ extern "C" int netif_receive_skb(struct sk_buff *skb)
|
||||
*/
|
||||
|
||||
/* send EAPOL related frames only to the wpa_supplicant */
|
||||
if (ntohs(skb->protocol) == ETH_P_PAE) {
|
||||
if (is_eapol(skb)) {
|
||||
/* XXX call only AF_PACKET hook */
|
||||
for (Proto_hook* ph = proto_hook_list().first(); ph; ph = ph->next()) {
|
||||
ph->pt.func(skb, Root::instance->device, &ph->pt, Root::instance->device);
|
||||
@ -605,6 +589,30 @@ extern "C" int netif_receive_skb(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
|
||||
gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
|
||||
{
|
||||
return netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void netif_start_subqueue(struct net_device *dev, u16 queue_index)
|
||||
{
|
||||
dev->_tx[queue_index].state = NETDEV_QUEUE_START;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
|
||||
{
|
||||
dev->_tx[queue_index].state = 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
|
||||
{
|
||||
dev->_tx[queue_index].state = NETDEV_QUEUE_START;
|
||||
}
|
||||
|
||||
|
||||
extern "C" u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
|
||||
{
|
||||
if (queue_index > dev-> real_num_tx_queues) {
|
||||
@ -618,6 +626,7 @@ extern "C" u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
|
||||
|
||||
|
||||
extern "C" 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)
|
||||
{
|
||||
|
@ -1,489 +0,0 @@
|
||||
/*
|
||||
* \brief Emulate 'pci_dev' structure
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-04-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode inludes */
|
||||
#include <ram_session/client.h>
|
||||
#include <util/retry.h>
|
||||
#include <base/object_pool.h>
|
||||
#include <platform_session/connection.h>
|
||||
#include <platform_device/client.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
static bool const verbose = false;
|
||||
#define PDBGV(...) do { if (verbose) PDBG(__VA_ARGS__); } while (0)
|
||||
|
||||
|
||||
struct bus_type pci_bus_type;
|
||||
|
||||
|
||||
/**
|
||||
* Scan PCI bus and probe for HCDs
|
||||
*/
|
||||
class Pci_driver
|
||||
{
|
||||
private:
|
||||
|
||||
pci_driver *_drv; /* Linux PCI driver */
|
||||
Platform::Device_capability _cap; /* PCI cap */
|
||||
pci_device_id const *_id; /* matched id for this driver */
|
||||
|
||||
public:
|
||||
|
||||
pci_dev *_dev; /* Linux PCI device */
|
||||
|
||||
private:
|
||||
|
||||
/* offset used in PCI config space */
|
||||
enum Pci_config { IRQ = 0x3c, REV = 0x8, CMD = 0x4,
|
||||
STATUS = 0x4, CAP = 0x34 };
|
||||
enum Pci_cap { CAP_LIST = 0x10, CAP_EXP = 0x10,
|
||||
CAP_EXP_FLAGS = 0x2, CAP_EXP_DEVCAP = 0x4 };
|
||||
|
||||
/**
|
||||
* Fill Linux device informations
|
||||
*/
|
||||
bool _setup_pci_device()
|
||||
{
|
||||
using namespace Platform;
|
||||
|
||||
Device_client client(_cap);
|
||||
if (client.device_id() != _id->device)
|
||||
return false;
|
||||
|
||||
_dev = new (Genode::env()->heap()) pci_dev;
|
||||
|
||||
_dev->vendor = client.vendor_id();
|
||||
_dev->device = client.device_id();
|
||||
_dev->class_ = client.class_code();
|
||||
_dev->revision = client.config_read(REV, Device::ACCESS_8BIT);
|
||||
_dev->dev.driver = &_drv->driver;
|
||||
|
||||
/* dummy dma mask used to mark device as DMA capable */
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
_dev->dev.dma_mask = &dma_mask;
|
||||
_dev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
/* read interrupt line */
|
||||
_dev->irq = client.config_read(IRQ, Device::ACCESS_8BIT);
|
||||
|
||||
/* hide ourselfs in bus structure */
|
||||
_dev->bus = (struct pci_bus *)this;
|
||||
|
||||
/* setup resources */
|
||||
bool io = false;
|
||||
for (int i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||
Device::Resource res = client.resource(i);
|
||||
if (res.type() == Device::Resource::INVALID)
|
||||
continue;
|
||||
|
||||
_dev->resource[i].start = res.base();
|
||||
_dev->resource[i].end = res.base() + res.size() - 1;
|
||||
_dev->resource[i].flags = res.type() == Device::Resource::IO
|
||||
? IORESOURCE_IO : 0;
|
||||
|
||||
PDBGV("base: %x size: %x type: %u",
|
||||
res.base(), res.size(), res.type());
|
||||
|
||||
/* request I/O memory (write combined) */
|
||||
if (res.type() == Device::Resource::MEMORY)
|
||||
PDBGV("I/O memory [%x-%x)", res.base(),
|
||||
res.base() + res.size());
|
||||
}
|
||||
|
||||
/* enable bus master and io bits */
|
||||
uint16_t cmd = client.config_read(CMD, Device::ACCESS_16BIT);
|
||||
cmd |= io ? 0x1 : 0;
|
||||
|
||||
/* enable bus master */
|
||||
cmd |= 0x4;
|
||||
client.config_write(CMD, cmd, Device::ACCESS_16BIT);
|
||||
|
||||
/* get pci express capability */
|
||||
_dev->pcie_cap = 0;
|
||||
uint16_t status = client.config_read(STATUS, Device::ACCESS_32BIT) >> 16;
|
||||
if (status & CAP_LIST) {
|
||||
uint8_t offset = client.config_read(CAP, Device::ACCESS_8BIT);
|
||||
while (offset != 0x00) {
|
||||
uint8_t value = client.config_read(offset, Device::ACCESS_8BIT);
|
||||
|
||||
if (value == CAP_EXP)
|
||||
_dev->pcie_cap = offset;
|
||||
|
||||
offset = client.config_read(offset + 1, Device::ACCESS_8BIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (_dev->pcie_cap) {
|
||||
uint16_t reg_val = client.config_read(_dev->pcie_cap, Device::ACCESS_16BIT);
|
||||
_dev->pcie_flags_reg = reg_val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe device with driver
|
||||
*/
|
||||
bool _probe()
|
||||
{
|
||||
|
||||
/* only probe if the device matches */
|
||||
if (!_setup_pci_device())
|
||||
return false;
|
||||
|
||||
/* PDBG("probe: %p 0x%x", _dev, _id); */
|
||||
|
||||
if (!_drv->probe(_dev, _id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Platform::Device::Access_size _access_size(T t)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1:
|
||||
return Platform::Device::ACCESS_8BIT;
|
||||
case 2:
|
||||
return Platform::Device::ACCESS_16BIT;
|
||||
default:
|
||||
return Platform::Device::ACCESS_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Pci_driver(pci_driver *drv, Platform::Device_capability cap,
|
||||
pci_device_id const * id)
|
||||
: _drv(drv), _cap(cap), _id(id), _dev(0)
|
||||
{
|
||||
if (!_probe())
|
||||
throw -1;
|
||||
}
|
||||
|
||||
~Pci_driver()
|
||||
{
|
||||
if (!_dev)
|
||||
return;
|
||||
|
||||
destroy(Genode::env()->heap(), _dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read/write data from/to config space
|
||||
*/
|
||||
template <typename T>
|
||||
void config_read(unsigned int devfn, T *val)
|
||||
{
|
||||
Platform::Device_client client(_cap);
|
||||
*val = client.config_read(devfn, _access_size(*val));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void config_write(unsigned int devfn, T val)
|
||||
{
|
||||
Platform::Device_client client(_cap);
|
||||
client.config_write(devfn, val, _access_size(val));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/********************************
|
||||
** Backend memory definitions **
|
||||
********************************/
|
||||
|
||||
struct Memory_object_base : Genode::Object_pool<Memory_object_base>::Entry
|
||||
{
|
||||
Memory_object_base(Genode::Ram_dataspace_capability cap)
|
||||
: Genode::Object_pool<Memory_object_base>::Entry(cap) {}
|
||||
virtual ~Memory_object_base() {};
|
||||
|
||||
virtual void free() = 0;
|
||||
|
||||
Genode::Ram_dataspace_capability ram_cap()
|
||||
{
|
||||
using namespace Genode;
|
||||
return reinterpret_cap_cast<Ram_dataspace>(cap());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Ram_object : Memory_object_base
|
||||
{
|
||||
Ram_object(Genode::Ram_dataspace_capability cap)
|
||||
: Memory_object_base(cap) {}
|
||||
|
||||
void free();
|
||||
};
|
||||
|
||||
|
||||
struct Dma_object : Memory_object_base
|
||||
{
|
||||
Dma_object(Genode::Ram_dataspace_capability cap)
|
||||
: Memory_object_base(cap) {}
|
||||
|
||||
void free();
|
||||
};
|
||||
|
||||
|
||||
/*********************
|
||||
** Linux interface **
|
||||
*********************/
|
||||
|
||||
extern "C" { Platform::Device_capability pci_device_cap; }
|
||||
static Platform::Connection *pci()
|
||||
{
|
||||
static Platform::Connection _pci;
|
||||
return &_pci;
|
||||
}
|
||||
static Genode::Object_pool<Memory_object_base> memory_pool;
|
||||
|
||||
|
||||
extern "C" int pci_register_driver(struct pci_driver *drv)
|
||||
{
|
||||
drv->driver.name = drv->name;
|
||||
|
||||
if (!drv->id_table) return -ENODEV;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum {
|
||||
PCI_CLASS_MASK = 0xfff000,
|
||||
/**
|
||||
* This is actually PCI_CLASS_NETWORK_OTHER and may only work
|
||||
* for the iwlwifi driver.
|
||||
*/
|
||||
PCI_CLASS_WIFI = 0x028000,
|
||||
};
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (Platform::Device_capability cap = pci()->first_device(PCI_CLASS_WIFI,
|
||||
PCI_CLASS_MASK);
|
||||
cap.valid() && !found;) {
|
||||
Pci_driver *pci_drv = nullptr;
|
||||
pci_device_cap = cap;
|
||||
|
||||
for (pci_device_id const *id = drv->id_table; id->device && !found; id++) {
|
||||
|
||||
if (id->class_ == (unsigned)PCI_ANY_ID) continue;
|
||||
|
||||
try {
|
||||
retry<Platform::Device::Quota_exceeded>(
|
||||
[&] {
|
||||
/* probe device */
|
||||
pci_drv = new (env()->heap()) Pci_driver(drv, cap, id);
|
||||
pci()->on_destruction(Platform::Connection::KEEP_OPEN);
|
||||
found = true;
|
||||
},
|
||||
[&] {
|
||||
Genode::env()->parent()->upgrade(pci()->cap(), "ram_quota=4096");
|
||||
});
|
||||
} catch (...) {
|
||||
destroy(env()->heap(), pci_drv);
|
||||
pci_drv = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Platform::Device_capability free_up = cap;
|
||||
cap = pci()->next_device(cap, PCI_CLASS_WIFI, PCI_CLASS_MASK);
|
||||
if (!pci_drv)
|
||||
pci()->release_device(free_up);
|
||||
}
|
||||
|
||||
if (!found) PERR("no usable wireless device found");
|
||||
|
||||
return found ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
extern "C" size_t pci_resource_start(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return 0;
|
||||
|
||||
return dev->resource[bar].start;
|
||||
}
|
||||
|
||||
|
||||
extern "C" size_t pci_resource_len(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
size_t start = pci_resource_start(dev, bar);
|
||||
|
||||
if (!start)
|
||||
return 0;
|
||||
|
||||
return (dev->resource[bar].end - start) + 1;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void *pci_ioremap_bar(struct pci_dev *dev, int bar)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (bar >= DEVICE_COUNT_RESOURCE || bar < 0)
|
||||
return 0;
|
||||
|
||||
size_t start = pci_resource_start(dev, bar);
|
||||
size_t size = pci_resource_len(dev, bar);
|
||||
|
||||
if (!start)
|
||||
return 0;
|
||||
|
||||
Io_mem_session_client *io_mem;
|
||||
try {
|
||||
Platform::Device_client device(pci_device_cap);
|
||||
io_mem = new (env()->heap()) Io_mem_session_client(device.io_mem(device.phys_bar_to_virt(bar)));
|
||||
} catch (...) {
|
||||
PERR("Failed to request I/O memory: [%zx,%zx)", start, start + size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!io_mem->dataspace().valid()) {
|
||||
PERR("I/O memory not accessible");
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_t map_addr = env()->rm_session()->attach(io_mem->dataspace());
|
||||
map_addr |= start & 0xfff;
|
||||
|
||||
return (void*)map_addr;
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return 0;
|
||||
|
||||
return dev->resource[bar].flags;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)bus;
|
||||
drv->config_read(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)bus;
|
||||
drv->config_read(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)bus;
|
||||
drv->config_write(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)bus;
|
||||
drv->config_write(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const char *pci_name(const struct pci_dev *pdev)
|
||||
{
|
||||
/* simply return driver name */
|
||||
return "dummy";
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pcie_capability_read_word(struct pci_dev *pdev, int pos, u16 *val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)pdev->bus;
|
||||
switch (pos) {
|
||||
case PCI_EXP_LNKCTL:
|
||||
drv->config_read(pdev->pcie_cap + PCI_EXP_LNKCTL, val);
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Ram_object::free() { Genode::env()->ram_session()->free(ram_cap()); }
|
||||
|
||||
|
||||
void Dma_object::free() { pci()->free_dma_buffer(ram_cap()); }
|
||||
|
||||
|
||||
Genode::Ram_dataspace_capability
|
||||
Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Memory_object_base *o;
|
||||
Genode::Ram_dataspace_capability cap;
|
||||
if (cached == CACHED) {
|
||||
cap = env()->ram_session()->alloc(size);
|
||||
o = new (env()->heap()) Ram_object(cap);
|
||||
} else {
|
||||
size_t donate = size;
|
||||
cap = Genode::retry<Platform::Session::Out_of_metadata>(
|
||||
[&] () { return pci()->alloc_dma_buffer(size); },
|
||||
[&] () {
|
||||
char quota[32];
|
||||
Genode::snprintf(quota, sizeof(quota), "ram_quota=%zd",
|
||||
donate);
|
||||
Genode::env()->parent()->upgrade(pci()->cap(), quota);
|
||||
donate = donate * 2 > size ? 4096 : donate * 2;
|
||||
});
|
||||
o = new (env()->heap()) Dma_object(cap);
|
||||
}
|
||||
|
||||
memory_pool.insert(o);
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
void Lx::backend_free(Genode::Ram_dataspace_capability cap)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Memory_object_base *object;
|
||||
auto lambda = [&] (Memory_object_base *o) {
|
||||
object = o;
|
||||
if (object) {
|
||||
object->free();
|
||||
memory_pool.remove(object);
|
||||
}
|
||||
};
|
||||
memory_pool.apply(cap, lambda);
|
||||
if (object) destroy(env()->heap(), object);
|
||||
}
|
@ -1,262 +0,0 @@
|
||||
/*
|
||||
* \brief User-level scheduling
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Christian Helmuth
|
||||
* \date 2012-04-25
|
||||
*
|
||||
* We use a pseudo-thread implementation based on setjmp/longjmp.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
#include <platform/platform.h>
|
||||
#include <scheduler.h>
|
||||
|
||||
|
||||
#define PDBGV(...) \
|
||||
do { if (DEBUG_SCHEDULING) PDBG(__VA_ARGS__); } while (0)
|
||||
|
||||
|
||||
/**********
|
||||
** Task **
|
||||
**********/
|
||||
|
||||
bool Lx::Task::_runnable() const
|
||||
{
|
||||
switch (_state) {
|
||||
case STATE_INIT: return true;
|
||||
case STATE_RUNNING: return true;
|
||||
case STATE_BLOCKED: return false;
|
||||
case STATE_MUTEX_BLOCKED: return false;
|
||||
case STATE_WAIT_BLOCKED: return false;
|
||||
}
|
||||
|
||||
PERR("state %d not handled by switch", _state);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
bool Lx::Task::run()
|
||||
{
|
||||
if (!_runnable())
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Save the execution environment. The scheduled task returns to this point
|
||||
* after execution, i.e., at the next preemption point.
|
||||
*/
|
||||
if (_setjmp(_saved_env))
|
||||
return true;
|
||||
|
||||
if (_state == STATE_INIT) {
|
||||
/* setup execution environment and call task's function */
|
||||
_state = STATE_RUNNING;
|
||||
Genode::Thread *th = Genode::Thread::myself();
|
||||
|
||||
enum { STACK_SIZE = 32 * 1024 }; /* FIXME make stack size configurable */
|
||||
_stack = th->alloc_secondary_stack(_name, STACK_SIZE);
|
||||
|
||||
/* switch stack and call '_func(_arg)' */
|
||||
platform_execute(_stack, (void *)_func, _arg);
|
||||
} else {
|
||||
/* restore execution environment */
|
||||
_longjmp(_env, 1);
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
PERR("Unexpected return of Task");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
void Lx::Task::schedule()
|
||||
{
|
||||
/*
|
||||
* Save the execution environment. The task will resume from here on next
|
||||
* schedule.
|
||||
*/
|
||||
if (_setjmp(_env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* return to thread calling run() */
|
||||
_longjmp(_saved_env, 1);
|
||||
}
|
||||
|
||||
|
||||
Lx::Task::Task(void (*func)(void*), void *arg, char const *name,
|
||||
Priority priority, Scheduler &scheduler)
|
||||
:
|
||||
_priority(priority), _scheduler(scheduler),
|
||||
_func(func), _arg(arg), _name(name)
|
||||
{
|
||||
scheduler.add(this);
|
||||
|
||||
PDBGV("name: '%s' func: %p arg: %p prio: %u t: %p", name, func, arg, priority, this);
|
||||
}
|
||||
|
||||
|
||||
Lx::Task::~Task()
|
||||
{
|
||||
// scheduler.remove(this);
|
||||
if (_stack)
|
||||
Genode::Thread::myself()->free_secondary_stack(_stack);
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Scheduler **
|
||||
***************/
|
||||
|
||||
Lx::Scheduler & Lx::scheduler()
|
||||
{
|
||||
static Lx::Scheduler inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
Lx::Task *Lx::Scheduler::current()
|
||||
{
|
||||
if (!_current) {
|
||||
PERR("BUG: _current is zero!");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
return _current;
|
||||
}
|
||||
|
||||
|
||||
void Lx::Scheduler::add(Task *task)
|
||||
{
|
||||
Lx::Task *p = _present_list.first();
|
||||
for ( ; p; p = p->next()) {
|
||||
if (p->priority() <= task->priority()) {
|
||||
_present_list.insert_before(task, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p)
|
||||
_present_list.append(task);
|
||||
}
|
||||
|
||||
|
||||
void Lx::Scheduler::schedule()
|
||||
{
|
||||
bool at_least_one = false;
|
||||
|
||||
/*
|
||||
* Iterate over all tasks and run first runnable.
|
||||
*
|
||||
* (1) If one runnable tasks was run start over from beginning of
|
||||
* list.
|
||||
*
|
||||
* (2) If no task is runnable quit scheduling (break endless
|
||||
* loop).
|
||||
*/
|
||||
while (true) {
|
||||
/* update jiffies before running task */
|
||||
Lx::timer_update_jiffies();
|
||||
|
||||
bool was_run = false;
|
||||
for (Task *t = _present_list.first(); t; t = t->next()) {
|
||||
/* update current before running task */
|
||||
_current = t;
|
||||
|
||||
if ((was_run = t->run())) {
|
||||
at_least_one = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!was_run)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!at_least_one) {
|
||||
PWRN("schedule() called without runnable tasks");
|
||||
log_state("SCHEDULE");
|
||||
}
|
||||
|
||||
/* clear current as no task is running */
|
||||
_current = nullptr;
|
||||
}
|
||||
|
||||
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
namespace {
|
||||
struct Logger : Genode::Thread_deprecated<0x4000>
|
||||
{
|
||||
Timer::Connection _timer;
|
||||
Lx::Scheduler &_scheduler;
|
||||
unsigned const _interval;
|
||||
|
||||
Logger(Lx::Scheduler &scheduler, unsigned interval_seconds)
|
||||
:
|
||||
Genode::Thread_deprecated<0x4000>("logger"),
|
||||
_scheduler(scheduler), _interval(interval_seconds)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
PWRN("Scheduler::Logger is up");
|
||||
_timer.msleep(1000 * _interval);
|
||||
while (true) {
|
||||
_scheduler.log_state("LOGGER");
|
||||
_timer.msleep(2000);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define ANSI_ESC_RESET "\033[00m"
|
||||
#define ANSI_ESC_BLACK "\033[30m"
|
||||
#define ANSI_ESC_RED "\033[31m"
|
||||
#define ANSI_ESC_YELLOW "\033[33m"
|
||||
|
||||
static char const *state_color(Lx::Task::State state)
|
||||
{
|
||||
switch (state) {
|
||||
case Lx::Task::STATE_INIT: return ANSI_ESC_RESET;
|
||||
case Lx::Task::STATE_RUNNING: return ANSI_ESC_RED;
|
||||
case Lx::Task::STATE_BLOCKED: return ANSI_ESC_YELLOW;
|
||||
case Lx::Task::STATE_MUTEX_BLOCKED: return ANSI_ESC_YELLOW;
|
||||
case Lx::Task::STATE_WAIT_BLOCKED: return ANSI_ESC_YELLOW;
|
||||
}
|
||||
|
||||
return ANSI_ESC_BLACK;
|
||||
}
|
||||
|
||||
|
||||
void Lx::Scheduler::log_state(char const *prefix)
|
||||
{
|
||||
unsigned i;
|
||||
Lx::Task *t;
|
||||
for (i = 0, t = _present_list.first(); t; t = t->next(), ++i) {
|
||||
Genode::printf("%s [%u] prio: %u state: %s%u" ANSI_ESC_RESET " %s\n",
|
||||
prefix, i, t->priority(), state_color(t->state()),
|
||||
t->state(), t->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Lx::Scheduler::Scheduler()
|
||||
{
|
||||
if (DEBUG_SCHEDULING)
|
||||
new (Genode::env()->heap()) Logger(*this, 10);
|
||||
}
|
||||
|
||||
|
||||
Lx::Scheduler::~Scheduler() { }
|
@ -1,110 +0,0 @@
|
||||
/**
|
||||
* \brief Linux emulation code
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2014-03-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
|
||||
/****************
|
||||
** net/sock.h **
|
||||
****************/
|
||||
|
||||
static const struct net_proto_family *net_families[NPROTO];
|
||||
|
||||
int sock_register(const struct net_proto_family *ops)
|
||||
{
|
||||
if (ops->family >= NPROTO) {
|
||||
printk("protocol %d >= NPROTO (%d)\n", ops->family, NPROTO);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_families[ops->family] = ops;
|
||||
pr_info("NET: Registered protocol family %d\n", ops->family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct socket *sock_alloc(void)
|
||||
{
|
||||
return (struct socket *)kmalloc(sizeof(struct socket), 0);
|
||||
}
|
||||
|
||||
|
||||
int sock_create_lite(int family, int type, int protocol, struct socket **res)
|
||||
|
||||
{
|
||||
struct socket *sock = sock_alloc();
|
||||
|
||||
if (!sock)
|
||||
return -ENOMEM;
|
||||
|
||||
sock->type = type;
|
||||
*res = sock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sock_create_kern(int family, int type, int proto,
|
||||
struct socket **res)
|
||||
{
|
||||
struct socket *sock;
|
||||
const struct net_proto_family *pf;
|
||||
int err;
|
||||
|
||||
if (family < 0 || family > NPROTO)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (type < 0 || type > SOCK_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
pf = net_families[family];
|
||||
|
||||
if (!pf) {
|
||||
printk("No protocol found for family %d\n", family);
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
if (!(sock = (struct socket *)kzalloc(sizeof(struct socket), 0))) {
|
||||
printk("Could not allocate socket\n");
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
sock->type = type;
|
||||
|
||||
err = pf->create(&init_net, sock, proto, 1);
|
||||
if (err) {
|
||||
kfree(sock);
|
||||
return err;
|
||||
}
|
||||
|
||||
*res = sock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void log_sock(struct socket *socket)
|
||||
{
|
||||
printk("\nNEW socket %p sk %p fsk %lx &sk %p &fsk %p\n\n",
|
||||
socket, socket->sk, socket->flags, &socket->sk, &socket->flags);
|
||||
}
|
||||
|
||||
|
||||
static void sock_init(void)
|
||||
{
|
||||
skb_init();
|
||||
}
|
||||
|
||||
|
||||
core_initcall(sock_init);
|
@ -5,24 +5,25 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
# include <linux/socket.h>
|
||||
# include <linux/net.h>
|
||||
# include <net/sock.h>
|
||||
#include <extern_c_end.h>
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
#include <wifi/socket_call.h>
|
||||
|
||||
@ -142,7 +143,7 @@ class Lx::Socket
|
||||
void _do_socket()
|
||||
{
|
||||
struct socket *s;
|
||||
int res = sock_create_kern(_call.socket.domain, _call.socket.type,
|
||||
int res = sock_create_kern(nullptr, _call.socket.domain, _call.socket.type,
|
||||
_call.socket.protocol, &s);
|
||||
if (!res) {
|
||||
_call.socket.result = s;
|
||||
@ -186,22 +187,14 @@ class Lx::Socket
|
||||
struct socket *sock = _call_socket();
|
||||
struct msghdr *msg = &_call.recvmsg.msg;
|
||||
|
||||
/* needed by AF_NETLINK */
|
||||
struct sock_iocb siocb;
|
||||
Genode::memset(&siocb, 0, sizeof(struct sock_iocb));
|
||||
struct kiocb kiocb;
|
||||
Genode::memset(&kiocb, 0, sizeof(struct kiocb));
|
||||
|
||||
kiocb.private_ = &siocb;
|
||||
|
||||
if (_call.handle->non_block)
|
||||
msg->msg_flags |= MSG_DONTWAIT;
|
||||
|
||||
size_t iovlen = 0;
|
||||
for (size_t i = 0; i < msg->msg_iovlen; i++)
|
||||
iovlen += msg->msg_iov[i].iov_len;
|
||||
for (size_t i = 0; i < msg->msg_iter.nr_segs; i++)
|
||||
iovlen += msg->msg_iter.iov[i].iov_len;
|
||||
|
||||
_call.err = sock->ops->recvmsg(&kiocb, sock, msg, iovlen, _call.recvmsg.flags);
|
||||
_call.err = sock->ops->recvmsg(sock, msg, iovlen, _call.recvmsg.flags);
|
||||
}
|
||||
|
||||
void _do_sendmsg()
|
||||
@ -209,22 +202,14 @@ class Lx::Socket
|
||||
struct socket *sock = _call_socket();
|
||||
struct msghdr *msg = const_cast<msghdr *>(&_call.sendmsg.msg);
|
||||
|
||||
/* needed by AF_NETLINK */
|
||||
struct sock_iocb siocb;
|
||||
Genode::memset(&siocb, 0, sizeof(struct sock_iocb));
|
||||
struct kiocb kiocb;
|
||||
Genode::memset(&kiocb, 0, sizeof(struct kiocb));
|
||||
|
||||
kiocb.private_ = &siocb;
|
||||
|
||||
if (_call.handle->non_block)
|
||||
msg->msg_flags |= MSG_DONTWAIT;
|
||||
|
||||
size_t iovlen = 0;
|
||||
for (size_t i = 0; i < msg->msg_iovlen; i++)
|
||||
iovlen += msg->msg_iov[i].iov_len;
|
||||
for (size_t i = 0; i < msg->msg_iter.nr_segs; i++)
|
||||
iovlen += msg->msg_iter.iov[i].iov_len;
|
||||
|
||||
_call.err = sock->ops->sendmsg(&kiocb, sock, msg, iovlen);
|
||||
_call.err = sock->ops->sendmsg(sock, msg, iovlen);
|
||||
}
|
||||
|
||||
void _do_setsockopt()
|
||||
@ -513,15 +498,16 @@ static int msg_flags(Wifi::Flags in)
|
||||
|
||||
Wifi::ssize_t Socket_call::recvmsg(Socket *s, Wifi::Msghdr *msg, Wifi::Flags flags)
|
||||
{
|
||||
_call.opcode = Call::RECVMSG;
|
||||
_call.handle = s;
|
||||
_call.recvmsg.msg.msg_name = msg->msg_name;
|
||||
_call.recvmsg.msg.msg_namelen = msg->msg_namelen;
|
||||
_call.recvmsg.msg.msg_iov = _call.recvmsg.iov;
|
||||
_call.recvmsg.msg.msg_iovlen = msg->msg_iovlen;
|
||||
_call.recvmsg.msg.msg_control = msg->msg_control;
|
||||
_call.recvmsg.msg.msg_controllen = msg->msg_controllen;
|
||||
_call.recvmsg.flags = msg_flags(flags);
|
||||
_call.opcode = Call::RECVMSG;
|
||||
_call.handle = s;
|
||||
_call.recvmsg.msg.msg_name = msg->msg_name;
|
||||
_call.recvmsg.msg.msg_namelen = msg->msg_namelen;
|
||||
_call.recvmsg.msg.msg_iter.iov = _call.recvmsg.iov;
|
||||
_call.recvmsg.msg.msg_iter.nr_segs = msg->msg_iovlen;
|
||||
_call.recvmsg.msg.msg_iter.count = msg->msg_count;
|
||||
_call.recvmsg.msg.msg_control = msg->msg_control;
|
||||
_call.recvmsg.msg.msg_controllen = msg->msg_controllen;
|
||||
_call.recvmsg.flags = msg_flags(flags);
|
||||
|
||||
for (unsigned i = 0; i < msg->msg_iovlen; ++i) {
|
||||
_call.recvmsg.iov[i].iov_base = msg->msg_iov[i].iov_base;
|
||||
@ -538,15 +524,16 @@ Wifi::ssize_t Socket_call::recvmsg(Socket *s, Wifi::Msghdr *msg, Wifi::Flags fla
|
||||
|
||||
Wifi::ssize_t Socket_call::sendmsg(Socket *s, Wifi::Msghdr const *msg, Wifi::Flags flags)
|
||||
{
|
||||
_call.opcode = Call::SENDMSG;
|
||||
_call.handle = s;
|
||||
_call.sendmsg.msg.msg_name = msg->msg_name;
|
||||
_call.sendmsg.msg.msg_namelen = msg->msg_namelen;
|
||||
_call.sendmsg.msg.msg_iov = _call.sendmsg.iov;
|
||||
_call.sendmsg.msg.msg_iovlen = msg->msg_iovlen;
|
||||
_call.sendmsg.msg.msg_control = 0;
|
||||
_call.sendmsg.msg.msg_controllen = 0;
|
||||
_call.sendmsg.flags = msg_flags(flags);
|
||||
_call.opcode = Call::SENDMSG;
|
||||
_call.handle = s;
|
||||
_call.sendmsg.msg.msg_name = msg->msg_name;
|
||||
_call.sendmsg.msg.msg_namelen = msg->msg_namelen;
|
||||
_call.sendmsg.msg.msg_iter.iov = _call.sendmsg.iov;
|
||||
_call.sendmsg.msg.msg_iter.nr_segs = msg->msg_iovlen;
|
||||
_call.sendmsg.msg.msg_iter.count = msg->msg_count;
|
||||
_call.sendmsg.msg.msg_control = 0;
|
||||
_call.sendmsg.msg.msg_controllen = 0;
|
||||
_call.sendmsg.flags = msg_flags(flags);
|
||||
|
||||
for (unsigned i = 0; i < msg->msg_iovlen; ++i) {
|
||||
_call.sendmsg.iov[i].iov_base = msg->msg_iov[i].iov_base;
|
||||
|
@ -1,357 +0,0 @@
|
||||
/*
|
||||
* \brief Signal context for timer events
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/tslab.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
unsigned long jiffies;
|
||||
|
||||
|
||||
static void run_timer(void*);
|
||||
|
||||
namespace Lx {
|
||||
class Timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lx::Timer
|
||||
*/
|
||||
class Lx::Timer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Context encapsulates a regular linux timer_list
|
||||
*/
|
||||
struct Context : public Lx::List<Context>::Element
|
||||
{
|
||||
enum { INVALID_TIMEOUT = ~0UL };
|
||||
|
||||
struct timer_list *timer;
|
||||
bool pending { false };
|
||||
unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */
|
||||
bool programmed { false };
|
||||
|
||||
Context(struct timer_list *timer) : timer(timer) { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
::Timer::Connection _timer_conn;
|
||||
Lx::List<Context> _list;
|
||||
Lx::Task _timer_task;
|
||||
Genode::Signal_rpc_member<Lx::Timer> _dispatcher;
|
||||
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
|
||||
|
||||
/**
|
||||
* Lookup local timer
|
||||
*/
|
||||
Context *_find_context(struct timer_list const *timer)
|
||||
{
|
||||
for (Context *c = _list.first(); c; c = c->next())
|
||||
if (c->timer == timer)
|
||||
return c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Program the first timer in the list
|
||||
*
|
||||
* The first timer is programmed if the 'programmed' flag was not set
|
||||
* before. The second timer is flagged as not programmed as
|
||||
* 'Timer::trigger_once' invalidates former registered one-shot
|
||||
* timeouts.
|
||||
*/
|
||||
void _program_first_timer()
|
||||
{
|
||||
Context *ctx = _list.first();
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->programmed)
|
||||
return;
|
||||
|
||||
/* calculate relative microseconds for trigger */
|
||||
unsigned long us = ctx->timeout > jiffies ?
|
||||
jiffies_to_msecs(ctx->timeout - jiffies) * 1000 : 0;
|
||||
_timer_conn.trigger_once(us);
|
||||
|
||||
ctx->programmed = true;
|
||||
|
||||
/* possibly programmed successor must be reprogrammed later */
|
||||
if (Context *next = ctx->next())
|
||||
next->programmed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule timer
|
||||
*
|
||||
* Add the context to the scheduling list depending on its timeout
|
||||
* and reprogram the first timer.
|
||||
*/
|
||||
void _schedule_timer(Context *ctx, unsigned long expires)
|
||||
{
|
||||
_list.remove(ctx);
|
||||
|
||||
ctx->timeout = expires;
|
||||
ctx->pending = true;
|
||||
ctx->programmed = false;
|
||||
/*
|
||||
* Also write the timeout value to the expires field in
|
||||
* struct timer_list because the wireless stack checks
|
||||
* it directly.
|
||||
*/
|
||||
ctx->timer->expires = expires;
|
||||
|
||||
Context *c;
|
||||
for (c = _list.first(); c; c = c->next())
|
||||
if (ctx->timeout <= c->timeout)
|
||||
break;
|
||||
_list.insert_before(ctx, c);
|
||||
|
||||
_program_first_timer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle trigger_once signal
|
||||
*/
|
||||
void _handle(unsigned)
|
||||
{
|
||||
_timer_task.unblock();
|
||||
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timer(Server::Entrypoint &ep)
|
||||
:
|
||||
_timer_task(run_timer, nullptr, "timer", Lx::Task::PRIORITY_2,
|
||||
Lx::scheduler()),
|
||||
_dispatcher(ep, *this, &Lx::Timer::_handle),
|
||||
_timer_alloc(Genode::env()->heap())
|
||||
{
|
||||
_timer_conn.sigh(_dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new linux timer
|
||||
*/
|
||||
void add(struct timer_list *timer)
|
||||
{
|
||||
Context *t = new (&_timer_alloc) Context(timer);
|
||||
_list.append(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete linux timer
|
||||
*/
|
||||
int del(struct timer_list *timer)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
|
||||
/**
|
||||
* If the timer expired it was already cleaned up after its
|
||||
* execution.
|
||||
*/
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
|
||||
|
||||
_list.remove(ctx);
|
||||
destroy(&_timer_alloc, ctx);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial scheduling of linux timer
|
||||
*/
|
||||
int schedule(struct timer_list *timer, unsigned long expires)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
if (!ctx) {
|
||||
PERR("schedule unknown timer %p", timer);
|
||||
return -1; /* XXX better use 0 as rv? */
|
||||
}
|
||||
|
||||
/*
|
||||
* If timer was already active return 1, otherwise 0. The return
|
||||
* value is needed by mod_timer().
|
||||
*/
|
||||
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
|
||||
|
||||
_schedule_timer(ctx, expires);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule next linux timer
|
||||
*/
|
||||
void schedule_next() { _program_first_timer(); }
|
||||
|
||||
/**
|
||||
* Check if the timer is currently pending
|
||||
*/
|
||||
bool pending(struct timer_list const *timer)
|
||||
{
|
||||
Context *ctx = _find_context(timer);
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ctx->pending;
|
||||
}
|
||||
|
||||
Context *find(struct timer_list const *timer) {
|
||||
return _find_context(timer); }
|
||||
|
||||
/**
|
||||
* Update jiffie counter
|
||||
*/
|
||||
void update_jiffies()
|
||||
{
|
||||
jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first timer context
|
||||
*/
|
||||
Context* first() { return _list.first(); }
|
||||
};
|
||||
|
||||
|
||||
static Lx::Timer *_lx_timer;
|
||||
|
||||
|
||||
void Lx::timer_init(Server::Entrypoint &ep)
|
||||
{
|
||||
/* XXX safer way preventing possible nullptr access? */
|
||||
static Lx::Timer lx_timer(ep);
|
||||
_lx_timer = &lx_timer;
|
||||
|
||||
/* initialize value explicitly */
|
||||
jiffies = 0UL;
|
||||
}
|
||||
|
||||
|
||||
void Lx::timer_update_jiffies() {
|
||||
_lx_timer->update_jiffies(); }
|
||||
|
||||
|
||||
static void run_timer(void *)
|
||||
{
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
while (Lx::Timer::Context *ctx = _lx_timer->first()) {
|
||||
if (ctx->timeout > jiffies)
|
||||
break;
|
||||
|
||||
ctx->timer->function(ctx->timer->data);
|
||||
_lx_timer->del(ctx->timer);
|
||||
}
|
||||
|
||||
_lx_timer->schedule_next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** linux/timer.h **
|
||||
*******************/
|
||||
|
||||
void init_timer(struct timer_list *timer) { }
|
||||
|
||||
|
||||
int mod_timer(struct timer_list *timer, unsigned long expires)
|
||||
{
|
||||
if (!_lx_timer->find(timer))
|
||||
_lx_timer->add(timer);
|
||||
|
||||
return _lx_timer->schedule(timer, expires);
|
||||
}
|
||||
|
||||
|
||||
void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
|
||||
unsigned long data)
|
||||
{
|
||||
timer->function = function;
|
||||
timer->data = data;
|
||||
init_timer(timer);
|
||||
}
|
||||
|
||||
|
||||
int timer_pending(const struct timer_list *timer)
|
||||
{
|
||||
bool pending = _lx_timer->pending(timer);
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
||||
int del_timer(struct timer_list *timer)
|
||||
{
|
||||
int rv = _lx_timer->del(timer);
|
||||
_lx_timer->schedule_next();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** linux/sched.h **
|
||||
*******************/
|
||||
|
||||
static void unblock_task(unsigned long task)
|
||||
{
|
||||
Lx::Task *t = (Lx::Task *)task;
|
||||
|
||||
t->unblock();
|
||||
}
|
||||
|
||||
|
||||
signed long schedule_timeout(signed long timeout)
|
||||
{
|
||||
struct timer_list timer;
|
||||
|
||||
setup_timer(&timer, unblock_task, (unsigned long)Lx::scheduler().current());
|
||||
mod_timer(&timer, timeout);
|
||||
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
del_timer(&timer);
|
||||
|
||||
timeout = (timeout - jiffies);
|
||||
|
||||
return timeout < 0 ? 0 : timeout;
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
/*
|
||||
* \brief Workqueue implementation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
#include <base/tslab.h>
|
||||
#include <util/fifo.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lx.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <lx_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
static void run_work(void *);
|
||||
static void run_delayed_work(void *);
|
||||
|
||||
namespace Lx {
|
||||
class Work;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lx::Work
|
||||
*/
|
||||
class Lx::Work
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Context encapsulates a normal work item
|
||||
*/
|
||||
struct Context : public Lx::List<Context>::Element
|
||||
{
|
||||
void *work;
|
||||
enum Type { NORMAL, DELAYED, TASKLET } type;
|
||||
|
||||
void exec() {
|
||||
switch (type) {
|
||||
case NORMAL:
|
||||
{
|
||||
work_struct *w = static_cast<work_struct *>(work);
|
||||
w->func(w);
|
||||
}
|
||||
break;
|
||||
case DELAYED:
|
||||
{
|
||||
delayed_work *w = static_cast<delayed_work *>(work);
|
||||
w->work.func(&(w)->work);
|
||||
}
|
||||
break;
|
||||
case TASKLET:
|
||||
{
|
||||
tasklet_struct *tasklet = static_cast<tasklet_struct *>(work);
|
||||
tasklet->func(tasklet->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Context(delayed_work *w) : work(w), type(DELAYED) { }
|
||||
Context(work_struct *w) : work(w), type(NORMAL) { }
|
||||
Context(tasklet_struct *w) : work(w), type(TASKLET) { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Lx::Task _task;
|
||||
Lx::List<Context> _list;
|
||||
|
||||
Genode::Tslab<Context, 64 * sizeof(Context)> _work_alloc;
|
||||
|
||||
public:
|
||||
|
||||
Work(void (*func)(void*), char const *name)
|
||||
:
|
||||
_task(func, nullptr, name, Lx::Task::PRIORITY_2, Lx::scheduler()),
|
||||
_work_alloc(Genode::env()->heap())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Unblock corresponding task
|
||||
*/
|
||||
void unblock() { _task.unblock(); }
|
||||
|
||||
/**
|
||||
* Schedule work item
|
||||
*/
|
||||
template <typename WORK>
|
||||
void schedule(WORK *work)
|
||||
{
|
||||
Context *c = new (&_work_alloc) Context(work);
|
||||
_list.append(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all available work items
|
||||
*/
|
||||
void exec()
|
||||
{
|
||||
while (Context *c = _list.first()) {
|
||||
c->exec();
|
||||
_list.remove(c);
|
||||
destroy(&_work_alloc, c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel work item
|
||||
*/
|
||||
bool cancel_work(struct work_struct *work, bool sync = false)
|
||||
{
|
||||
for (Context *c = _list.first(); c; c = c->next()) {
|
||||
if (c->work == work) {
|
||||
if (sync)
|
||||
c->exec();
|
||||
|
||||
_list.remove(c);
|
||||
destroy(&_work_alloc, c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Lx::Work *_lx_work;
|
||||
static Lx::Work *_lx_delayed_work;
|
||||
|
||||
|
||||
void Lx::work_init(Server::Entrypoint &ep)
|
||||
{
|
||||
static Lx::Work work_ctx(run_work, "work");
|
||||
_lx_work = &work_ctx;
|
||||
|
||||
static Lx::Work delayed_work_ctx(run_delayed_work, "delayed_work");
|
||||
_lx_delayed_work = &delayed_work_ctx;
|
||||
}
|
||||
|
||||
|
||||
static void run_work(void *)
|
||||
{
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
_lx_work->exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void run_delayed_work(void *)
|
||||
{
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
_lx_delayed_work->exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
/***********************
|
||||
** linux/workquque.h **
|
||||
***********************/
|
||||
|
||||
int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
|
||||
{
|
||||
_lx_delayed_work->schedule(work);
|
||||
_lx_delayed_work->unblock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int schedule_work(struct work_struct *work)
|
||||
{
|
||||
_lx_work->schedule(work);
|
||||
_lx_work->unblock();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool cancel_delayed_work(struct delayed_work *dwork)
|
||||
{
|
||||
int pending = timer_pending(&dwork->timer);
|
||||
del_timer(&dwork->timer);
|
||||
|
||||
/* if the timer is still pending dwork was not executed */
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
||||
bool cancel_delayed_work_sync(struct delayed_work *dwork)
|
||||
{
|
||||
bool pending = cancel_delayed_work(dwork);
|
||||
|
||||
if (pending) {
|
||||
PERR("WARN: delayed_work %p is executed directly in current '%s' routine",
|
||||
dwork, Lx::scheduler().current()->name());
|
||||
|
||||
dwork->work.func(&dwork->work);
|
||||
}
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
||||
static void execute_delayed_work(unsigned long dwork)
|
||||
{
|
||||
_lx_delayed_work->schedule((struct delayed_work *)dwork);
|
||||
_lx_delayed_work->unblock();
|
||||
}
|
||||
|
||||
|
||||
bool queue_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 {
|
||||
setup_timer(&dwork->timer, execute_delayed_work, (unsigned long)dwork);
|
||||
mod_timer(&dwork->timer, delay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cancel_work_sync(struct work_struct *work)
|
||||
{
|
||||
return _lx_work->cancel_work(work, true);
|
||||
}
|
||||
|
||||
|
||||
bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
|
||||
{
|
||||
_lx_work->schedule(work);
|
||||
_lx_work->unblock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** linux/interrupt.h **
|
||||
***********************/
|
||||
|
||||
void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d)
|
||||
{
|
||||
t->func = f;
|
||||
t->data = d;
|
||||
}
|
||||
|
||||
|
||||
void tasklet_schedule(struct tasklet_struct *tasklet)
|
||||
{
|
||||
_lx_work->schedule(tasklet);
|
||||
}
|
||||
|
||||
|
||||
void tasklet_hi_schedule(struct tasklet_struct *tasklet)
|
||||
{
|
||||
tasklet_schedule(tasklet);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
@ -32,9 +32,11 @@
|
||||
#include "common.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
|
||||
|
||||
static char const *conf_file = "/config/wpa_supplicant.conf";
|
||||
|
||||
int wpa_main(void)
|
||||
|
||||
int wpa_main(int debug_msg)
|
||||
{
|
||||
struct wpa_interface iface;
|
||||
int exitcode = 0;
|
||||
@ -43,8 +45,7 @@ int wpa_main(void)
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
params.wpa_debug_level = MSG_INFO;
|
||||
// params.wpa_debug_level = MSG_DEBUG;
|
||||
params.wpa_debug_level = debug_msg ? MSG_DEBUG : MSG_INFO;
|
||||
|
||||
global = wpa_supplicant_init(¶ms);
|
||||
if (global == NULL)
|
||||
|
Reference in New Issue
Block a user