summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>2019-10-03 17:51:12 -0700
committerSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>2019-10-04 11:25:47 -0700
commit0e8ad333d9ee4e2e8700aa517785d098208da06e (patch)
treedc8901252dfeab95ae96ed766607696c5f365f32 /drivers
parentefe63abb0c15b355401df17fa23e781015206b0b (diff)
downloaddata-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.c123
-rwxr-xr-xdrivers/rmnet/shs/rmnet_shs_main.c9
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.
*/