Loading drivers/platform/msm/mhi/mhi.h +2 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,7 @@ enum MHI_PKT_TYPE { MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, MHI_PKT_TYPE_TX_EVENT = 0x22, MHI_PKT_TYPE_EE_EVENT = 0x40, MHI_PKT_TYPE_STALE_EVENT, /* Internal event */ MHI_PKT_TYPE_SYS_ERR_EVENT = 0xFF, }; Loading Loading @@ -310,6 +311,7 @@ struct mhi_ring { uintptr_t el_size; u32 overwrite_en; enum MHI_CHAN_DIR dir; enum MHI_CHAN_STATE ch_state; struct db_mode db_mode; u32 msi_disable_cntr; u32 msi_enable_cntr; Loading drivers/platform/msm/mhi/mhi_event.c +3 −0 Original line number Diff line number Diff line Loading @@ -122,9 +122,11 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) { struct mhi_ring *event_ctxt = NULL; u64 db_value = 0; unsigned long flags; event_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[event_ring_index]; spin_lock_irqsave(&event_ctxt->ring_lock, flags); db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, event_ring_index, (uintptr_t) event_ctxt->wp); Loading @@ -132,6 +134,7 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) mhi_dev_ctxt->mmio_info.event_db_addr, event_ring_index, db_value); spin_unlock_irqrestore(&event_ctxt->ring_lock, flags); } static int mhi_event_ring_init(struct mhi_event_ctxt *ev_list, Loading drivers/platform/msm/mhi/mhi_init.c +1 −0 Original line number Diff line number Diff line Loading @@ -594,6 +594,7 @@ int mhi_init_chan_ctxt(struct mhi_chan_ctxt *cc_list, ring->el_size = sizeof(struct mhi_tx_pkt); ring->overwrite_en = 0; ring->dir = chan_type; ring->ch_state = MHI_CHAN_STATE_DISABLED; ring->db_mode.db_mode = 1; ring->db_mode.preserve_db_state = (preserve_db_state) ? 1 : 0; ring->db_mode.brstmode = brstmode; Loading drivers/platform/msm/mhi/mhi_isr.c +31 −6 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ static int mhi_process_event_ring( union mhi_event_pkt event_to_process; int ret_val = 0; struct mhi_event_ctxt *ev_ctxt = NULL; unsigned long flags; struct mhi_ring *local_ev_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[ev_index]; Loading @@ -38,6 +39,7 @@ static int mhi_process_event_ring( read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); ev_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[ev_index]; spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, Loading @@ -45,19 +47,19 @@ static int mhi_process_event_ring( ev_ctxt->mhi_event_read_ptr); local_rp = (union mhi_event_pkt *)local_ev_ctxt->rp; spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); BUG_ON(validate_ev_el_addr(local_ev_ctxt, (uintptr_t)device_rp)); while ((local_rp != device_rp) && (event_quota > 0) && (device_rp != NULL) && (local_rp != NULL)) { spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); event_to_process = *local_rp; read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); recycle_trb_and_ring(mhi_dev_ctxt, local_ev_ctxt, MHI_RING_TYPE_EVENT_RING, ev_index); read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); switch (MHI_TRB_READ_INFO(EV_TRB_TYPE, &event_to_process)) { case MHI_PKT_TYPE_CMD_COMPLETION_EVENT: Loading Loading @@ -93,12 +95,28 @@ static int mhi_process_event_ring( break; } case MHI_PKT_TYPE_TX_EVENT: { u32 chan; struct mhi_ring *ring; __pm_stay_awake(&mhi_dev_ctxt->w_lock); chan = MHI_EV_READ_CHID(EV_CHID, &event_to_process); if (unlikely(!VALID_CHAN_NR(chan))) { mhi_log(MHI_MSG_ERROR, "Invalid chan:%d\n", chan); break; } ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; spin_lock_bh(&ring->ring_lock); if (ring->ch_state == MHI_CHAN_STATE_ENABLED) parse_xfer_event(mhi_dev_ctxt, &event_to_process, ev_index); spin_unlock_bh(&ring->ring_lock); __pm_relax(&mhi_dev_ctxt->w_lock); break; } case MHI_PKT_TYPE_STATE_CHANGE_EVENT: { enum STATE_TRANSITION new_state; Loading Loading @@ -153,6 +171,11 @@ static int mhi_process_event_ring( } break; } case MHI_PKT_TYPE_STALE_EVENT: mhi_log(MHI_MSG_INFO, "Stale Event received for chan:%u\n", MHI_EV_READ_CHID(EV_CHID, local_rp)); break; case MHI_PKT_TYPE_SYS_ERR_EVENT: mhi_log(MHI_MSG_INFO, "MHI System Error Detected. Triggering Reset\n"); Loading @@ -165,12 +188,14 @@ static int mhi_process_event_ring( &event_to_process)); break; } spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); local_rp = (union mhi_event_pkt *)local_ev_ctxt->rp; device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, ev_index, ev_ctxt->mhi_event_read_ptr); spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); ret_val = 0; --event_quota; } Loading drivers/platform/msm/mhi/mhi_main.c +59 −44 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) { int ret_val = 0; struct mhi_device_ctxt *mhi_dev_ctxt; struct mhi_ring *chan_ring; int chan; struct mhi_chan_cfg *cfg; struct mhi_cmd_complete_event_pkt cmd_event_pkt; Loading @@ -295,6 +296,7 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) chan = client_handle->chan_info.chan_nr; cfg = &mhi_dev_ctxt->mhi_chan_cfg[chan]; chan_ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mutex_lock(&cfg->chan_lock); mhi_log(MHI_MSG_INFO, "Entered: Client opening chan 0x%x\n", chan); Loading Loading @@ -352,6 +354,9 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev); spin_lock_irq(&chan_ring->ring_lock); chan_ring->ch_state = MHI_CHAN_STATE_ENABLED; spin_unlock_irq(&chan_ring->ring_lock); ret_val = mhi_send_cmd(client_handle->mhi_dev_ctxt, MHI_COMMAND_START_CHAN, chan); Loading Loading @@ -462,6 +467,7 @@ void mhi_close_channel(struct mhi_client_handle *client_handle) struct mhi_device_ctxt *mhi_dev_ctxt; struct mhi_cmd_complete_event_pkt cmd_event_pkt; union mhi_cmd_pkt cmd_pkt; struct mhi_ring *chan_ring; enum MHI_EVENT_CCS ev_code; if (!client_handle || Loading @@ -474,7 +480,13 @@ void mhi_close_channel(struct mhi_client_handle *client_handle) cfg = &mhi_dev_ctxt->mhi_chan_cfg[chan]; mhi_log(MHI_MSG_INFO, "Client attempting to close chan 0x%x\n", chan); chan_ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mutex_lock(&cfg->chan_lock); /* No more processing events for this channel */ spin_lock_irq(&chan_ring->ring_lock); chan_ring->ch_state = MHI_CHAN_STATE_DISABLED; spin_unlock_irq(&chan_ring->ring_lock); init_completion(&cfg->cmd_complete); read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); WARN_ON(mhi_dev_ctxt->mhi_pm_state == MHI_PM_DISABLE); Loading Loading @@ -829,8 +841,6 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, enum MHI_COMMAND cmd, u32 chan) { union mhi_cmd_pkt *cmd_pkt = NULL; enum MHI_CHAN_STATE from_state = MHI_CHAN_STATE_DISABLED; enum MHI_CHAN_STATE to_state = MHI_CHAN_STATE_DISABLED; enum MHI_PKT_TYPE ring_el_type = MHI_PKT_TYPE_NOOP_CMD; int ret_val = 0; unsigned long flags, flags2; Loading @@ -849,33 +859,17 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), mhi_dev_ctxt->dev_exec_env, chan, cmd); from_state = mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan].chstate; switch (cmd) { break; case MHI_COMMAND_RESET_CHAN: to_state = MHI_CHAN_STATE_DISABLED; ring_el_type = MHI_PKT_TYPE_RESET_CHAN_CMD; break; case MHI_COMMAND_START_CHAN: switch (from_state) { case MHI_CHAN_STATE_DISABLED: case MHI_CHAN_STATE_ENABLED: case MHI_CHAN_STATE_STOP: to_state = MHI_CHAN_STATE_RUNNING; break; default: mhi_log(MHI_MSG_ERROR, "Invalid stt cmd 0x%x, from_state 0x%x\n", cmd, from_state); ret_val = -EPERM; goto error_invalid; } ring_el_type = MHI_PKT_TYPE_START_CHAN_CMD; break; default: mhi_log(MHI_MSG_ERROR, "Bad command received\n"); return -EINVAL; } spin_lock_irqsave(&mhi_ring->ring_lock, flags); Loading @@ -897,7 +891,7 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, "Sent command 0x%x for chan %d\n", cmd, chan); error_invalid: mhi_log(MHI_MSG_INFO, "Exited ret %d.\n", ret_val); return ret_val; } Loading Loading @@ -1120,13 +1114,11 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, u32 nr_trb_to_parse; u32 i = 0; u32 ev_code; struct mhi_ring *local_chan_ctxt; trace_mhi_ev(event); chan = MHI_EV_READ_CHID(EV_CHID, event); if (unlikely(!VALID_CHAN_NR(chan))) { mhi_log(MHI_MSG_ERROR, "Bad ring id.\n"); return -EINVAL; } local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; ev_code = MHI_EV_READ_CODE(EV_TRB_CODE, event); client_handle = mhi_dev_ctxt->client_handle_list[chan]; client_handle->pkt_count++; Loading @@ -1147,10 +1139,7 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, dma_addr_t trb_data_loc; u32 ieot_flag; int ret_val; struct mhi_ring *local_chan_ctxt; local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; phy_ev_trb_loc = MHI_EV_READ_PTR(EV_PTR, event); chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan]; Loading Loading @@ -1217,29 +1206,22 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, case MHI_EVENT_CC_OOB: case MHI_EVENT_CC_DB_MODE: { struct mhi_ring *chan_ctxt = NULL; u64 db_value = 0; unsigned long flags; chan = MHI_EV_READ_CHID(EV_CHID, event); chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mhi_log(MHI_MSG_INFO, "DB_MODE/OOB Detected chan %d.\n", chan); spin_lock_irqsave(&chan_ctxt->ring_lock, flags); chan_ctxt->db_mode.db_mode = 1; if (chan_ctxt->wp != chan_ctxt->rp) { local_chan_ctxt->db_mode.db_mode = 1; if (local_chan_ctxt->wp != local_chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_XFER_RING, chan, (uintptr_t) chan_ctxt->wp); chan_ctxt->db_mode.process_db(mhi_dev_ctxt, (uintptr_t) local_chan_ctxt->wp); local_chan_ctxt->db_mode.process_db(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.chan_db_addr, chan, db_value); } client_handle = mhi_dev_ctxt->client_handle_list[chan]; if (client_handle) result->transaction_status = -ENOTCONN; spin_unlock_irqrestore(&chan_ctxt->ring_lock, flags); break; } case MHI_EVENT_CC_BAD_TRE: Loading Loading @@ -1272,7 +1254,6 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, u64 db_value = 0; void *removed_element = NULL; void *added_element = NULL; spinlock_t *lock; unsigned long flags; struct mhi_ring *mhi_ring = &mhi_dev_ctxt-> mhi_local_event_ctxt[ring_index]; Loading @@ -1292,8 +1273,7 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, if (!MHI_DB_ACCESS_VALID(mhi_dev_ctxt->mhi_pm_state)) return -EACCES; lock = &mhi_ring->ring_lock; spin_lock_irqsave(lock, flags); read_lock_irqsave(&mhi_dev_ctxt->pm_xfer_lock, flags); db_value = mhi_v2p_addr(mhi_dev_ctxt, ring_type, ring_index, Loading @@ -1301,7 +1281,7 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_ring->db_mode.process_db(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.event_db_addr, ring_index, db_value); spin_unlock_irqrestore(lock, flags); read_unlock_irqrestore(&mhi_dev_ctxt->pm_xfer_lock, flags); return 0; Loading @@ -1313,10 +1293,15 @@ static int reset_chan_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan = 0; int ret_val = 0; struct mhi_ring *local_chan_ctxt; struct mhi_ring *ev_ring; struct mhi_chan_ctxt *chan_ctxt; struct mhi_event_ctxt *ev_ctxt = NULL; struct mhi_client_handle *client_handle = NULL; int pending_el = 0, i; struct mhi_ring *bb_ctxt; unsigned long flags; union mhi_event_pkt *local_rp = NULL; union mhi_event_pkt *device_rp = NULL; MHI_TRB_GET_INFO(CMD_TRB_CHID, cmd_pkt, chan); Loading @@ -1330,8 +1315,38 @@ static int reset_chan_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, client_handle = mhi_dev_ctxt->client_handle_list[chan]; local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan]; ev_ring = &mhi_dev_ctxt-> mhi_local_event_ctxt[chan_ctxt->mhi_event_ring_index]; ev_ctxt = &mhi_dev_ctxt-> dev_space.ring_ctxt.ec_list[chan_ctxt->mhi_event_ring_index]; mhi_log(MHI_MSG_INFO, "Processed cmd reset event\n"); /* Clear all stale events related to Channel */ spin_lock_irqsave(&ev_ring->ring_lock, flags); device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, chan_ctxt->mhi_event_ring_index, ev_ctxt->mhi_event_read_ptr); local_rp = (union mhi_event_pkt *)ev_ring->rp; while (device_rp != local_rp) { if (MHI_TRB_READ_INFO(EV_TRB_TYPE, local_rp) == MHI_PKT_TYPE_TX_EVENT) { u32 ev_chan = MHI_EV_READ_CHID(EV_CHID, local_rp); /* Mark as stale event */ if (ev_chan == chan) MHI_TRB_SET_INFO(EV_TRB_TYPE, local_rp, MHI_PKT_TYPE_STALE_EVENT); } local_rp++; if (local_rp == (ev_ring->base + ev_ring->len)) local_rp = ev_ring->base; } spin_unlock_irqrestore(&ev_ring->ring_lock, flags); /* * If outbound elements are pending, they must be cleared since * they will never be acked after a channel reset. Loading Loading
drivers/platform/msm/mhi/mhi.h +2 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,7 @@ enum MHI_PKT_TYPE { MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, MHI_PKT_TYPE_TX_EVENT = 0x22, MHI_PKT_TYPE_EE_EVENT = 0x40, MHI_PKT_TYPE_STALE_EVENT, /* Internal event */ MHI_PKT_TYPE_SYS_ERR_EVENT = 0xFF, }; Loading Loading @@ -310,6 +311,7 @@ struct mhi_ring { uintptr_t el_size; u32 overwrite_en; enum MHI_CHAN_DIR dir; enum MHI_CHAN_STATE ch_state; struct db_mode db_mode; u32 msi_disable_cntr; u32 msi_enable_cntr; Loading
drivers/platform/msm/mhi/mhi_event.c +3 −0 Original line number Diff line number Diff line Loading @@ -122,9 +122,11 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) { struct mhi_ring *event_ctxt = NULL; u64 db_value = 0; unsigned long flags; event_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[event_ring_index]; spin_lock_irqsave(&event_ctxt->ring_lock, flags); db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, event_ring_index, (uintptr_t) event_ctxt->wp); Loading @@ -132,6 +134,7 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) mhi_dev_ctxt->mmio_info.event_db_addr, event_ring_index, db_value); spin_unlock_irqrestore(&event_ctxt->ring_lock, flags); } static int mhi_event_ring_init(struct mhi_event_ctxt *ev_list, Loading
drivers/platform/msm/mhi/mhi_init.c +1 −0 Original line number Diff line number Diff line Loading @@ -594,6 +594,7 @@ int mhi_init_chan_ctxt(struct mhi_chan_ctxt *cc_list, ring->el_size = sizeof(struct mhi_tx_pkt); ring->overwrite_en = 0; ring->dir = chan_type; ring->ch_state = MHI_CHAN_STATE_DISABLED; ring->db_mode.db_mode = 1; ring->db_mode.preserve_db_state = (preserve_db_state) ? 1 : 0; ring->db_mode.brstmode = brstmode; Loading
drivers/platform/msm/mhi/mhi_isr.c +31 −6 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ static int mhi_process_event_ring( union mhi_event_pkt event_to_process; int ret_val = 0; struct mhi_event_ctxt *ev_ctxt = NULL; unsigned long flags; struct mhi_ring *local_ev_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[ev_index]; Loading @@ -38,6 +39,7 @@ static int mhi_process_event_ring( read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); ev_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[ev_index]; spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, Loading @@ -45,19 +47,19 @@ static int mhi_process_event_ring( ev_ctxt->mhi_event_read_ptr); local_rp = (union mhi_event_pkt *)local_ev_ctxt->rp; spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); BUG_ON(validate_ev_el_addr(local_ev_ctxt, (uintptr_t)device_rp)); while ((local_rp != device_rp) && (event_quota > 0) && (device_rp != NULL) && (local_rp != NULL)) { spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); event_to_process = *local_rp; read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); recycle_trb_and_ring(mhi_dev_ctxt, local_ev_ctxt, MHI_RING_TYPE_EVENT_RING, ev_index); read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); switch (MHI_TRB_READ_INFO(EV_TRB_TYPE, &event_to_process)) { case MHI_PKT_TYPE_CMD_COMPLETION_EVENT: Loading Loading @@ -93,12 +95,28 @@ static int mhi_process_event_ring( break; } case MHI_PKT_TYPE_TX_EVENT: { u32 chan; struct mhi_ring *ring; __pm_stay_awake(&mhi_dev_ctxt->w_lock); chan = MHI_EV_READ_CHID(EV_CHID, &event_to_process); if (unlikely(!VALID_CHAN_NR(chan))) { mhi_log(MHI_MSG_ERROR, "Invalid chan:%d\n", chan); break; } ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; spin_lock_bh(&ring->ring_lock); if (ring->ch_state == MHI_CHAN_STATE_ENABLED) parse_xfer_event(mhi_dev_ctxt, &event_to_process, ev_index); spin_unlock_bh(&ring->ring_lock); __pm_relax(&mhi_dev_ctxt->w_lock); break; } case MHI_PKT_TYPE_STATE_CHANGE_EVENT: { enum STATE_TRANSITION new_state; Loading Loading @@ -153,6 +171,11 @@ static int mhi_process_event_ring( } break; } case MHI_PKT_TYPE_STALE_EVENT: mhi_log(MHI_MSG_INFO, "Stale Event received for chan:%u\n", MHI_EV_READ_CHID(EV_CHID, local_rp)); break; case MHI_PKT_TYPE_SYS_ERR_EVENT: mhi_log(MHI_MSG_INFO, "MHI System Error Detected. Triggering Reset\n"); Loading @@ -165,12 +188,14 @@ static int mhi_process_event_ring( &event_to_process)); break; } spin_lock_irqsave(&local_ev_ctxt->ring_lock, flags); local_rp = (union mhi_event_pkt *)local_ev_ctxt->rp; device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, ev_index, ev_ctxt->mhi_event_read_ptr); spin_unlock_irqrestore(&local_ev_ctxt->ring_lock, flags); ret_val = 0; --event_quota; } Loading
drivers/platform/msm/mhi/mhi_main.c +59 −44 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) { int ret_val = 0; struct mhi_device_ctxt *mhi_dev_ctxt; struct mhi_ring *chan_ring; int chan; struct mhi_chan_cfg *cfg; struct mhi_cmd_complete_event_pkt cmd_event_pkt; Loading @@ -295,6 +296,7 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) chan = client_handle->chan_info.chan_nr; cfg = &mhi_dev_ctxt->mhi_chan_cfg[chan]; chan_ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mutex_lock(&cfg->chan_lock); mhi_log(MHI_MSG_INFO, "Entered: Client opening chan 0x%x\n", chan); Loading Loading @@ -352,6 +354,9 @@ int mhi_open_channel(struct mhi_client_handle *client_handle) read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev); spin_lock_irq(&chan_ring->ring_lock); chan_ring->ch_state = MHI_CHAN_STATE_ENABLED; spin_unlock_irq(&chan_ring->ring_lock); ret_val = mhi_send_cmd(client_handle->mhi_dev_ctxt, MHI_COMMAND_START_CHAN, chan); Loading Loading @@ -462,6 +467,7 @@ void mhi_close_channel(struct mhi_client_handle *client_handle) struct mhi_device_ctxt *mhi_dev_ctxt; struct mhi_cmd_complete_event_pkt cmd_event_pkt; union mhi_cmd_pkt cmd_pkt; struct mhi_ring *chan_ring; enum MHI_EVENT_CCS ev_code; if (!client_handle || Loading @@ -474,7 +480,13 @@ void mhi_close_channel(struct mhi_client_handle *client_handle) cfg = &mhi_dev_ctxt->mhi_chan_cfg[chan]; mhi_log(MHI_MSG_INFO, "Client attempting to close chan 0x%x\n", chan); chan_ring = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mutex_lock(&cfg->chan_lock); /* No more processing events for this channel */ spin_lock_irq(&chan_ring->ring_lock); chan_ring->ch_state = MHI_CHAN_STATE_DISABLED; spin_unlock_irq(&chan_ring->ring_lock); init_completion(&cfg->cmd_complete); read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); WARN_ON(mhi_dev_ctxt->mhi_pm_state == MHI_PM_DISABLE); Loading Loading @@ -829,8 +841,6 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, enum MHI_COMMAND cmd, u32 chan) { union mhi_cmd_pkt *cmd_pkt = NULL; enum MHI_CHAN_STATE from_state = MHI_CHAN_STATE_DISABLED; enum MHI_CHAN_STATE to_state = MHI_CHAN_STATE_DISABLED; enum MHI_PKT_TYPE ring_el_type = MHI_PKT_TYPE_NOOP_CMD; int ret_val = 0; unsigned long flags, flags2; Loading @@ -849,33 +859,17 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), mhi_dev_ctxt->dev_exec_env, chan, cmd); from_state = mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan].chstate; switch (cmd) { break; case MHI_COMMAND_RESET_CHAN: to_state = MHI_CHAN_STATE_DISABLED; ring_el_type = MHI_PKT_TYPE_RESET_CHAN_CMD; break; case MHI_COMMAND_START_CHAN: switch (from_state) { case MHI_CHAN_STATE_DISABLED: case MHI_CHAN_STATE_ENABLED: case MHI_CHAN_STATE_STOP: to_state = MHI_CHAN_STATE_RUNNING; break; default: mhi_log(MHI_MSG_ERROR, "Invalid stt cmd 0x%x, from_state 0x%x\n", cmd, from_state); ret_val = -EPERM; goto error_invalid; } ring_el_type = MHI_PKT_TYPE_START_CHAN_CMD; break; default: mhi_log(MHI_MSG_ERROR, "Bad command received\n"); return -EINVAL; } spin_lock_irqsave(&mhi_ring->ring_lock, flags); Loading @@ -897,7 +891,7 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, "Sent command 0x%x for chan %d\n", cmd, chan); error_invalid: mhi_log(MHI_MSG_INFO, "Exited ret %d.\n", ret_val); return ret_val; } Loading Loading @@ -1120,13 +1114,11 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, u32 nr_trb_to_parse; u32 i = 0; u32 ev_code; struct mhi_ring *local_chan_ctxt; trace_mhi_ev(event); chan = MHI_EV_READ_CHID(EV_CHID, event); if (unlikely(!VALID_CHAN_NR(chan))) { mhi_log(MHI_MSG_ERROR, "Bad ring id.\n"); return -EINVAL; } local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; ev_code = MHI_EV_READ_CODE(EV_TRB_CODE, event); client_handle = mhi_dev_ctxt->client_handle_list[chan]; client_handle->pkt_count++; Loading @@ -1147,10 +1139,7 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, dma_addr_t trb_data_loc; u32 ieot_flag; int ret_val; struct mhi_ring *local_chan_ctxt; local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; phy_ev_trb_loc = MHI_EV_READ_PTR(EV_PTR, event); chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan]; Loading Loading @@ -1217,29 +1206,22 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, case MHI_EVENT_CC_OOB: case MHI_EVENT_CC_DB_MODE: { struct mhi_ring *chan_ctxt = NULL; u64 db_value = 0; unsigned long flags; chan = MHI_EV_READ_CHID(EV_CHID, event); chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mhi_log(MHI_MSG_INFO, "DB_MODE/OOB Detected chan %d.\n", chan); spin_lock_irqsave(&chan_ctxt->ring_lock, flags); chan_ctxt->db_mode.db_mode = 1; if (chan_ctxt->wp != chan_ctxt->rp) { local_chan_ctxt->db_mode.db_mode = 1; if (local_chan_ctxt->wp != local_chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_XFER_RING, chan, (uintptr_t) chan_ctxt->wp); chan_ctxt->db_mode.process_db(mhi_dev_ctxt, (uintptr_t) local_chan_ctxt->wp); local_chan_ctxt->db_mode.process_db(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.chan_db_addr, chan, db_value); } client_handle = mhi_dev_ctxt->client_handle_list[chan]; if (client_handle) result->transaction_status = -ENOTCONN; spin_unlock_irqrestore(&chan_ctxt->ring_lock, flags); break; } case MHI_EVENT_CC_BAD_TRE: Loading Loading @@ -1272,7 +1254,6 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, u64 db_value = 0; void *removed_element = NULL; void *added_element = NULL; spinlock_t *lock; unsigned long flags; struct mhi_ring *mhi_ring = &mhi_dev_ctxt-> mhi_local_event_ctxt[ring_index]; Loading @@ -1292,8 +1273,7 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, if (!MHI_DB_ACCESS_VALID(mhi_dev_ctxt->mhi_pm_state)) return -EACCES; lock = &mhi_ring->ring_lock; spin_lock_irqsave(lock, flags); read_lock_irqsave(&mhi_dev_ctxt->pm_xfer_lock, flags); db_value = mhi_v2p_addr(mhi_dev_ctxt, ring_type, ring_index, Loading @@ -1301,7 +1281,7 @@ int recycle_trb_and_ring(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_ring->db_mode.process_db(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.event_db_addr, ring_index, db_value); spin_unlock_irqrestore(lock, flags); read_unlock_irqrestore(&mhi_dev_ctxt->pm_xfer_lock, flags); return 0; Loading @@ -1313,10 +1293,15 @@ static int reset_chan_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan = 0; int ret_val = 0; struct mhi_ring *local_chan_ctxt; struct mhi_ring *ev_ring; struct mhi_chan_ctxt *chan_ctxt; struct mhi_event_ctxt *ev_ctxt = NULL; struct mhi_client_handle *client_handle = NULL; int pending_el = 0, i; struct mhi_ring *bb_ctxt; unsigned long flags; union mhi_event_pkt *local_rp = NULL; union mhi_event_pkt *device_rp = NULL; MHI_TRB_GET_INFO(CMD_TRB_CHID, cmd_pkt, chan); Loading @@ -1330,8 +1315,38 @@ static int reset_chan_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, client_handle = mhi_dev_ctxt->client_handle_list[chan]; local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan]; ev_ring = &mhi_dev_ctxt-> mhi_local_event_ctxt[chan_ctxt->mhi_event_ring_index]; ev_ctxt = &mhi_dev_ctxt-> dev_space.ring_ctxt.ec_list[chan_ctxt->mhi_event_ring_index]; mhi_log(MHI_MSG_INFO, "Processed cmd reset event\n"); /* Clear all stale events related to Channel */ spin_lock_irqsave(&ev_ring->ring_lock, flags); device_rp = (union mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt, MHI_RING_TYPE_EVENT_RING, chan_ctxt->mhi_event_ring_index, ev_ctxt->mhi_event_read_ptr); local_rp = (union mhi_event_pkt *)ev_ring->rp; while (device_rp != local_rp) { if (MHI_TRB_READ_INFO(EV_TRB_TYPE, local_rp) == MHI_PKT_TYPE_TX_EVENT) { u32 ev_chan = MHI_EV_READ_CHID(EV_CHID, local_rp); /* Mark as stale event */ if (ev_chan == chan) MHI_TRB_SET_INFO(EV_TRB_TYPE, local_rp, MHI_PKT_TYPE_STALE_EVENT); } local_rp++; if (local_rp == (ev_ring->base + ev_ring->len)) local_rp = ev_ring->base; } spin_unlock_irqrestore(&ev_ring->ring_lock, flags); /* * If outbound elements are pending, they must be cleared since * they will never be acked after a channel reset. Loading