Loading drivers/bus/mhi/core/mhi_internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,9 @@ struct mhi_chan { struct completion completion; rwlock_t lock; struct list_head node; /* stats */ u64 mode_change; }; struct tsync_node { Loading drivers/bus/mhi/core/mhi_main.c +49 −24 Original line number Diff line number Diff line Loading @@ -568,9 +568,9 @@ int mhi_queue_dma(struct mhi_device *mhi_dev, mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(mhi_chan->bei, 1, 0, 0); } MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, mhi_tre->dword[0], mhi_tre->dword[1]); MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x rDB %d\n", mhi_chan->chan, (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, mhi_tre->dword[0], mhi_tre->dword[1], ring_db); /* increment WP */ mhi_add_ring_element(mhi_cntrl, tre_ring); Loading Loading @@ -982,6 +982,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, unsigned long flags = 0; bool ring_db = true; int n_free_tre, n_queued_tre; unsigned long rflags; ev_code = MHI_TRE_GET_EV_CODE(event); buf_ring = &mhi_chan->buf_ring; Loading Loading @@ -1071,12 +1072,8 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, break; } /* CC_EOT */ case MHI_EV_CC_OOB: case MHI_EV_CC_DB_MODE: { unsigned long flags; MHI_VERB("DB_MODE/OOB Detected chan %d.\n", mhi_chan->chan); mhi_chan->db_cfg.db_mode = 1; mhi_chan->db_cfg.db_mode = true; mhi_chan->mode_change++; /* * on RSC channel IPA HW has a minimum credit requirement before Loading @@ -1090,14 +1087,27 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, ring_db = false; } read_lock_irqsave(&mhi_cntrl->pm_lock, flags); MHI_VERB("OOB_MODE chan %d ring_db %d\n", mhi_chan->chan, ring_db); read_lock_irqsave(&mhi_cntrl->pm_lock, rflags); if (tre_ring->wp != tre_ring->rp && MHI_DB_ACCESS_VALID(mhi_cntrl) && ring_db) { MHI_DB_ACCESS_VALID(mhi_cntrl) && ring_db) mhi_ring_chan_db(mhi_cntrl, mhi_chan); } read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); read_unlock_irqrestore(&mhi_cntrl->pm_lock, rflags); break; case MHI_EV_CC_DB_MODE: MHI_VERB("DB_MODE chan %d.\n", mhi_chan->chan); mhi_chan->db_cfg.db_mode = true; mhi_chan->mode_change++; read_lock_irqsave(&mhi_cntrl->pm_lock, rflags); if (tre_ring->wp != tre_ring->rp && MHI_DB_ACCESS_VALID(mhi_cntrl)) mhi_ring_chan_db(mhi_cntrl, mhi_chan); read_unlock_irqrestore(&mhi_cntrl->pm_lock, rflags); break; } case MHI_EV_CC_BAD_TRE: MHI_ASSERT(1, "Received BAD TRE event for ring"); break; Loading Loading @@ -1135,7 +1145,12 @@ static int parse_rsc_event(struct mhi_controller *mhi_cntrl, xfer_len = MHI_TRE_GET_EV_LEN(event); /* received out of bound cookie */ MHI_ASSERT(cookie >= buf_ring->len, "Invalid Cookie\n"); if (cookie >= buf_ring->len) { MHI_ERR("cookie 0x%08x bufring_len %zu", cookie, buf_ring->len); MHI_ERR("Processing Event:0x%llx 0x%08x 0x%08x\n", event->ptr, event->dword[0], event->dword[1]); panic("invalid cookie"); } buf_info = buf_ring->base + cookie; Loading Loading @@ -1385,6 +1400,10 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); chan = MHI_TRE_GET_EV_CHID(local_rp); if (chan >= mhi_cntrl->max_chan) { MHI_ERR("invalid channel id %u\n", chan); continue; } mhi_chan = &mhi_cntrl->mhi_chan[chan]; if (likely(type == MHI_PKT_TYPE_TX_EVENT)) { Loading Loading @@ -1680,14 +1699,18 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) MHI_VERB("Enter\n"); write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { write_unlock_irq(&mhi_cntrl->pm_lock); goto exit_intvec; } state = mhi_get_mhi_state(mhi_cntrl); ee = mhi_cntrl->ee; mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", MHI_LOG("local ee: %s device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_STATE_STR(state)); } if (state == MHI_STATE_SYS_ERR) { MHI_ERR("MHI system error detected\n"); Loading Loading @@ -2205,12 +2228,14 @@ int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d) chan_ctxt->pollcfg, chan_ctxt->chtype, chan_ctxt->erindex); seq_printf(m, " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n", " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx mode_change:0x%llx\n", chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->wp, mhi_to_physical(ring, ring->rp), mhi_to_physical(ring, ring->wp), mhi_chan->db_cfg.db_val); mhi_chan->db_cfg.db_val, mhi_chan->mode_change); mhi_chan->mode_change = 0; } } Loading drivers/bus/mhi/core/mhi_pm.c +6 −0 Original line number Diff line number Diff line Loading @@ -1163,6 +1163,9 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) write_unlock_irq(&mhi_cntrl->pm_lock); MHI_LOG("Wait for M3 completion\n"); /* finish reg writes before D3 cold */ mhi_force_reg_write(mhi_cntrl); ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->dev_state == MHI_STATE_M3 || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), Loading Loading @@ -1274,6 +1277,9 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) mhi_cntrl->M3_FAST++; write_unlock_irq(&mhi_cntrl->pm_lock); /* finish reg writes before DRV hand-off to avoid noc err */ mhi_force_reg_write(mhi_cntrl); /* now safe to check ctrl event ring */ tasklet_enable(&mhi_cntrl->mhi_event->task); mhi_msi_handlr(0, mhi_cntrl->mhi_event); Loading drivers/bus/mhi/devices/mhi_netdev.c +9 −2 Original line number Diff line number Diff line /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -120,6 +120,7 @@ struct mhi_netdev { /* debug stats */ u32 abuffers, kbuffers, rbuffers; bool napi_scheduled; }; struct mhi_netdev_priv { Loading Loading @@ -458,6 +459,7 @@ static int mhi_netdev_alloc_thread(void *data) /* replenish the ring */ napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; /* wait for buffers to run low or thread to stop */ wait_event_interruptible(mhi_netdev->alloc_event, Loading Loading @@ -497,6 +499,7 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget) if (rx_work < 0) { MSG_ERR("Error polling ret:%d\n", rx_work); napi_complete(napi); mhi_netdev->napi_scheduled = false; return 0; } Loading @@ -507,8 +510,10 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget) mhi_netdev_queue(mhi_netdev, rsc_dev->mhi_dev); /* complete work if # of packet processed less than allocated budget */ if (rx_work < budget) if (rx_work < budget) { napi_complete(napi); mhi_netdev->napi_scheduled = false; } MSG_VERB("polled %d pkts\n", rx_work); Loading Loading @@ -844,6 +849,7 @@ static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) return; napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; } #ifdef CONFIG_DEBUG_FS Loading Loading @@ -1104,6 +1110,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev, * by triggering a napi_poll */ napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; return 0; } Loading Loading
drivers/bus/mhi/core/mhi_internal.h +3 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,9 @@ struct mhi_chan { struct completion completion; rwlock_t lock; struct list_head node; /* stats */ u64 mode_change; }; struct tsync_node { Loading
drivers/bus/mhi/core/mhi_main.c +49 −24 Original line number Diff line number Diff line Loading @@ -568,9 +568,9 @@ int mhi_queue_dma(struct mhi_device *mhi_dev, mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(mhi_chan->bei, 1, 0, 0); } MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, mhi_tre->dword[0], mhi_tre->dword[1]); MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x rDB %d\n", mhi_chan->chan, (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, mhi_tre->dword[0], mhi_tre->dword[1], ring_db); /* increment WP */ mhi_add_ring_element(mhi_cntrl, tre_ring); Loading Loading @@ -982,6 +982,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, unsigned long flags = 0; bool ring_db = true; int n_free_tre, n_queued_tre; unsigned long rflags; ev_code = MHI_TRE_GET_EV_CODE(event); buf_ring = &mhi_chan->buf_ring; Loading Loading @@ -1071,12 +1072,8 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, break; } /* CC_EOT */ case MHI_EV_CC_OOB: case MHI_EV_CC_DB_MODE: { unsigned long flags; MHI_VERB("DB_MODE/OOB Detected chan %d.\n", mhi_chan->chan); mhi_chan->db_cfg.db_mode = 1; mhi_chan->db_cfg.db_mode = true; mhi_chan->mode_change++; /* * on RSC channel IPA HW has a minimum credit requirement before Loading @@ -1090,14 +1087,27 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl, ring_db = false; } read_lock_irqsave(&mhi_cntrl->pm_lock, flags); MHI_VERB("OOB_MODE chan %d ring_db %d\n", mhi_chan->chan, ring_db); read_lock_irqsave(&mhi_cntrl->pm_lock, rflags); if (tre_ring->wp != tre_ring->rp && MHI_DB_ACCESS_VALID(mhi_cntrl) && ring_db) { MHI_DB_ACCESS_VALID(mhi_cntrl) && ring_db) mhi_ring_chan_db(mhi_cntrl, mhi_chan); } read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); read_unlock_irqrestore(&mhi_cntrl->pm_lock, rflags); break; case MHI_EV_CC_DB_MODE: MHI_VERB("DB_MODE chan %d.\n", mhi_chan->chan); mhi_chan->db_cfg.db_mode = true; mhi_chan->mode_change++; read_lock_irqsave(&mhi_cntrl->pm_lock, rflags); if (tre_ring->wp != tre_ring->rp && MHI_DB_ACCESS_VALID(mhi_cntrl)) mhi_ring_chan_db(mhi_cntrl, mhi_chan); read_unlock_irqrestore(&mhi_cntrl->pm_lock, rflags); break; } case MHI_EV_CC_BAD_TRE: MHI_ASSERT(1, "Received BAD TRE event for ring"); break; Loading Loading @@ -1135,7 +1145,12 @@ static int parse_rsc_event(struct mhi_controller *mhi_cntrl, xfer_len = MHI_TRE_GET_EV_LEN(event); /* received out of bound cookie */ MHI_ASSERT(cookie >= buf_ring->len, "Invalid Cookie\n"); if (cookie >= buf_ring->len) { MHI_ERR("cookie 0x%08x bufring_len %zu", cookie, buf_ring->len); MHI_ERR("Processing Event:0x%llx 0x%08x 0x%08x\n", event->ptr, event->dword[0], event->dword[1]); panic("invalid cookie"); } buf_info = buf_ring->base + cookie; Loading Loading @@ -1385,6 +1400,10 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); chan = MHI_TRE_GET_EV_CHID(local_rp); if (chan >= mhi_cntrl->max_chan) { MHI_ERR("invalid channel id %u\n", chan); continue; } mhi_chan = &mhi_cntrl->mhi_chan[chan]; if (likely(type == MHI_PKT_TYPE_TX_EVENT)) { Loading Loading @@ -1680,14 +1699,18 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) MHI_VERB("Enter\n"); write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { write_unlock_irq(&mhi_cntrl->pm_lock); goto exit_intvec; } state = mhi_get_mhi_state(mhi_cntrl); ee = mhi_cntrl->ee; mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("device ee:%s dev_state:%s\n", MHI_LOG("local ee: %s device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_STATE_STR(state)); } if (state == MHI_STATE_SYS_ERR) { MHI_ERR("MHI system error detected\n"); Loading Loading @@ -2205,12 +2228,14 @@ int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d) chan_ctxt->pollcfg, chan_ctxt->chtype, chan_ctxt->erindex); seq_printf(m, " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n", " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx mode_change:0x%llx\n", chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->wp, mhi_to_physical(ring, ring->rp), mhi_to_physical(ring, ring->wp), mhi_chan->db_cfg.db_val); mhi_chan->db_cfg.db_val, mhi_chan->mode_change); mhi_chan->mode_change = 0; } } Loading
drivers/bus/mhi/core/mhi_pm.c +6 −0 Original line number Diff line number Diff line Loading @@ -1163,6 +1163,9 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) write_unlock_irq(&mhi_cntrl->pm_lock); MHI_LOG("Wait for M3 completion\n"); /* finish reg writes before D3 cold */ mhi_force_reg_write(mhi_cntrl); ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->dev_state == MHI_STATE_M3 || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), Loading Loading @@ -1274,6 +1277,9 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) mhi_cntrl->M3_FAST++; write_unlock_irq(&mhi_cntrl->pm_lock); /* finish reg writes before DRV hand-off to avoid noc err */ mhi_force_reg_write(mhi_cntrl); /* now safe to check ctrl event ring */ tasklet_enable(&mhi_cntrl->mhi_event->task); mhi_msi_handlr(0, mhi_cntrl->mhi_event); Loading
drivers/bus/mhi/devices/mhi_netdev.c +9 −2 Original line number Diff line number Diff line /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -120,6 +120,7 @@ struct mhi_netdev { /* debug stats */ u32 abuffers, kbuffers, rbuffers; bool napi_scheduled; }; struct mhi_netdev_priv { Loading Loading @@ -458,6 +459,7 @@ static int mhi_netdev_alloc_thread(void *data) /* replenish the ring */ napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; /* wait for buffers to run low or thread to stop */ wait_event_interruptible(mhi_netdev->alloc_event, Loading Loading @@ -497,6 +499,7 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget) if (rx_work < 0) { MSG_ERR("Error polling ret:%d\n", rx_work); napi_complete(napi); mhi_netdev->napi_scheduled = false; return 0; } Loading @@ -507,8 +510,10 @@ static int mhi_netdev_poll(struct napi_struct *napi, int budget) mhi_netdev_queue(mhi_netdev, rsc_dev->mhi_dev); /* complete work if # of packet processed less than allocated budget */ if (rx_work < budget) if (rx_work < budget) { napi_complete(napi); mhi_netdev->napi_scheduled = false; } MSG_VERB("polled %d pkts\n", rx_work); Loading Loading @@ -844,6 +849,7 @@ static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) return; napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; } #ifdef CONFIG_DEBUG_FS Loading Loading @@ -1104,6 +1110,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev, * by triggering a napi_poll */ napi_schedule(mhi_netdev->napi); mhi_netdev->napi_scheduled = true; return 0; } Loading