Loading drivers/platform/msm/mhi_dev/mhi.c +116 −61 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ static void mhi_dev_cmd_event_msi_cb(void *req); static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi); static int mhi_dev_ring_init(struct mhi_dev *dev); static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; static DECLARE_COMPLETION(read_from_host); Loading Loading @@ -1348,13 +1349,7 @@ static int mhi_enable_int(void) int rc = 0; mhi_log(MHI_MSG_VERBOSE, "Enable chdb, ctrl and cmdb interrupts\n"); rc = mhi_dev_mmio_enable_chdb_interrupts(mhi_ctx); if (rc) { pr_err("Failed to enable channel db: %d\n", rc); return rc; } "Enable ctrl and cmdb interrupts\n"); rc = mhi_dev_mmio_enable_ctrl_interrupt(mhi_ctx); if (rc) { Loading Loading @@ -1839,6 +1834,18 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) struct mhi_dev_channel *ch; struct mhi_addr host_addr; rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_id); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Failed to disable chdb for ch %d\n", ch_id); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_VERBOSE, "Error with compl event\n"); return; } ch = &mhi->ch[ch_id]; /* hard stop and set the channel to stop */ mhi->ch_ctx_cache[ch_id].ch_state = Loading Loading @@ -1871,7 +1878,7 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) ch->reset_pending = false; } static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { int rc = 0; Loading @@ -1888,7 +1895,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, switch (el->generic.type) { case MHI_DEV_RING_EL_START: mhi_log(MHI_MSG_VERBOSE, "recived start cmd for channel %d\n", mhi_log(MHI_MSG_VERBOSE, "received start cmd for channel %d\n", ch_id); if (ch_id >= (HW_CHANNEL_BASE)) { rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type); Loading @@ -1900,9 +1907,22 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; return rc; } goto send_start_completion_event; } else { rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Failed to enable chdb for ch %d\n", ch_id); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_VERBOSE, "Error with compl event\n"); return rc; } } /* fetch the channel context from host */ Loading @@ -1920,7 +1940,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; return rc; } mhi->ring[mhi->ch_ring_start + ch_id].state = Loading @@ -1933,18 +1953,6 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi->ch[ch_id].ring = &mhi->ring[mhi->ch_ring_start + ch_id]; mhi->ch[ch_id].ch_type = mhi->ch_ctx_cache[ch_id].ch_type; /* enable DB for event ring */ rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); if (rc) { pr_err("Failed to enable channel db\n"); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; } if (mhi->use_edma || mhi->use_ipa) { uint32_t evnt_ring_idx = mhi->ev_ring_start + mhi->ch_ctx_cache[ch_id].err_indx; Loading @@ -1958,7 +1966,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_ERROR, "error starting event ring %d\n", mhi->ch_ctx_cache[ch_id].err_indx); return; return rc; } } mutex_lock(&mhi->ch[ch_id].ch_lock); Loading Loading @@ -2013,7 +2021,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); return; return rc; } } else { /* Loading @@ -2026,7 +2034,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); return; return -EINVAL; } ch = &mhi->ch[ch_id]; Loading Loading @@ -2075,7 +2083,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); return; return rc; } } else { Loading @@ -2086,7 +2094,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); return; return -EINVAL; } ch = &mhi->ch[ch_id]; mutex_lock(&ch->ch_lock); Loading @@ -2098,7 +2106,8 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ch->reset_pending = true; mutex_unlock(&ch->ring->event_lock); mutex_unlock(&ch->ch_lock); return; rc = -EBUSY; return rc; } mhi_dev_process_reset_cmd(mhi, ch_id); mutex_unlock(&ch->ring->event_lock); Loading @@ -2113,9 +2122,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("%s: Invalid command:%d\n", __func__, el->generic.type); break; } return rc; } static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, static int mhi_dev_process_tre_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { struct mhi_dev_ring *ring = (struct mhi_dev_ring *)ctx; Loading @@ -2126,7 +2136,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_VERBOSE, "invalid channel ring id (%d), should be < %lu\n", ring->id, mhi->ch_ring_start); return; return -EINVAL; } ch = &mhi->ch[ring->id - mhi->ch_ring_start]; Loading @@ -2140,6 +2150,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, */ if (ch->active_client && ch->active_client->event_trigger != NULL) ch->active_client->event_trigger(&reason); return 0; } static void mhi_dev_process_ring_pending(struct work_struct *work) Loading @@ -2154,7 +2165,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_lock(&mhi_ctx->mhi_lock); rc = mhi_dev_process_ring(&mhi->ring[mhi->cmd_ring_idx]); if (rc) { if (rc && rc != -EBUSY) { mhi_log(MHI_MSG_ERROR, "error processing command ring\n"); goto exit; } Loading @@ -2180,6 +2191,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) } mutex_lock(&ch->ch_lock); ch->db_pending = false; mutex_unlock(&ch->ch_lock); if (ch->reset_pending) { /* Loading @@ -2190,9 +2202,13 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) ch_id = ch->ch_id; mhi_log(MHI_MSG_VERBOSE, "processing pending ch:%d reset\n", ch_id); mutex_lock(&ch->ring->event_lock); mhi_dev_process_reset_cmd(mhi, ch_id); mutex_unlock(&ch->ring->event_lock); rc = mhi_dev_process_ring( &mhi->ring[mhi->cmd_ring_idx]); if (rc) { mhi_log(MHI_MSG_ERROR, "error processing command ring\n"); goto exit; } } rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch->ch_id); Loading @@ -2202,7 +2218,6 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_unlock(&ch->ch_lock); goto exit; } mutex_unlock(&ch->ch_lock); } exit: Loading Loading @@ -2235,11 +2250,12 @@ static int mhi_dev_get_event_notify(enum mhi_dev_state state, return rc; } static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, static bool mhi_dev_queue_channel_db(struct mhi_dev *mhi, uint32_t chintr_value, uint32_t ch_num) { struct mhi_dev_ring *ring; struct mhi_dev_channel *ch; bool work_pending = false; int rc = 0; for (; chintr_value; ch_num++, chintr_value >>= 1) { Loading @@ -2254,14 +2270,16 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, ch = &mhi->ch[ch_num]; mutex_lock(&ch->ch_lock); ch->db_pending = true; work_pending = true; mutex_unlock(&ch->ch_lock); rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_num); if (rc) { pr_err("Error disabling chdb\n"); return; return work_pending; } } } return work_pending; } /* Loading Loading @@ -2290,11 +2308,11 @@ static bool mhi_dev_check_channel_interrupt(struct mhi_dev *mhi) /* Process channel status whose mask is enabled */ chintr_value = (mhi->chdb[i].status & mhi->chdb[i].mask); if (chintr_value) { pending_work = true; mhi_log(MHI_MSG_VERBOSE, "processing id: %d, ch interrupt 0x%x\n", i, chintr_value); mhi_dev_queue_channel_db(mhi, chintr_value, ch_num); pending_work |= mhi_dev_queue_channel_db(mhi, chintr_value, ch_num); rc = mhi_dev_mmio_write(mhi, MHI_CHDB_INT_CLEAR_A7_n(i), mhi->chdb[i].status); if (rc) { Loading Loading @@ -2685,6 +2703,25 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->cfg.event_rings; mhi->ch_ctx_shadow.size = sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels; /* Allocate ring elements, during M0 when host * would have updated MHICFG register */ if (!mhi->ring) { mhi->ring = devm_kcalloc(&pdev->dev, (mhi->cfg.channels + mhi->cfg.event_rings+1), sizeof(struct mhi_dev_ring), GFP_KERNEL); if (!mhi->ring) { rc = -ENOMEM; goto exit; } mhi_log(MHI_MSG_INFO, "MEM_ALLOC: size:%d RING_ALLOC\n", (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1))); } /* * This func mhi_dev_cache_host_cfg will be called when * processing mhi device reset as well, do not allocate Loading Loading @@ -2731,6 +2768,13 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) } memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels); rc = mhi_dev_ring_init(mhi); if (rc) { mhi_log(MHI_MSG_VERBOSE, "MHI dev ring init failed\n"); goto exit; } if (MHI_USE_DMA(mhi)) { data_transfer.phy_addr = mhi->cmd_ctx_cache_dma_handle; data_transfer.host_pa = mhi->cmd_ctx_shadow.host_pa; Loading Loading @@ -2761,21 +2805,43 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->ev_ctx_cache->rp, mhi->ev_ctx_cache->wp); return mhi_ring_start(&mhi->ring[0], rc = mhi_ring_start(&mhi->ring[0], (union mhi_dev_ring_ctx *)mhi->cmd_ctx_cache, mhi); if (rc) { pr_err("MHI ring start failed:%d\n", rc); goto exit; } return 0; exit: if (mhi->cmd_ctx_cache) if (mhi->ring) { devm_kfree(&pdev->dev, mhi->ring); mhi->ring = NULL; mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d RING_ALLOC\n", (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1))); } if (mhi->cmd_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_cmd_ctx), mhi->cmd_ctx_cache, mhi->cmd_ctx_cache_dma_handle); if (mhi->ev_ctx_cache) mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d CMD_CTX_CACHE\n", sizeof(struct mhi_dev_cmd_ctx)); } if (mhi->ev_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings, mhi->ev_ctx_cache, mhi->ev_ctx_cache_dma_handle); mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d EV_CTX_CACHE\n", sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings); } return rc; } Loading Loading @@ -2926,8 +2992,8 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) sizeof(*cmd_ctx->ereqs), GFP_KERNEL); if (!cmd_ctx->ereqs) { rc = -ENOMEM; goto free_ereqs; return -ENOMEM; } /* Allocate buffers to queue transfer completion events */ Loading Loading @@ -2956,9 +3022,13 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) return 0; free_ereqs: kfree(mhi->cmd_ctx); kfree(cmd_ctx->ereqs); cmd_ctx->ereqs = NULL; kfree(mhi->cmd_ctx); mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d CMD_CTX\n", sizeof(struct mhi_cmd_cmpl_ctx)); mhi->cmd_ctx = NULL; return rc; } Loading Loading @@ -3675,13 +3745,6 @@ static void mhi_dev_enable(struct work_struct *work) } } rc = mhi_dev_ring_init(mhi); if (rc) { pr_err("MHI dev ring init failed\n"); return; } rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); Loading Loading @@ -3995,14 +4058,6 @@ static int mhi_init(struct mhi_dev *mhi) return rc; } if (!mhi->ring) mhi->ring = devm_kzalloc(&pdev->dev, (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1)), GFP_KERNEL); if (!mhi->ring) return -ENOMEM; /* * mhi_init is also called during device reset, in * which case channel mem will already be allocated. Loading drivers/platform/msm/mhi_dev/mhi.h +2 −2 Original line number Diff line number Diff line Loading @@ -407,7 +407,7 @@ struct mhi_dev_ring { /* ring_ctx_shadow -> tracking ring_ctx in the host */ union mhi_dev_ring_ctx *ring_ctx_shadow; struct msi_buf_cb_data msi_buffer; void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx); }; Loading Loading @@ -775,7 +775,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, * @ring_cb: callback function. */ void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)); /** Loading drivers/platform/msm/mhi_dev/mhi_mmio.c +23 −4 Original line number Diff line number Diff line Loading @@ -601,13 +601,18 @@ EXPORT_SYMBOL(mhi_dev_mmio_reset); int mhi_dev_restore_mmio(struct mhi_dev *dev) { int rc = 0; uint32_t i, reg_cntl_value; void *reg_cntl_addr; if (WARN_ON(!dev)) return -EINVAL; mhi_dev_mmio_mask_interrupts(dev); mhi_dev_mmio_disable_ctrl_interrupt(dev); mhi_dev_mmio_disable_cmdb_interrupt(dev); mhi_dev_mmio_mask_erdb_interrupts(dev); for (i = 0; i < (MHI_DEV_MMIO_RANGE/4); i++) { reg_cntl_addr = dev->mmio_base_addr + Loading @@ -618,12 +623,26 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) mhi_dev_mmio_clear_interrupts(dev); for (i = 0; i < MHI_MASK_ROWS_CH_EV_DB; i++) { /* Enable channel interrupt whose mask is enabled */ if (dev->chdb[i].mask) { mhi_log(MHI_MSG_VERBOSE, "Enabling id: %d, chdb mask 0x%x\n", i, dev->chdb[i].mask); rc = mhi_dev_mmio_write(dev, MHI_CHDB_INT_MASK_A7_n(i), dev->chdb[i].mask); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Error writing enable for A7\n"); return rc; } } } /* Mask and enable control interrupt */ mhi_dev_mmio_enable_ctrl_interrupt(dev); /*Enable chdb interrupt*/ mhi_dev_mmio_enable_chdb_interrupts(dev); /*Enable cmdb interrupt*/ mhi_dev_mmio_enable_cmdb_interrupt(dev); Loading drivers/platform/msm/mhi_dev/mhi_ring.c +2 −2 Original line number Diff line number Diff line Loading @@ -197,7 +197,7 @@ int mhi_dev_process_ring_element(struct mhi_dev_ring *ring, size_t offset) el->tre.len, offset); if (ring->ring_cb) ring->ring_cb(ring->mhi_dev, el, (void *)ring); return ring->ring_cb(ring->mhi_dev, el, (void *)ring); else mhi_log(MHI_MSG_ERROR, "No callback registered for ring %d\n", ring->id); Loading Loading @@ -557,7 +557,7 @@ void mhi_ring_init(struct mhi_dev_ring *ring, enum mhi_dev_ring_type type, EXPORT_SYMBOL(mhi_ring_init); void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)) { if (WARN_ON(!ring || !ring_cb)) Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +116 −61 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ static void mhi_dev_cmd_event_msi_cb(void *req); static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi); static int mhi_dev_ring_init(struct mhi_dev *dev); static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; static DECLARE_COMPLETION(read_from_host); Loading Loading @@ -1348,13 +1349,7 @@ static int mhi_enable_int(void) int rc = 0; mhi_log(MHI_MSG_VERBOSE, "Enable chdb, ctrl and cmdb interrupts\n"); rc = mhi_dev_mmio_enable_chdb_interrupts(mhi_ctx); if (rc) { pr_err("Failed to enable channel db: %d\n", rc); return rc; } "Enable ctrl and cmdb interrupts\n"); rc = mhi_dev_mmio_enable_ctrl_interrupt(mhi_ctx); if (rc) { Loading Loading @@ -1839,6 +1834,18 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) struct mhi_dev_channel *ch; struct mhi_addr host_addr; rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_id); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Failed to disable chdb for ch %d\n", ch_id); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_VERBOSE, "Error with compl event\n"); return; } ch = &mhi->ch[ch_id]; /* hard stop and set the channel to stop */ mhi->ch_ctx_cache[ch_id].ch_state = Loading Loading @@ -1871,7 +1878,7 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) ch->reset_pending = false; } static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { int rc = 0; Loading @@ -1888,7 +1895,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, switch (el->generic.type) { case MHI_DEV_RING_EL_START: mhi_log(MHI_MSG_VERBOSE, "recived start cmd for channel %d\n", mhi_log(MHI_MSG_VERBOSE, "received start cmd for channel %d\n", ch_id); if (ch_id >= (HW_CHANNEL_BASE)) { rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type); Loading @@ -1900,9 +1907,22 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; return rc; } goto send_start_completion_event; } else { rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Failed to enable chdb for ch %d\n", ch_id); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_VERBOSE, "Error with compl event\n"); return rc; } } /* fetch the channel context from host */ Loading @@ -1920,7 +1940,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; return rc; } mhi->ring[mhi->ch_ring_start + ch_id].state = Loading @@ -1933,18 +1953,6 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi->ch[ch_id].ring = &mhi->ring[mhi->ch_ring_start + ch_id]; mhi->ch[ch_id].ch_type = mhi->ch_ctx_cache[ch_id].ch_type; /* enable DB for event ring */ rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); if (rc) { pr_err("Failed to enable channel db\n"); rc = mhi_dev_send_cmd_comp_event(mhi, MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return; } if (mhi->use_edma || mhi->use_ipa) { uint32_t evnt_ring_idx = mhi->ev_ring_start + mhi->ch_ctx_cache[ch_id].err_indx; Loading @@ -1958,7 +1966,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_ERROR, "error starting event ring %d\n", mhi->ch_ctx_cache[ch_id].err_indx); return; return rc; } } mutex_lock(&mhi->ch[ch_id].ch_lock); Loading Loading @@ -2013,7 +2021,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); return; return rc; } } else { /* Loading @@ -2026,7 +2034,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); return; return -EINVAL; } ch = &mhi->ch[ch_id]; Loading Loading @@ -2075,7 +2083,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); return; return rc; } } else { Loading @@ -2086,7 +2094,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); return; return -EINVAL; } ch = &mhi->ch[ch_id]; mutex_lock(&ch->ch_lock); Loading @@ -2098,7 +2106,8 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, ch->reset_pending = true; mutex_unlock(&ch->ring->event_lock); mutex_unlock(&ch->ch_lock); return; rc = -EBUSY; return rc; } mhi_dev_process_reset_cmd(mhi, ch_id); mutex_unlock(&ch->ring->event_lock); Loading @@ -2113,9 +2122,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("%s: Invalid command:%d\n", __func__, el->generic.type); break; } return rc; } static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, static int mhi_dev_process_tre_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { struct mhi_dev_ring *ring = (struct mhi_dev_ring *)ctx; Loading @@ -2126,7 +2136,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_VERBOSE, "invalid channel ring id (%d), should be < %lu\n", ring->id, mhi->ch_ring_start); return; return -EINVAL; } ch = &mhi->ch[ring->id - mhi->ch_ring_start]; Loading @@ -2140,6 +2150,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, */ if (ch->active_client && ch->active_client->event_trigger != NULL) ch->active_client->event_trigger(&reason); return 0; } static void mhi_dev_process_ring_pending(struct work_struct *work) Loading @@ -2154,7 +2165,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_lock(&mhi_ctx->mhi_lock); rc = mhi_dev_process_ring(&mhi->ring[mhi->cmd_ring_idx]); if (rc) { if (rc && rc != -EBUSY) { mhi_log(MHI_MSG_ERROR, "error processing command ring\n"); goto exit; } Loading @@ -2180,6 +2191,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) } mutex_lock(&ch->ch_lock); ch->db_pending = false; mutex_unlock(&ch->ch_lock); if (ch->reset_pending) { /* Loading @@ -2190,9 +2202,13 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) ch_id = ch->ch_id; mhi_log(MHI_MSG_VERBOSE, "processing pending ch:%d reset\n", ch_id); mutex_lock(&ch->ring->event_lock); mhi_dev_process_reset_cmd(mhi, ch_id); mutex_unlock(&ch->ring->event_lock); rc = mhi_dev_process_ring( &mhi->ring[mhi->cmd_ring_idx]); if (rc) { mhi_log(MHI_MSG_ERROR, "error processing command ring\n"); goto exit; } } rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch->ch_id); Loading @@ -2202,7 +2218,6 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_unlock(&ch->ch_lock); goto exit; } mutex_unlock(&ch->ch_lock); } exit: Loading Loading @@ -2235,11 +2250,12 @@ static int mhi_dev_get_event_notify(enum mhi_dev_state state, return rc; } static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, static bool mhi_dev_queue_channel_db(struct mhi_dev *mhi, uint32_t chintr_value, uint32_t ch_num) { struct mhi_dev_ring *ring; struct mhi_dev_channel *ch; bool work_pending = false; int rc = 0; for (; chintr_value; ch_num++, chintr_value >>= 1) { Loading @@ -2254,14 +2270,16 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, ch = &mhi->ch[ch_num]; mutex_lock(&ch->ch_lock); ch->db_pending = true; work_pending = true; mutex_unlock(&ch->ch_lock); rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_num); if (rc) { pr_err("Error disabling chdb\n"); return; return work_pending; } } } return work_pending; } /* Loading Loading @@ -2290,11 +2308,11 @@ static bool mhi_dev_check_channel_interrupt(struct mhi_dev *mhi) /* Process channel status whose mask is enabled */ chintr_value = (mhi->chdb[i].status & mhi->chdb[i].mask); if (chintr_value) { pending_work = true; mhi_log(MHI_MSG_VERBOSE, "processing id: %d, ch interrupt 0x%x\n", i, chintr_value); mhi_dev_queue_channel_db(mhi, chintr_value, ch_num); pending_work |= mhi_dev_queue_channel_db(mhi, chintr_value, ch_num); rc = mhi_dev_mmio_write(mhi, MHI_CHDB_INT_CLEAR_A7_n(i), mhi->chdb[i].status); if (rc) { Loading Loading @@ -2685,6 +2703,25 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->cfg.event_rings; mhi->ch_ctx_shadow.size = sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels; /* Allocate ring elements, during M0 when host * would have updated MHICFG register */ if (!mhi->ring) { mhi->ring = devm_kcalloc(&pdev->dev, (mhi->cfg.channels + mhi->cfg.event_rings+1), sizeof(struct mhi_dev_ring), GFP_KERNEL); if (!mhi->ring) { rc = -ENOMEM; goto exit; } mhi_log(MHI_MSG_INFO, "MEM_ALLOC: size:%d RING_ALLOC\n", (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1))); } /* * This func mhi_dev_cache_host_cfg will be called when * processing mhi device reset as well, do not allocate Loading Loading @@ -2731,6 +2768,13 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) } memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels); rc = mhi_dev_ring_init(mhi); if (rc) { mhi_log(MHI_MSG_VERBOSE, "MHI dev ring init failed\n"); goto exit; } if (MHI_USE_DMA(mhi)) { data_transfer.phy_addr = mhi->cmd_ctx_cache_dma_handle; data_transfer.host_pa = mhi->cmd_ctx_shadow.host_pa; Loading Loading @@ -2761,21 +2805,43 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->ev_ctx_cache->rp, mhi->ev_ctx_cache->wp); return mhi_ring_start(&mhi->ring[0], rc = mhi_ring_start(&mhi->ring[0], (union mhi_dev_ring_ctx *)mhi->cmd_ctx_cache, mhi); if (rc) { pr_err("MHI ring start failed:%d\n", rc); goto exit; } return 0; exit: if (mhi->cmd_ctx_cache) if (mhi->ring) { devm_kfree(&pdev->dev, mhi->ring); mhi->ring = NULL; mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d RING_ALLOC\n", (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1))); } if (mhi->cmd_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_cmd_ctx), mhi->cmd_ctx_cache, mhi->cmd_ctx_cache_dma_handle); if (mhi->ev_ctx_cache) mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d CMD_CTX_CACHE\n", sizeof(struct mhi_dev_cmd_ctx)); } if (mhi->ev_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings, mhi->ev_ctx_cache, mhi->ev_ctx_cache_dma_handle); mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d EV_CTX_CACHE\n", sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings); } return rc; } Loading Loading @@ -2926,8 +2992,8 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) sizeof(*cmd_ctx->ereqs), GFP_KERNEL); if (!cmd_ctx->ereqs) { rc = -ENOMEM; goto free_ereqs; return -ENOMEM; } /* Allocate buffers to queue transfer completion events */ Loading Loading @@ -2956,9 +3022,13 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) return 0; free_ereqs: kfree(mhi->cmd_ctx); kfree(cmd_ctx->ereqs); cmd_ctx->ereqs = NULL; kfree(mhi->cmd_ctx); mhi_log(MHI_MSG_INFO, "MEM_DEALLOC: size:%d CMD_CTX\n", sizeof(struct mhi_cmd_cmpl_ctx)); mhi->cmd_ctx = NULL; return rc; } Loading Loading @@ -3675,13 +3745,6 @@ static void mhi_dev_enable(struct work_struct *work) } } rc = mhi_dev_ring_init(mhi); if (rc) { pr_err("MHI dev ring init failed\n"); return; } rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); Loading Loading @@ -3995,14 +4058,6 @@ static int mhi_init(struct mhi_dev *mhi) return rc; } if (!mhi->ring) mhi->ring = devm_kzalloc(&pdev->dev, (sizeof(struct mhi_dev_ring) * (mhi->cfg.channels + mhi->cfg.event_rings + 1)), GFP_KERNEL); if (!mhi->ring) return -ENOMEM; /* * mhi_init is also called during device reset, in * which case channel mem will already be allocated. Loading
drivers/platform/msm/mhi_dev/mhi.h +2 −2 Original line number Diff line number Diff line Loading @@ -407,7 +407,7 @@ struct mhi_dev_ring { /* ring_ctx_shadow -> tracking ring_ctx in the host */ union mhi_dev_ring_ctx *ring_ctx_shadow; struct msi_buf_cb_data msi_buffer; void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx); }; Loading Loading @@ -775,7 +775,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, * @ring_cb: callback function. */ void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)); /** Loading
drivers/platform/msm/mhi_dev/mhi_mmio.c +23 −4 Original line number Diff line number Diff line Loading @@ -601,13 +601,18 @@ EXPORT_SYMBOL(mhi_dev_mmio_reset); int mhi_dev_restore_mmio(struct mhi_dev *dev) { int rc = 0; uint32_t i, reg_cntl_value; void *reg_cntl_addr; if (WARN_ON(!dev)) return -EINVAL; mhi_dev_mmio_mask_interrupts(dev); mhi_dev_mmio_disable_ctrl_interrupt(dev); mhi_dev_mmio_disable_cmdb_interrupt(dev); mhi_dev_mmio_mask_erdb_interrupts(dev); for (i = 0; i < (MHI_DEV_MMIO_RANGE/4); i++) { reg_cntl_addr = dev->mmio_base_addr + Loading @@ -618,12 +623,26 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) mhi_dev_mmio_clear_interrupts(dev); for (i = 0; i < MHI_MASK_ROWS_CH_EV_DB; i++) { /* Enable channel interrupt whose mask is enabled */ if (dev->chdb[i].mask) { mhi_log(MHI_MSG_VERBOSE, "Enabling id: %d, chdb mask 0x%x\n", i, dev->chdb[i].mask); rc = mhi_dev_mmio_write(dev, MHI_CHDB_INT_MASK_A7_n(i), dev->chdb[i].mask); if (rc) { mhi_log(MHI_MSG_VERBOSE, "Error writing enable for A7\n"); return rc; } } } /* Mask and enable control interrupt */ mhi_dev_mmio_enable_ctrl_interrupt(dev); /*Enable chdb interrupt*/ mhi_dev_mmio_enable_chdb_interrupts(dev); /*Enable cmdb interrupt*/ mhi_dev_mmio_enable_cmdb_interrupt(dev); Loading
drivers/platform/msm/mhi_dev/mhi_ring.c +2 −2 Original line number Diff line number Diff line Loading @@ -197,7 +197,7 @@ int mhi_dev_process_ring_element(struct mhi_dev_ring *ring, size_t offset) el->tre.len, offset); if (ring->ring_cb) ring->ring_cb(ring->mhi_dev, el, (void *)ring); return ring->ring_cb(ring->mhi_dev, el, (void *)ring); else mhi_log(MHI_MSG_ERROR, "No callback registered for ring %d\n", ring->id); Loading Loading @@ -557,7 +557,7 @@ void mhi_ring_init(struct mhi_dev_ring *ring, enum mhi_dev_ring_type type, EXPORT_SYMBOL(mhi_ring_init); void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)) { if (WARN_ON(!ring || !ring_cb)) Loading