diff options
author | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2019-10-03 17:51:12 -0700 |
---|---|---|
committer | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2019-10-04 11:25:47 -0700 |
commit | 0e8ad333d9ee4e2e8700aa517785d098208da06e (patch) | |
tree | dc8901252dfeab95ae96ed766607696c5f365f32 /drivers | |
parent | efe63abb0c15b355401df17fa23e781015206b0b (diff) | |
download | data-kernel-0e8ad333d9ee4e2e8700aa517785d098208da06e.tar.gz |
drivers: rmnet_shs: Change init to Register events
Previously we used NETDEV_GOING_DOWN and NETDEV_UP events
to cover shs init/de-init scenarios. That did not cover
rmnet driver going down prematurely if rmnet vnds were
cleaned up in a non-SSR scenario.
This change will allow shs to keep track of registered vnds
and to de-init when the last vnd has been unregistered to
avoid this issue.
<6> Unable to handle kernel NULL pointer dereference at virtual address 00000000
<6> Mem abort info:
<6> Exception class = DABT (current EL), IL = 32 bits
<6> SET = 0, FnV = 0
<6> EA = 0, S1PTW = 0
<6> FSC = 5
<6> Data abort info:
<6> ISV = 0, ISS = 0x00000005
<6> CM = 0, WnR = 0
<6> user pgtable: 4k pages, 39-bit VAs, pgd = 00000000bafe2c18
<6> task: 00000000d6d739bd task.stack: 000000009afe105c
<2> pc : rmnet_map_dl_ind_deregister+0x24/0x68
<2> lr : rmnet_shs_exit+0x30/0x68 [rmnet_shs]
<2> Call trace:
<2> rmnet_map_dl_ind_deregister+0x24/0x68
<2> rmnet_shs_dev_notify_cb+0x118/0x478 [rmnet_shs]
<2> raw_notifier_call_chain+0x3c/0x68
<2> __dev_close_many+0x9c/0x158
<2> dev_close_many+0x7c/0x1e0
<2> rollback_registered_many+0xe4/0x460
<2> unregister_netdev+0x48/0xd0
<2> mhi_netdev_remove+0x124/0x220
<2> mhi_driver_remove+0x178/0x250
<2> device_release_driver_internal+0x158/0x200
<2> device_release_driver+0x14/0x20
<2> bus_remove_device+0xd8/0x100
CRs-Fixed: 2540066
Change-Id: I231ff0af3cb2feb955b891b628487ab4fc3377ba
Acked-by: Raul Martinez <mraul@qti.qualcomm.com>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rmnet/shs/rmnet_shs_config.c | 123 | ||||
-rwxr-xr-x | drivers/rmnet/shs/rmnet_shs_main.c | 9 |
2 files changed, 69 insertions, 63 deletions
diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c index 341dcc9..ffa4f1d 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.c +++ b/drivers/rmnet/shs/rmnet_shs_config.c @@ -70,26 +70,26 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb, struct net_device *dev = netdev_notifier_info_to_dev(data); struct rmnet_priv *priv; struct rmnet_port *port; + int ret = 0; if (!dev) { rmnet_shs_crit_err[RMNET_SHS_NETDEV_ERR]++; return NOTIFY_DONE; } + if (!(strncmp(dev->name, "rmnet_data", 10) == 0 || + strncmp(dev->name, "r_rmnet_data", 12) == 0)) + return NOTIFY_DONE; + switch (event) { - case NETDEV_GOING_DOWN: + case NETDEV_UNREGISTER: rmnet_shs_wq_reset_ep_active(dev); - - if (strncmp(dev->name, "rmnet_data", 10) == 0) - rmnet_vnd_total--; + rmnet_vnd_total--; /* Deinitialize if last vnd is going down or if * phy_dev is going down. */ - if ((rmnet_is_real_dev_registered(dev) && - (!strcmp(dev->name, "rmnet_ipa0") || - !strcmp(dev->name, "rmnet_mhi0"))) && - rmnet_shs_cfg.rmnet_shs_init_complete) { + if (!rmnet_vnd_total && rmnet_shs_cfg.rmnet_shs_init_complete) { pr_info("rmnet_shs deinit %s going down ", dev->name); RCU_INIT_POINTER(rmnet_shs_skb_entry, NULL); qmi_rmnet_ps_ind_deregister(rmnet_shs_cfg.port, @@ -105,58 +105,73 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb, } break; - case NETDEV_UP: + case NETDEV_REGISTER: + rmnet_vnd_total++; - if (strncmp(dev->name, "rmnet_data", 10) == 0){ - rmnet_vnd_total++; - } + if (rmnet_vnd_total && !rmnet_shs_cfg.rmnet_shs_init_complete) { + pr_info("rmnet_shs initializing %s", dev->name); + priv = netdev_priv(dev); + port = rmnet_get_port(priv->real_dev); + if (!port) { + pr_err("rmnet_shs: invalid rmnet_port"); + break; + } + rmnet_shs_init(priv->real_dev, dev); + rmnet_shs_wq_init(priv->real_dev); + rmnet_shs_rx_wq_init(); - if (strncmp(dev->name, "rmnet_data", 10) == 0) { - /* Need separate if check to avoid - * NULL dereferencing - */ - - if (!rmnet_shs_cfg.rmnet_shs_init_complete) { - pr_info("rmnet_shs initializing %s", dev->name); - priv = netdev_priv(dev); - port = rmnet_get_port(priv->real_dev); - if (!port) { - pr_err("rmnet_shs: invalid rmnet_port"); - break; - } - rmnet_shs_init(priv->real_dev, dev); - rmnet_shs_wq_init(priv->real_dev); - rmnet_shs_rx_wq_init(); - rmnet_shs_cfg.is_timer_init = 1; - rmnet_shs_cfg.dl_mrk_ind_cb.priority = - RMNET_SHS; - if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER_V2) { - rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler_v2 = - &rmnet_shs_dl_hdr_handler_v2; - rmnet_shs_cfg.dl_mrk_ind_cb.dl_trl_handler_v2 = - &rmnet_shs_dl_trl_handler_v2; - } else { - rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler = - &rmnet_shs_dl_hdr_handler; - rmnet_shs_cfg.dl_mrk_ind_cb.dl_trl_handler = - &rmnet_shs_dl_trl_handler; - } - - trace_rmnet_shs_high(RMNET_SHS_MODULE, - RMNET_SHS_MODULE_INIT_WQ, - 0xDEF, 0xDEF, 0xDEF, - 0xDEF, NULL, NULL); - rmnet_shs_cfg.rmnet_idl_ind_cb.ps_on_handler = - &rmnet_shs_ps_on_hdlr; - rmnet_shs_cfg.rmnet_idl_ind_cb.ps_off_handler = - &rmnet_shs_ps_off_hdlr; - RCU_INIT_POINTER(rmnet_shs_skb_entry, - rmnet_shs_assign); + rmnet_shs_cfg.is_timer_init = 1; + } + rmnet_shs_wq_set_ep_active(dev); + break; + case NETDEV_UP: + if (!rmnet_shs_cfg.is_reg_dl_mrk_ind && + rmnet_shs_cfg.rmnet_shs_init_complete) { + port = rmnet_shs_cfg.port; + if (!port) { + pr_err("rmnet_shs: invalid rmnet_cfg_port"); + break; } - rmnet_shs_wq_set_ep_active(dev); + rmnet_shs_cfg.dl_mrk_ind_cb.priority = + RMNET_SHS; + if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER_V2) { + rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler_v2 = + &rmnet_shs_dl_hdr_handler_v2; + rmnet_shs_cfg.dl_mrk_ind_cb.dl_trl_handler_v2 = + &rmnet_shs_dl_trl_handler_v2; + } else { + rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler = + &rmnet_shs_dl_hdr_handler; + rmnet_shs_cfg.dl_mrk_ind_cb.dl_trl_handler = + &rmnet_shs_dl_trl_handler; + } + rmnet_shs_cfg.rmnet_idl_ind_cb.ps_on_handler = + &rmnet_shs_ps_on_hdlr; + rmnet_shs_cfg.rmnet_idl_ind_cb.ps_off_handler = + &rmnet_shs_ps_off_hdlr; + + ret = rmnet_map_dl_ind_register(port, + &rmnet_shs_cfg.dl_mrk_ind_cb); + if (ret) + pr_err("%s(): rmnet dl_ind registration fail\n", + __func__); + + ret = qmi_rmnet_ps_ind_register(port, + &rmnet_shs_cfg.rmnet_idl_ind_cb); + if (ret) + pr_err("%s(): rmnet ps_ind registration fail\n", + __func__); + + rmnet_shs_cfg.is_reg_dl_mrk_ind = 1; + trace_rmnet_shs_high(RMNET_SHS_MODULE, + RMNET_SHS_MODULE_INIT_WQ, + 0xDEF, 0xDEF, 0xDEF, + 0xDEF, NULL, NULL); + RCU_INIT_POINTER(rmnet_shs_skb_entry, + rmnet_shs_assign); } break; diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index 4b7734b..b52e608 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1563,15 +1563,6 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port) return; } - if (!rmnet_shs_cfg.is_reg_dl_mrk_ind) { - rmnet_map_dl_ind_register(port, &rmnet_shs_cfg.dl_mrk_ind_cb); - qmi_rmnet_ps_ind_register(port, - &rmnet_shs_cfg.rmnet_idl_ind_cb); - - rmnet_shs_cfg.is_reg_dl_mrk_ind = 1; - shs_rx_work.port = port; - - } /* We got the first packet after a previous successdul flush. Arm the * flushing timer. */ |