Loading drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c +204 −56 Original line number Diff line number Diff line Loading @@ -317,6 +317,12 @@ enum ipa_mpm_gsi_state { GSI_STOPPED, }; enum ipa_mpm_remote_state { MPM_MHIP_REMOTE_STOP, MPM_MHIP_REMOTE_START, MPM_MHIP_REMOTE_ERR, }; struct ipa_mpm_channel { struct ipa_mpm_channel_props chan_props; struct ipa_mpm_event_props evt_props; Loading Loading @@ -382,6 +388,7 @@ struct ipa_mpm_mhi_driver { struct mutex mhi_mutex; bool in_lpm; struct ipa_mpm_clk_cnt_type clk_cnt; enum ipa_mpm_remote_state remote_state; }; struct ipa_mpm_context { Loading Loading @@ -1440,6 +1447,59 @@ static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote, } } static int ipa_mpm_start_stop_remote_mhip_chan( int probe_id, enum ipa_mpm_start_stop_type start_stop) { int ret = 0; struct mhi_device *mhi_dev = ipa_mpm_ctx->md[probe_id].mhi_dev; if (!mhi_dev) { IPA_MPM_ERR("MHI not initialized yet\n"); return ret; } mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); /* For error state, expect modem SSR to recover from error */ if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_ERR) { IPA_MPM_ERR("Remote channels in err state for %d\n", probe_id); mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); return -EFAULT; } if (start_stop == MPM_MHIP_START) { if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_START) { IPA_MPM_DBG("Remote channel already started for %d\n", probe_id); } else { ret = mhi_resume_transfer(mhi_dev); if (ret) ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_ERR; else ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_START; } } else { if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_STOP) { IPA_MPM_DBG("Remote channel already stopped for %d\n", probe_id); } else { ret = mhi_pause_transfer(mhi_dev); if (ret) ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_ERR; else ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_STOP; } } mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); return ret; } static enum mhip_status_type ipa_mpm_start_stop_mhip_chan( enum ipa_mpm_mhip_chan mhip_chan, int probe_id, Loading Loading @@ -1627,6 +1687,26 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret); return ret; } /* * Make sure to start Device side channels before * starting Host side UL channels. This is to make * sure device side access host side only after * Host IPA gets voted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_START); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan start fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are started\n"); status = ipa_mpm_start_stop_mhip_chan( IPA_MPM_MHIP_CHAN_UL, probe_id, MPM_MHIP_START); switch (status) { Loading @@ -1636,7 +1716,7 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret = ipa_mpm_start_stop_ul_mhip_data_path( probe_id, MPM_MHIP_START); if (ret) { IPA_MPM_ERR("err UL chan start\n"); IPA_MPM_ERR("UL chan start err = %d\n", ret); ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id); return ret; } Loading @@ -1662,6 +1742,25 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) } ipa_mpm_ctx->md[probe_id].mhip_client = mhip_client; } else { /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure device side doesn't access host IPA after * Host IPA gets devoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are stopped\n"); status = ipa_mpm_start_stop_mhip_chan( IPA_MPM_MHIP_CHAN_UL, probe_id, MPM_MHIP_STOP); Loading Loading @@ -1691,7 +1790,7 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret = ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id); if (ret) { IPA_MPM_ERR("Error cloking on PCIe clk, err = %d\n", IPA_MPM_ERR("Error cloking off PCIe clk, err = %d\n", ret); return ret; } Loading Loading @@ -1892,6 +1991,9 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ipa_mpm_ctx->mhi_parent_dev = ipa_mpm_ctx->md[probe_id].mhi_dev->dev.parent; mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_STOP; mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_vote_unvote_pcie_clk(CLK_ON, probe_id); mutex_lock(&ipa_mpm_ctx->md[probe_id].lpm_mutex); ipa_mpm_vote_unvote_ipa_clk(CLK_ON, probe_id); Loading Loading @@ -1938,6 +2040,33 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ch->evt_props.device_db = ipa_mpm_ctx->dev_info.erdb_base + ch->chan_props.ch_ctx.erindex * 8; /* connect Host GSI pipes with MHI' protocol */ ret = ipa_mpm_connect_mhip_gsi_pipe(ul_prod, probe_id, &ul_out_params); if (ret) { IPA_MPM_ERR("failed connecting MPM client %d\n", ul_prod); goto fail_gsi_setup; } ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, ul_out_params.db_reg_phs_addr_lsb); if (ch->evt_props.ev_ctx.update_rp_addr == 0) ipa_assert(); ipa_mpm_ctx->md[probe_id].ul_prod.db_device_iova = ch->evt_props.ev_ctx.update_rp_addr; ret = __ipa_mpm_configure_mhi_device( ch, probe_id, DMA_TO_HIPA); if (ret) { IPA_MPM_ERR("configure_mhi_dev fail %d\n", ret); goto fail_smmu; } } if (dl_cons != IPA_CLIENT_MAX) { Loading Loading @@ -1965,19 +2094,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ch->evt_props.device_db = ipa_mpm_ctx->dev_info.erdb_base + ch->chan_props.ch_ctx.erindex * 8; } /* connect Host GSI pipes with MHI' protocol */ if (ul_prod != IPA_CLIENT_MAX) { ret = ipa_mpm_connect_mhip_gsi_pipe(ul_prod, probe_id, &ul_out_params); if (ret) { IPA_MPM_ERR("failed connecting MPM client %d\n", ul_prod); goto fail_gsi_setup; } } if (dl_cons != IPA_CLIENT_MAX) { /* connect Host GSI pipes with MHI' protocol */ ret = ipa_mpm_connect_mhip_gsi_pipe(dl_cons, probe_id, &dl_out_params); if (ret) { Loading @@ -1985,30 +2103,7 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, dl_cons); goto fail_gsi_setup; } } if (ul_prod != IPA_CLIENT_MAX) { ch = &ipa_mpm_ctx->md[probe_id].ul_prod; ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, ul_out_params.db_reg_phs_addr_lsb); if (ch->evt_props.ev_ctx.update_rp_addr == 0) ipa_assert(); ipa_mpm_ctx->md[probe_id].ul_prod.db_device_iova = ch->evt_props.ev_ctx.update_rp_addr; ret = __ipa_mpm_configure_mhi_device( ch, probe_id, DMA_TO_HIPA); if (ret) { IPA_MPM_ERR("configure_mhi_dev fail %d\n", ret); goto fail_smmu; } } if (dl_cons != IPA_CLIENT_MAX) { ch = &ipa_mpm_ctx->md[probe_id].dl_cons; ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, Loading Loading @@ -2044,6 +2139,10 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, return 0; } /* mhi_prepare_for_transfer translates to starting remote channels */ mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_START; mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); /* * Ring initial channel db - Host Side UL and Device side DL channel. * To ring doorbell, write "WP" into doorbell register. Loading @@ -2068,13 +2167,11 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iounmap(db_addr); ipa_mpm_read_channel(ul_prod); } /* Ring UL PRODUCER EVENT RING (HOST IPA -> DEVICE IPA) Doorbell * Ring the event DB to a value outside the * ring range such that rp and wp never meet. */ if (ul_prod != IPA_CLIENT_MAX) { ipa_ep_idx = ipa3_get_ep_mapping(ul_prod); if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) { Loading @@ -2100,10 +2197,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iowrite32(wp_addr, db_addr); iounmap(db_addr); } /* Ring DEVICE IPA DL CONSUMER Event Doorbell */ if (ul_prod != IPA_CLIENT_MAX) { db_addr = ioremap((phys_addr_t) (ipa_mpm_ctx->md[probe_id].ul_prod.evt_props.device_db), 4); Loading @@ -2130,14 +2225,12 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iowrite32(wp_addr, db_addr); iounmap(db_addr); } /* * Ring event ring DB on Device side. * ipa_mpm should ring the event DB to a value outside the * ring range such that rp and wp never meet. */ if (dl_cons != IPA_CLIENT_MAX) { db_addr = ioremap( (phys_addr_t) Loading @@ -2151,10 +2244,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, IPA_MPM_DBG("Device UL ER DB = 0X%pK,wp_addr = 0X%0x", db_addr, wp_addr); iounmap(db_addr); } /* Ring DL EVENT RING CONSUMER (DEVICE IPA CONSUMER) Doorbell */ if (dl_cons != IPA_CLIENT_MAX) { ipa_ep_idx = ipa3_get_ep_mapping(dl_cons); if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) { Loading Loading @@ -2182,6 +2273,23 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, */ switch (ipa_mpm_ctx->md[probe_id].teth_state) { case IPA_MPM_TETH_INIT: /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure Device side doesn't access host side IPA if * Host IPA gets unvoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } if (ul_prod != IPA_CLIENT_MAX) { /* No teth started yet, disable UL channel */ ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL, Loading Loading @@ -2437,6 +2545,27 @@ int ipa_mpm_mhip_xdci_pipe_enable(enum ipa_usb_teth_prot xdci_teth_prot) return ret; } /* * Make sure to start Device side channels before * starting Host side UL channels. This is to make * sure device side access host side IPA only when * Host IPA gets voted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_START); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan start fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channel start success\n"); switch (mhip_client) { case IPA_MPM_MHIP_USB_RMNET: ipa_mpm_set_dma_mode(IPA_CLIENT_USB_PROD, Loading Loading @@ -2529,6 +2658,25 @@ int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot) IPA_MPM_ERR("xdci disconnect prot %d mhip_client = %d probe_id = %d\n", xdci_teth_prot, mhip_client, probe_id); /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure device side doesn't access host side IPA if * Host IPA gets unvoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are stopped\n"); switch (mhip_client) { case IPA_MPM_MHIP_USB_RMNET: Loading Loading
drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c +204 −56 Original line number Diff line number Diff line Loading @@ -317,6 +317,12 @@ enum ipa_mpm_gsi_state { GSI_STOPPED, }; enum ipa_mpm_remote_state { MPM_MHIP_REMOTE_STOP, MPM_MHIP_REMOTE_START, MPM_MHIP_REMOTE_ERR, }; struct ipa_mpm_channel { struct ipa_mpm_channel_props chan_props; struct ipa_mpm_event_props evt_props; Loading Loading @@ -382,6 +388,7 @@ struct ipa_mpm_mhi_driver { struct mutex mhi_mutex; bool in_lpm; struct ipa_mpm_clk_cnt_type clk_cnt; enum ipa_mpm_remote_state remote_state; }; struct ipa_mpm_context { Loading Loading @@ -1440,6 +1447,59 @@ static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote, } } static int ipa_mpm_start_stop_remote_mhip_chan( int probe_id, enum ipa_mpm_start_stop_type start_stop) { int ret = 0; struct mhi_device *mhi_dev = ipa_mpm_ctx->md[probe_id].mhi_dev; if (!mhi_dev) { IPA_MPM_ERR("MHI not initialized yet\n"); return ret; } mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); /* For error state, expect modem SSR to recover from error */ if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_ERR) { IPA_MPM_ERR("Remote channels in err state for %d\n", probe_id); mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); return -EFAULT; } if (start_stop == MPM_MHIP_START) { if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_START) { IPA_MPM_DBG("Remote channel already started for %d\n", probe_id); } else { ret = mhi_resume_transfer(mhi_dev); if (ret) ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_ERR; else ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_START; } } else { if (ipa_mpm_ctx->md[probe_id].remote_state == MPM_MHIP_REMOTE_STOP) { IPA_MPM_DBG("Remote channel already stopped for %d\n", probe_id); } else { ret = mhi_pause_transfer(mhi_dev); if (ret) ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_ERR; else ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_STOP; } } mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); return ret; } static enum mhip_status_type ipa_mpm_start_stop_mhip_chan( enum ipa_mpm_mhip_chan mhip_chan, int probe_id, Loading Loading @@ -1627,6 +1687,26 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret); return ret; } /* * Make sure to start Device side channels before * starting Host side UL channels. This is to make * sure device side access host side only after * Host IPA gets voted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_START); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan start fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are started\n"); status = ipa_mpm_start_stop_mhip_chan( IPA_MPM_MHIP_CHAN_UL, probe_id, MPM_MHIP_START); switch (status) { Loading @@ -1636,7 +1716,7 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret = ipa_mpm_start_stop_ul_mhip_data_path( probe_id, MPM_MHIP_START); if (ret) { IPA_MPM_ERR("err UL chan start\n"); IPA_MPM_ERR("UL chan start err = %d\n", ret); ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id); return ret; } Loading @@ -1662,6 +1742,25 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) } ipa_mpm_ctx->md[probe_id].mhip_client = mhip_client; } else { /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure device side doesn't access host IPA after * Host IPA gets devoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are stopped\n"); status = ipa_mpm_start_stop_mhip_chan( IPA_MPM_MHIP_CHAN_UL, probe_id, MPM_MHIP_STOP); Loading Loading @@ -1691,7 +1790,7 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state) ret = ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id); if (ret) { IPA_MPM_ERR("Error cloking on PCIe clk, err = %d\n", IPA_MPM_ERR("Error cloking off PCIe clk, err = %d\n", ret); return ret; } Loading Loading @@ -1892,6 +1991,9 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ipa_mpm_ctx->mhi_parent_dev = ipa_mpm_ctx->md[probe_id].mhi_dev->dev.parent; mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_STOP; mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_vote_unvote_pcie_clk(CLK_ON, probe_id); mutex_lock(&ipa_mpm_ctx->md[probe_id].lpm_mutex); ipa_mpm_vote_unvote_ipa_clk(CLK_ON, probe_id); Loading Loading @@ -1938,6 +2040,33 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ch->evt_props.device_db = ipa_mpm_ctx->dev_info.erdb_base + ch->chan_props.ch_ctx.erindex * 8; /* connect Host GSI pipes with MHI' protocol */ ret = ipa_mpm_connect_mhip_gsi_pipe(ul_prod, probe_id, &ul_out_params); if (ret) { IPA_MPM_ERR("failed connecting MPM client %d\n", ul_prod); goto fail_gsi_setup; } ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, ul_out_params.db_reg_phs_addr_lsb); if (ch->evt_props.ev_ctx.update_rp_addr == 0) ipa_assert(); ipa_mpm_ctx->md[probe_id].ul_prod.db_device_iova = ch->evt_props.ev_ctx.update_rp_addr; ret = __ipa_mpm_configure_mhi_device( ch, probe_id, DMA_TO_HIPA); if (ret) { IPA_MPM_ERR("configure_mhi_dev fail %d\n", ret); goto fail_smmu; } } if (dl_cons != IPA_CLIENT_MAX) { Loading Loading @@ -1965,19 +2094,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ch->evt_props.device_db = ipa_mpm_ctx->dev_info.erdb_base + ch->chan_props.ch_ctx.erindex * 8; } /* connect Host GSI pipes with MHI' protocol */ if (ul_prod != IPA_CLIENT_MAX) { ret = ipa_mpm_connect_mhip_gsi_pipe(ul_prod, probe_id, &ul_out_params); if (ret) { IPA_MPM_ERR("failed connecting MPM client %d\n", ul_prod); goto fail_gsi_setup; } } if (dl_cons != IPA_CLIENT_MAX) { /* connect Host GSI pipes with MHI' protocol */ ret = ipa_mpm_connect_mhip_gsi_pipe(dl_cons, probe_id, &dl_out_params); if (ret) { Loading @@ -1985,30 +2103,7 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, dl_cons); goto fail_gsi_setup; } } if (ul_prod != IPA_CLIENT_MAX) { ch = &ipa_mpm_ctx->md[probe_id].ul_prod; ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, ul_out_params.db_reg_phs_addr_lsb); if (ch->evt_props.ev_ctx.update_rp_addr == 0) ipa_assert(); ipa_mpm_ctx->md[probe_id].ul_prod.db_device_iova = ch->evt_props.ev_ctx.update_rp_addr; ret = __ipa_mpm_configure_mhi_device( ch, probe_id, DMA_TO_HIPA); if (ret) { IPA_MPM_ERR("configure_mhi_dev fail %d\n", ret); goto fail_smmu; } } if (dl_cons != IPA_CLIENT_MAX) { ch = &ipa_mpm_ctx->md[probe_id].dl_cons; ch->evt_props.ev_ctx.update_rp_addr = ipa_mpm_smmu_map_doorbell( MHIP_SMMU_DOMAIN_PCIE, Loading Loading @@ -2044,6 +2139,10 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, return 0; } /* mhi_prepare_for_transfer translates to starting remote channels */ mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); ipa_mpm_ctx->md[probe_id].remote_state = MPM_MHIP_REMOTE_START; mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex); /* * Ring initial channel db - Host Side UL and Device side DL channel. * To ring doorbell, write "WP" into doorbell register. Loading @@ -2068,13 +2167,11 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iounmap(db_addr); ipa_mpm_read_channel(ul_prod); } /* Ring UL PRODUCER EVENT RING (HOST IPA -> DEVICE IPA) Doorbell * Ring the event DB to a value outside the * ring range such that rp and wp never meet. */ if (ul_prod != IPA_CLIENT_MAX) { ipa_ep_idx = ipa3_get_ep_mapping(ul_prod); if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) { Loading @@ -2100,10 +2197,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iowrite32(wp_addr, db_addr); iounmap(db_addr); } /* Ring DEVICE IPA DL CONSUMER Event Doorbell */ if (ul_prod != IPA_CLIENT_MAX) { db_addr = ioremap((phys_addr_t) (ipa_mpm_ctx->md[probe_id].ul_prod.evt_props.device_db), 4); Loading @@ -2130,14 +2225,12 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, iowrite32(wp_addr, db_addr); iounmap(db_addr); } /* * Ring event ring DB on Device side. * ipa_mpm should ring the event DB to a value outside the * ring range such that rp and wp never meet. */ if (dl_cons != IPA_CLIENT_MAX) { db_addr = ioremap( (phys_addr_t) Loading @@ -2151,10 +2244,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, IPA_MPM_DBG("Device UL ER DB = 0X%pK,wp_addr = 0X%0x", db_addr, wp_addr); iounmap(db_addr); } /* Ring DL EVENT RING CONSUMER (DEVICE IPA CONSUMER) Doorbell */ if (dl_cons != IPA_CLIENT_MAX) { ipa_ep_idx = ipa3_get_ep_mapping(dl_cons); if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) { Loading Loading @@ -2182,6 +2273,23 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, */ switch (ipa_mpm_ctx->md[probe_id].teth_state) { case IPA_MPM_TETH_INIT: /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure Device side doesn't access host side IPA if * Host IPA gets unvoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } if (ul_prod != IPA_CLIENT_MAX) { /* No teth started yet, disable UL channel */ ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL, Loading Loading @@ -2437,6 +2545,27 @@ int ipa_mpm_mhip_xdci_pipe_enable(enum ipa_usb_teth_prot xdci_teth_prot) return ret; } /* * Make sure to start Device side channels before * starting Host side UL channels. This is to make * sure device side access host side IPA only when * Host IPA gets voted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_START); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan start fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channel start success\n"); switch (mhip_client) { case IPA_MPM_MHIP_USB_RMNET: ipa_mpm_set_dma_mode(IPA_CLIENT_USB_PROD, Loading Loading @@ -2529,6 +2658,25 @@ int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot) IPA_MPM_ERR("xdci disconnect prot %d mhip_client = %d probe_id = %d\n", xdci_teth_prot, mhip_client, probe_id); /* * Make sure to stop Device side channels before * stopping Host side UL channels. This is to make * sure device side doesn't access host side IPA if * Host IPA gets unvoted. */ ret = ipa_mpm_start_stop_remote_mhip_chan(probe_id, MPM_MHIP_STOP); if (ret) { /* * This can fail only when modem is in SSR state. * Eventually there would be a remove callback, * so return a failure. */ IPA_MPM_ERR("MHIP remote chan stop fail = %d\n", ret); return ret; } IPA_MPM_DBG("MHIP remote channels are stopped\n"); switch (mhip_client) { case IPA_MPM_MHIP_USB_RMNET: Loading