Commit 7e0abe8f authored by Vikram Narayanan's avatar Vikram Narayanan

lcd/ixgbe: Add a mechanism for graceful exit of LCD

A module parameter is added to the KLCD module, which is exposed by the kernel
in sysfs. The dispatch loop monitors for a change in this variable and sends a
message to LCD to exit, thereby paving way for LCD to gracefully exit.
Signed-off-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent 26efd0f5
......@@ -5,6 +5,8 @@
#define trace(x) LIBLCD_MSG("net got " #x " msg")
extern void ixgbe_exit_module(void);
int dispatch_async_loop(struct thc_channel *_channel,
struct fipc_message *message,
struct glue_cspace *cspace,
......@@ -27,6 +29,14 @@ int dispatch_async_loop(struct thc_channel *_channel,
cspace,
sync_ep);
case TRIGGER_EXIT:
trace(TRIGGER_EXIT);
ixgbe_exit_module();
/* XXX: return failure to exit the dispatch
* loop. After exit, there is no reason to
* be spinning on the loop
*/
return -1;
default:
LIBLCD_ERR("unexpected function label: %d",
fn_type);
......
......@@ -86,18 +86,6 @@ static void main_and_loop(void)
LIBLCD_MSG("IXGBE EXITED DISPATCH LOOP");
);
/*
* We don't expect any requests coming back to us, so it's safe
* to just run this without a loop (it's effectively polling since
* only one awe will run in this do-finish).
*/
DO_FINISH(
ASYNC(
ixgbe_exit_module();
LIBLCD_MSG("SUCCESSFULLY UNREGISTERED IXGBE driver!");
);
);
LIBLCD_MSG("EXITED IXGBE DO_FINISH");
return;
......
......@@ -1903,3 +1903,34 @@ int pci_wake_from_d3_callee(struct fipc_message *_request,
_response);
return ret;
}
int trigger_exit_to_lcd(struct thc_channel *_channel)
{
struct fipc_message *_request;
int ret;
unsigned int request_cookie;
dump_stack();
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_EXIT);
/* 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:
return ret;
}
\ No newline at end of file
......@@ -28,6 +28,9 @@ extern void destroy_async_net_ring_channel(struct thc_channel *chnl);
extern struct glue_cspace *c_cspace;
struct pci_driver_container *pci_container;
static bool unload_lcd =0;
module_param_named(unload, unload_lcd, bool, S_IWUSR);
struct net_info *
add_net(struct thc_channel *chnl, struct glue_cspace *cspace,
cptr_t sync_endpoint)
......@@ -56,6 +59,15 @@ void remove_net(struct net_info *net)
}
static int __get_net(struct net_info **net_out)
{
struct net_info *first;
first = list_first_entry_or_null(&net_infos, struct net_info, list);
if (first)
*net_out = first;
return first ? 1 : 0;
}
static int async_loop(struct net_info **net_out, struct fipc_message **msg_out)
{
......@@ -189,6 +201,8 @@ fail1:
}
#define REGISTER_FREQ 50
extern int trigger_exit_to_lcd(struct thc_channel *_channel);
static void loop(cptr_t register_chnl)
{
unsigned long tics = jiffies + REGISTER_FREQ;
......@@ -200,7 +214,6 @@ static void loop(cptr_t register_chnl)
DO_FINISH(
while (!stop) {
//LIBLCD_MSG(" tics %lu\n", tics);
if (jiffies >= tics) {
/*
* Listen for a register call
......@@ -213,16 +226,18 @@ static void loop(cptr_t register_chnl)
tics = jiffies + REGISTER_FREQ;
continue;
}
/*
if (ixgbe_ready) {
ixgbe_ready = 0;
ASYNC(
stop = do_ixgbe_test();
);
}
*/
if (stop)
break;
/*
* will be updated by a write into sysfs
* from userspace.
*/
if (unload_lcd) {
unload_lcd = 0;
if (__get_net(&net))
trigger_exit_to_lcd(net->chnl);
}
ret = async_loop(&net, &msg);
if (!ret) {
ASYNC(
......@@ -263,10 +278,7 @@ static void loop(cptr_t register_chnl)
);
if (pci_container) {
pci_unregister_driver(&pci_container->pci_driver);
}
LIBLCD_MSG("EXITED IXGBE DO_FINISH");
LIBLCD_MSG("EXITED net_klcd DO_FINISH");
}
/* INIT / EXIT ---------------------------------------- */
......
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