Commit 607f74c1 authored by Vikram Narayanan's avatar Vikram Narayanan

lcd/ixgbe: Support timers

Timers can't run inside LCD as there is no support. So, start a timer in KLCD
(but with a lower frequency compared to the original one) and trigger a handler
inside LCD when the timer expires.

In case of ixgbe driver, a service_event is triggered by the timer.

Also add support for asynchronous register dump via sysfs module params.
Signed-off-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent b2d3f159
......@@ -80,6 +80,8 @@ enum dispatch_t {
SYNC,
UNSYNC,
TRIGGER_EXIT,
SERVICE_EVENT_SCHED,
TRIGGER_DUMP,
};
typedef enum {
......
......@@ -2527,6 +2527,62 @@ fail_lookup:
return ret;
}
extern void __ixgbe_service_event_schedule(struct net_device *netdev);
int ixgbe_service_event_schedule_callee(struct fipc_message *_request,
struct thc_channel *_channel,
struct glue_cspace *cspace,
struct cptr sync_ep)
{
struct net_device_container *dev_container;
int ret = 0;
unsigned int request_cookie;
ret = glue_cap_lookup_net_device_type(c_cspace,
__cptr(fipc_get_reg1(_request)),
&dev_container);
if (ret) {
LIBLCD_ERR("lookup");
goto fail_lookup;
}
request_cookie = thc_get_request_cookie(_request);
fipc_recv_msg_end(thc_channel_to_fipc(_channel),
_request);
LIBLCD_MSG("service timer callback");
__ixgbe_service_event_schedule(&dev_container->net_device);
fail_lookup:
return ret;
}
extern void __ixgbe_dump(struct net_device *);
int trigger_dump_callee(struct fipc_message *_request,
struct thc_channel *_channel,
struct glue_cspace *cspace,
struct cptr sync_ep)
{
struct net_device_container *dev_container;
int ret = 0;
unsigned int request_cookie;
ret = glue_cap_lookup_net_device_type(c_cspace,
__cptr(fipc_get_reg1(_request)),
&dev_container);
if (ret) {
LIBLCD_ERR("lookup");
goto fail_lookup;
}
request_cookie = thc_get_request_cookie(_request);
fipc_recv_msg_end(thc_channel_to_fipc(_channel),
_request);
__ixgbe_dump(&dev_container->net_device);
fail_lookup:
return ret;
}
struct sync_container *sync_container;
struct unsync_container *unsync_container;
......
......@@ -113,6 +113,20 @@ int dispatch_async_loop(struct thc_channel *_channel,
cspace,
sync_ep);
case SERVICE_EVENT_SCHED:
trace(SERVICE_EVENT_SCHED);
return ixgbe_service_event_schedule_callee(message,
_channel,
cspace,
sync_ep);
case TRIGGER_DUMP:
trace(TRIGGER_DUMP);
return trigger_dump_callee(message,
_channel,
cspace,
sync_ep);
case TRIGGER_EXIT:
trace(TRIGGER_EXIT);
ixgbe_exit_module();
......
......@@ -363,6 +363,12 @@ static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
#endif
}
void __ixgbe_service_event_schedule(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
ixgbe_service_event_schedule(adapter);
}
static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
{
#ifndef LCD_ISOLATE
......@@ -897,6 +903,11 @@ static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
}
void __ixgbe_dump(struct net_device *dev)
{
ixgbe_dump(netdev_priv(dev));
}
static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
{
u32 ctrl_ext;
......
......@@ -68,4 +68,15 @@ int unsync_callee(struct fipc_message *_request,
struct thc_channel *_channel,
struct glue_cspace *cspace,
struct cptr sync_ep);
int ixgbe_service_event_schedule_callee(struct fipc_message *_request,
struct thc_channel *_channel,
struct glue_cspace *cspace,
struct cptr sync_ep);
int trigger_dump_callee(struct fipc_message *_request,
struct thc_channel *_channel,
struct glue_cspace *cspace,
struct cptr sync_ep);
#endif /* __IXGBE_CALLER_H__ */
......@@ -19,6 +19,7 @@ struct thc_channel *ixgbe_async;
struct cptr sync_ep;
extern struct cspace *klcd_cspace;
struct timer_list service_timer;
/* This is the only device we strive for */
#define IXGBE_DEV_ID_82599_SFP_SF2 0x154D
......@@ -584,6 +585,8 @@ fail_ipc:
return ret;
}
extern void ixgbe_service_timer(unsigned long data);
int probe(struct pci_dev *dev,
struct pci_device_id *id,
struct trampoline_hidden_args *hidden_args)
......@@ -696,6 +699,7 @@ int probe(struct pci_dev *dev,
fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl),
_response);
setup_timer(&service_timer, &ixgbe_service_timer, (unsigned long) NULL);
return func_ret;
fail_async:
fail_sync:
......@@ -832,6 +836,7 @@ void remove(struct pci_dev *dev,
}
fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl),
_response);
del_timer_sync(&service_timer);
return;
fail_async:
fail_ipc:
......@@ -875,6 +880,7 @@ int ndo_open_user(struct net_device *dev,
}
func_ret = fipc_get_reg1(_response);
printk("%s, returned %d\n", __func__, func_ret);
mod_timer(&service_timer, jiffies + msecs_to_jiffies(2000));
fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl),
_response);
lcd_exit(0);
......@@ -3693,6 +3699,90 @@ fail_ipc:
return ret;
}
int ixgbe_trigger_dump(struct thc_channel *_channel)
{
struct fipc_message *_request;
unsigned int request_cookie;
int ret;
struct net_device_container *dev_container;
bool cleanup = false;
if (!PTS()) {
cleanup = true;
thc_init();
}
ret = async_msg_blocking_send_start(_channel,
&_request);
if (ret) {
LIBLCD_ERR("failed to get a send slot");
goto fail_async;
}
async_msg_set_fn_type(_request,
TRIGGER_DUMP);
dev_container = container_of(g_ndev,
struct net_device_container, net_device);
fipc_set_reg1(_request,
dev_container->other_ref.cptr);
/* No need to wait for a response here */
ret = thc_ipc_send_request(_channel,
_request,
&request_cookie);
if (ret) {
LIBLCD_ERR("thc_ipc send");
goto fail_ipc;
}
fail_async:
fail_ipc:
if (cleanup)
lcd_exit(0);
return ret;
}
int ixgbe_service_event_sched(struct thc_channel *_channel)
{
struct fipc_message *_request;
unsigned int request_cookie;
int ret;
struct net_device_container *dev_container;
bool cleanup = false;
if (!PTS()) {
cleanup = true;
thc_init();
}
ret = async_msg_blocking_send_start(_channel,
&_request);
if (ret) {
LIBLCD_ERR("failed to get a send slot");
goto fail_async;
}
async_msg_set_fn_type(_request,
SERVICE_EVENT_SCHED);
dev_container = container_of(g_ndev,
struct net_device_container, net_device);
fipc_set_reg1(_request,
dev_container->other_ref.cptr);
/* No need to wait for a response here */
ret = thc_ipc_send_request(_channel,
_request,
&request_cookie);
if (ret) {
LIBLCD_ERR("thc_ipc send");
goto fail_ipc;
}
fail_async:
fail_ipc:
if (cleanup)
lcd_exit(0);
return ret;
}
int sync_user(struct net_device *dev,
unsigned char *mac,
struct trampoline_hidden_args *hidden_args)
......
......@@ -25,12 +25,20 @@ static LIST_HEAD(net_infos);
extern int setup_async_net_ring_channel(cptr_t tx, cptr_t rx,
struct thc_channel **chnl_out);
extern void destroy_async_net_ring_channel(struct thc_channel *chnl);
extern int ixgbe_trigger_dump(struct thc_channel *_channel);
extern int ixgbe_service_event_sched(struct thc_channel *_channel);
extern int trigger_exit_to_lcd(struct thc_channel *_channel);
extern struct timer_list service_timer;
extern struct glue_cspace *c_cspace;
struct pci_driver_container *pci_container;
/* mechanism for unloading LCD gracefully */
static bool unload_lcd =0;
module_param_named(unload, unload_lcd, bool, S_IWUSR);
/* to dump ixgbe registers */
static bool ixgbe_dump =0;
module_param_named(dump_regs, ixgbe_dump, bool, S_IWUSR);
struct net_info *
add_net(struct thc_channel *chnl, struct glue_cspace *cspace,
cptr_t sync_endpoint)
......@@ -58,7 +66,6 @@ void remove_net(struct net_info *net)
kfree(net);
}
static int __get_net(struct net_info **net_out)
{
struct net_info *first;
......@@ -68,7 +75,6 @@ static int __get_net(struct net_info **net_out)
return first ? 1 : 0;
}
static int async_loop(struct net_info **net_out, struct fipc_message **msg_out)
{
struct net_info *cursor, *next;
......@@ -110,6 +116,22 @@ static int async_loop(struct net_info **net_out, struct fipc_message **msg_out)
return -EWOULDBLOCK;
}
void ixgbe_service_timer(unsigned long data)
{
unsigned long next_event_offset;
struct net_info *net;
next_event_offset = msecs_to_jiffies(10000);
/* Reset the timer */
mod_timer(&service_timer, next_event_offset + jiffies);
if (__get_net(&net)) {
ixgbe_service_event_sched(net->chnl);
}
}
/* LOOP -------------------------------------------------- */
static int do_one_register(cptr_t register_chnl)
{
......@@ -201,7 +223,6 @@ fail1:
}
#define REGISTER_FREQ 50
extern int trigger_exit_to_lcd(struct thc_channel *_channel);
static void loop(cptr_t register_chnl)
{
......@@ -238,6 +259,11 @@ static void loop(cptr_t register_chnl)
if (__get_net(&net))
trigger_exit_to_lcd(net->chnl);
}
if (ixgbe_dump) {
ixgbe_dump = 0;
if (__get_net(&net))
ixgbe_trigger_dump(net->chnl);
}
ret = async_loop(&net, &msg);
if (!ret) {
ASYNC(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment