Loading drivers/platform/msm/mhi/mhi.h +50 −31 Original line number Diff line number Diff line Loading @@ -95,9 +95,12 @@ struct bhi_ctxt_t { u32 poll_timeout; /* BHI/E vector table */ bool manage_boot; /* fw download done by MHI host */ bool support_rddm; struct work_struct fw_load_work; struct firmware_info firmware_info; struct bhie_vec_table fw_table; struct bhie_vec_table rddm_table; size_t rddm_size; }; enum MHI_CHAN_DIR { Loading Loading @@ -140,12 +143,6 @@ enum MHI_CHAIN { MHI_TRE_CHAIN_reserved = 0x80000000 }; enum MHI_EVENT_RING_STATE { MHI_EVENT_RING_UINIT = 0x0, MHI_EVENT_RING_INIT = 0x1, MHI_EVENT_RING_reserved = 0x80000000 }; enum MHI_STATE { MHI_STATE_RESET = 0x0, MHI_STATE_READY = 0x1, Loading @@ -154,9 +151,8 @@ enum MHI_STATE { MHI_STATE_M2 = 0x4, MHI_STATE_M3 = 0x5, MHI_STATE_BHI = 0x7, MHI_STATE_SYS_ERR = 0x8, MHI_STATE_LIMIT = 0x9, MHI_STATE_reserved = 0x80000000 MHI_STATE_SYS_ERR = 0xFF, MHI_STATE_LIMIT, }; enum MHI_BRSTMODE { Loading @@ -168,22 +164,36 @@ enum MHI_BRSTMODE { }; enum MHI_PM_STATE { MHI_PM_DISABLE = 0x0, /* MHI is not enabled */ MHI_PM_POR = 0x1, /* Power On Reset State */ MHI_PM_M0 = 0x2, MHI_PM_M1 = 0x4, MHI_PM_M1_M2_TRANSITION = 0x8, /* Register access not allowed */ MHI_PM_M2 = 0x10, MHI_PM_M3_ENTER = 0x20, MHI_PM_M3 = 0x40, MHI_PM_M3_EXIT = 0x80, MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */ MHI_PM_POR = BIT(1), /* Power On Reset State */ MHI_PM_M0 = BIT(2), MHI_PM_M1 = BIT(3), MHI_PM_M1_M2_TRANSITION = BIT(4), /* Register access not allowed */ MHI_PM_M2 = BIT(5), MHI_PM_M3_ENTER = BIT(6), MHI_PM_M3 = BIT(7), MHI_PM_M3_EXIT = BIT(8), MHI_PM_SYS_ERR_DETECT = BIT(9), MHI_PM_SYS_ERR_PROCESS = BIT(10), MHI_PM_SHUTDOWN_PROCESS = BIT(11), MHI_PM_LD_ERR_FATAL_DETECT = BIT(12), /* Link not accessible */ MHI_PM_SSR_PENDING = BIT(13) }; struct mhi_pm_transitions { enum MHI_PM_STATE from_state; u32 to_states; }; #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1)) #define MHI_WAKE_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2)) #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state > MHI_PM_DISABLE) && \ (pm_state < MHI_PM_M3_EXIT)) #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ MHI_PM_SHUTDOWN_PROCESS))) #define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ pm_state >= MHI_PM_SYS_ERR_DETECT) struct __packed mhi_event_ctxt { u32 mhi_intmodt; u32 mhi_event_er_type; Loading Loading @@ -239,7 +249,6 @@ enum MHI_PKT_TYPE { 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, }; struct __packed mhi_tx_pkt { Loading Loading @@ -393,7 +402,8 @@ enum STATE_TRANSITION { STATE_TRANSITION_LINK_DOWN, STATE_TRANSITION_WAKE, STATE_TRANSITION_BHIE, STATE_TRANSITION_SYS_ERR, STATE_TRANSITION_RDDM, STATE_TRANSITION_SYS_ERR = MHI_STATE_SYS_ERR, STATE_TRANSITION_MAX }; Loading @@ -402,7 +412,8 @@ enum MHI_EXEC_ENV { MHI_EXEC_ENV_SBL = 0x1, MHI_EXEC_ENV_AMSS = 0x2, MHI_EXEC_ENV_BHIE = 0x3, MHI_EXEC_ENV_reserved = 0x80000000 MHI_EXEC_ENV_RDDM = 0x4, MHI_EXEC_ENV_DISABLE_TRANSITION, /* local EE, not related to mhi spec */ }; struct mhi_chan_info { Loading Loading @@ -480,7 +491,7 @@ struct mhi_counters { }; struct mhi_flags { u32 mhi_initialized; bool mhi_initialized; u32 link_up; bool bb_required; }; Loading Loading @@ -546,6 +557,7 @@ struct mhi_device_ctxt { struct mhi_event_ring_cfg *ev_ring_props; struct work_struct st_thread_worker; struct work_struct process_m1_worker; struct work_struct process_sys_err_worker; struct mhi_wait_queues mhi_ev_wq; struct dev_mmio_info mmio_info; Loading Loading @@ -587,7 +599,8 @@ struct mhi_device_ctxt { void (*assert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt, bool force_set); void (*deassert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt); void (*status_cb)(enum MHI_CB_REASON, void *priv); void *priv_data; /* private data for bus master */ struct completion cmd_complete; }; Loading @@ -612,7 +625,6 @@ struct mhi_event_ring_cfg { */ u32 priority; enum MHI_RING_CLASS class; enum MHI_EVENT_RING_STATE state; irqreturn_t (*mhi_handler_ptr)(int , void *); }; #define MHI_EV_PRIORITY_TASKLET (1) Loading Loading @@ -673,13 +685,12 @@ enum MHI_EVENT_CCS get_cmd_pkt(struct mhi_device_ctxt *mhi_dev_ctxt, union mhi_cmd_pkt **cmd_pkt, u32 event_index); int parse_cmd_event(struct mhi_device_ctxt *ctxt, union mhi_event_pkt *event, u32 event_index); int mhi_test_for_device_ready( struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_reset( struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_reset(struct mhi_device_ctxt *mhi_dev_ctxt); int validate_ring_el_addr(struct mhi_ring *ring, uintptr_t addr); int validate_ev_el_addr(struct mhi_ring *ring, uintptr_t addr); void mhi_state_change_worker(struct work_struct *work); void mhi_sys_err_worker(struct work_struct *work); int mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt, enum STATE_TRANSITION new_state); int mhi_wait_for_mdm(struct mhi_device_ctxt *mhi_dev_ctxt); Loading Loading @@ -709,7 +720,7 @@ int mhi_reg_notifiers(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_cpu_notifier_cb(struct notifier_block *nfb, unsigned long action, void *hcpu); int init_mhi_base_state(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_turn_off_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_turn_off_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt, bool graceful); int mhi_turn_on_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt); Loading Loading @@ -757,5 +768,13 @@ void mhi_ev_task(unsigned long data); void process_event_ring(struct work_struct *work); int process_m0_transition(struct mhi_device_ctxt *mhi_dev_ctxt); int process_m3_transition(struct mhi_device_ctxt *mhi_dev_ctxt); enum MHI_PM_STATE __must_check mhi_tryset_pm_state(struct mhi_device_ctxt *, enum MHI_PM_STATE); void mhi_reset_chan(struct mhi_device_ctxt *mhi_dev_ctxt, int chan); void free_tre_ring(struct mhi_device_ctxt *mhi_dev_ctxt, int chan); void process_disable_transition(enum MHI_PM_STATE transition_state, struct mhi_device_ctxt *mhi_dev_ctxt); bool mhi_in_sys_err(struct mhi_device_ctxt *mhi_dev_ctxt); void bhi_exit(struct mhi_device_ctxt *mhi_dev_ctxt); #endif drivers/platform/msm/mhi/mhi_bhi.c +149 −27 Original line number Diff line number Diff line Loading @@ -137,17 +137,36 @@ static int bhi_alloc_pbl_xfer(struct mhi_device_ctxt *mhi_dev_ctxt, return 0; } /* Load firmware via bhie protocol */ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) /* transfer firmware or ramdump via bhie protocol */ static int bhi_bhie_transfer(struct mhi_device_ctxt *mhi_dev_ctxt, struct bhie_vec_table *vec_table, bool tx_vec_table) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; /* last element is the vector table */ const struct bhie_mem_info *bhie_mem_info = &fw_table->bhie_mem_info[fw_table->segment_count - 1]; &vec_table->bhie_mem_info[vec_table->segment_count - 1]; u32 val; const u32 tx_sequence = fw_table->sequence++; const u32 tx_sequence = vec_table->sequence++; unsigned long timeout; rwlock_t *pm_xfer_lock = &mhi_dev_ctxt->pm_xfer_lock; unsigned bhie_vecaddr_high_offs, bhie_vecaddr_low_offs, bhie_vecsize_offs, bhie_vecdb_offs, bhie_vecstatus_offs; if (tx_vec_table) { bhie_vecaddr_high_offs = BHIE_TXVECADDR_HIGH_OFFS; bhie_vecaddr_low_offs = BHIE_TXVECADDR_LOW_OFFS; bhie_vecsize_offs = BHIE_TXVECSIZE_OFFS; bhie_vecdb_offs = BHIE_TXVECDB_OFFS; bhie_vecstatus_offs = BHIE_TXVECSTATUS_OFFS; } else { bhie_vecaddr_high_offs = BHIE_RXVECADDR_HIGH_OFFS; bhie_vecaddr_low_offs = BHIE_RXVECADDR_LOW_OFFS; bhie_vecsize_offs = BHIE_RXVECSIZE_OFFS; bhie_vecdb_offs = BHIE_RXVECDB_OFFS; bhie_vecstatus_offs = BHIE_RXVECSTATUS_OFFS; } /* Program TX/RX Vector table */ read_lock_bh(pm_xfer_lock); Loading @@ -157,27 +176,17 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) } val = HIGH_WORD(bhie_mem_info->phys_addr); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECADDR_HIGH_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecaddr_high_offs, val); val = LOW_WORD(bhie_mem_info->phys_addr); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECADDR_LOW_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecaddr_low_offs, val); val = (u32)bhie_mem_info->size; mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECSIZE_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecsize_offs, val); /* Ring DB to begin Xfer */ mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECDB_OFFS, BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecdb_offs, BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, tx_sequence); read_unlock_bh(pm_xfer_lock); Loading @@ -190,10 +199,10 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) read_unlock_bh(pm_xfer_lock); return -EIO; } val = mhi_reg_read(bhi_ctxt->bhi_base, BHIE_TXVECSTATUS_OFFS); val = mhi_reg_read(bhi_ctxt->bhi_base, bhie_vecstatus_offs); read_unlock_bh(pm_xfer_lock); mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "TXVEC_STATUS:0x%x\n", val); "%sVEC_STATUS:0x%x\n", tx_vec_table ? "TX" : "RX", val); current_seq = (val & BHIE_TXVECSTATUS_SEQNUM_BMSK) >> BHIE_TXVECSTATUS_SEQNUM_SHFT; status = (val & BHIE_TXVECSTATUS_STATUS_BMSK) >> Loading @@ -201,17 +210,60 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) if ((status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) && (current_seq == tx_sequence)) { mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Image transfer complete\n"); "%s transfer complete\n", tx_vec_table ? "image" : "rddm"); return 0; } msleep(BHI_POLL_SLEEP_TIME_MS); } mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Error xfering image via BHIE\n"); "Error xfer %s via BHIE\n", tx_vec_table ? "image" : "rddm"); return -EIO; } static int bhi_rddm_graceful(struct mhi_device_ctxt *mhi_dev_ctxt) { int ret; struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; enum MHI_EXEC_ENV exec_env = mhi_dev_ctxt->dev_exec_env; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered with pm_state:0x%x exec_env:0x%x mhi_state:%s\n", mhi_dev_ctxt->mhi_pm_state, exec_env, TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); if (exec_env != MHI_EXEC_ENV_RDDM) { mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Not in RDDM exec env, exec_env:0x%x\n", exec_env); return -EIO; } ret = bhi_bhie_transfer(mhi_dev_ctxt, rddm_table, false); mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "rddm transfer status:%d\n", ret); return ret; } /* collect ramdump from device using bhie protocol */ int bhi_rddm(struct mhi_device_ctxt *mhi_dev_ctxt, bool in_panic) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; if (!rddm_table->bhie_mem_info) { mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "RDDM table == NULL\n"); return -ENOMEM; } if (!in_panic) return bhi_rddm_graceful(mhi_dev_ctxt); mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "RDDM collection in panic not yet supported\n"); return -EINVAL; } static int bhi_load_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; Loading Loading @@ -425,7 +477,8 @@ void bhi_firmware_download(struct work_struct *work) return; } ret = bhi_load_bhie_firmware(mhi_dev_ctxt); ret = bhi_bhie_transfer(mhi_dev_ctxt, &mhi_dev_ctxt->bhi_ctxt.fw_table, true); if (ret) { mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Failed to Load amss firmware\n"); Loading @@ -437,6 +490,7 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt) struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct firmware_info *fw_info = &bhi_ctxt->firmware_info; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; const struct firmware *firmware; struct scatterlist *itr; int ret, i; Loading Loading @@ -503,7 +557,75 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt) fw_table->sequence++; release_firmware(firmware); /* allocate memory and setup rddm table */ if (bhi_ctxt->support_rddm) { ret = bhi_alloc_bhie_xfer(mhi_dev_ctxt, bhi_ctxt->rddm_size, rddm_table); if (!ret) { for (i = 0, itr = &rddm_table->sg_list[1]; i < rddm_table->segment_count - 1; i++, itr++) { size_t size = rddm_table->bhie_mem_info[i].size; rddm_table->bhi_vec_entry[i].phys_addr = rddm_table->bhie_mem_info[i].phys_addr; rddm_table->bhi_vec_entry[i].size = size; sg_set_buf(itr, rddm_table-> bhie_mem_info[i].aligned, size); sg_dma_address(itr) = rddm_table->bhie_mem_info[i].phys_addr; sg_dma_len(itr) = size; } rddm_table->sequence++; } else { /* out of memory for rddm, not fatal error */ mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Could not successfully allocate mem for rddm\n"); } } /* Schedule a worker thread and wait for BHI Event */ schedule_work(&bhi_ctxt->fw_load_work); return 0; } void bhi_exit(struct mhi_device_ctxt *mhi_dev_ctxt) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; struct device *dev = &mhi_dev_ctxt->plat_dev->dev; struct bhie_mem_info *bhie_mem_info; int i; if (bhi_ctxt->manage_boot == false) return; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "freeing firmware and rddm memory\n"); /* free memory allocated for firmware */ kfree(fw_table->sg_list); fw_table->sg_list = NULL; bhie_mem_info = fw_table->bhie_mem_info; for (i = 0; i < fw_table->segment_count; i++, bhie_mem_info++) dma_free_coherent(dev, bhie_mem_info->alloc_size, bhie_mem_info->pre_aligned, bhie_mem_info->dma_handle); fw_table->bhie_mem_info = NULL; /* vector table is the last entry in bhie_mem_info */ fw_table->bhi_vec_entry = NULL; if (!rddm_table->bhie_mem_info) return; /* free memory allocated for rddm */ kfree(rddm_table->sg_list); rddm_table->sg_list = NULL; bhie_mem_info = rddm_table->bhie_mem_info; for (i = 0; i < rddm_table->segment_count; i++, bhie_mem_info++) dma_free_coherent(dev, bhie_mem_info->alloc_size, bhie_mem_info->pre_aligned, bhie_mem_info->dma_handle); rddm_table->bhie_mem_info = NULL; rddm_table->bhi_vec_entry = NULL; } drivers/platform/msm/mhi/mhi_bhi.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2014, 2016-2017 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 @@ -90,5 +90,6 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt); void bhi_firmware_download(struct work_struct *work); int bhi_rddm(struct mhi_device_ctxt *mhi_dev_ctxt, bool in_panic); #endif drivers/platform/msm/mhi/mhi_event.c +3 −5 Original line number Diff line number Diff line Loading @@ -226,8 +226,7 @@ int init_local_ev_ring_by_type(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered\n"); for (i = 0; i < mhi_dev_ctxt->mmio_info.nr_event_rings; i++) { if (GET_EV_PROPS(EV_TYPE, mhi_dev_ctxt->ev_ring_props[i].flags) == type && !mhi_dev_ctxt->ev_ring_props[i].state) { mhi_dev_ctxt->ev_ring_props[i].flags) == type) { ret_val = mhi_init_local_event_ring(mhi_dev_ctxt, mhi_dev_ctxt->ev_ring_props[i].nr_desc, i); Loading Loading @@ -292,7 +291,6 @@ int mhi_init_local_event_ring(struct mhi_device_ctxt *mhi_dev_ctxt, break; } } mhi_dev_ctxt->ev_ring_props[ring_index].state = MHI_EVENT_RING_INIT; spin_unlock_irqrestore(lock, flags); return ret_val; } Loading @@ -309,6 +307,7 @@ void mhi_reset_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[index]; local_ev_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[index]; spin_lock_irq(&local_ev_ctxt->ring_lock); ev_ctxt->mhi_event_read_ptr = ev_ctxt->mhi_event_ring_base_addr; ev_ctxt->mhi_event_write_ptr = ev_ctxt->mhi_event_ring_base_addr; local_ev_ctxt->rp = local_ev_ctxt->base; Loading @@ -317,6 +316,5 @@ void mhi_reset_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, ev_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[index]; ev_ctxt->mhi_event_read_ptr = ev_ctxt->mhi_event_ring_base_addr; ev_ctxt->mhi_event_write_ptr = ev_ctxt->mhi_event_ring_base_addr; /* Flush writes to MMIO */ wmb(); spin_unlock_irq(&local_ev_ctxt->ring_lock); } drivers/platform/msm/mhi/mhi_iface.c +1 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ static int mhi_pci_probe(struct pci_dev *pcie_device, mhi_dev_ctxt->mhi_pm_state = MHI_PM_DISABLE; INIT_WORK(&mhi_dev_ctxt->process_m1_worker, process_m1_transition); INIT_WORK(&mhi_dev_ctxt->st_thread_worker, mhi_state_change_worker); INIT_WORK(&mhi_dev_ctxt->process_sys_err_worker, mhi_sys_err_worker); mutex_init(&mhi_dev_ctxt->pm_lock); rwlock_init(&mhi_dev_ctxt->pm_xfer_lock); spin_lock_init(&mhi_dev_ctxt->dev_wake_lock); Loading Loading
drivers/platform/msm/mhi/mhi.h +50 −31 Original line number Diff line number Diff line Loading @@ -95,9 +95,12 @@ struct bhi_ctxt_t { u32 poll_timeout; /* BHI/E vector table */ bool manage_boot; /* fw download done by MHI host */ bool support_rddm; struct work_struct fw_load_work; struct firmware_info firmware_info; struct bhie_vec_table fw_table; struct bhie_vec_table rddm_table; size_t rddm_size; }; enum MHI_CHAN_DIR { Loading Loading @@ -140,12 +143,6 @@ enum MHI_CHAIN { MHI_TRE_CHAIN_reserved = 0x80000000 }; enum MHI_EVENT_RING_STATE { MHI_EVENT_RING_UINIT = 0x0, MHI_EVENT_RING_INIT = 0x1, MHI_EVENT_RING_reserved = 0x80000000 }; enum MHI_STATE { MHI_STATE_RESET = 0x0, MHI_STATE_READY = 0x1, Loading @@ -154,9 +151,8 @@ enum MHI_STATE { MHI_STATE_M2 = 0x4, MHI_STATE_M3 = 0x5, MHI_STATE_BHI = 0x7, MHI_STATE_SYS_ERR = 0x8, MHI_STATE_LIMIT = 0x9, MHI_STATE_reserved = 0x80000000 MHI_STATE_SYS_ERR = 0xFF, MHI_STATE_LIMIT, }; enum MHI_BRSTMODE { Loading @@ -168,22 +164,36 @@ enum MHI_BRSTMODE { }; enum MHI_PM_STATE { MHI_PM_DISABLE = 0x0, /* MHI is not enabled */ MHI_PM_POR = 0x1, /* Power On Reset State */ MHI_PM_M0 = 0x2, MHI_PM_M1 = 0x4, MHI_PM_M1_M2_TRANSITION = 0x8, /* Register access not allowed */ MHI_PM_M2 = 0x10, MHI_PM_M3_ENTER = 0x20, MHI_PM_M3 = 0x40, MHI_PM_M3_EXIT = 0x80, MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */ MHI_PM_POR = BIT(1), /* Power On Reset State */ MHI_PM_M0 = BIT(2), MHI_PM_M1 = BIT(3), MHI_PM_M1_M2_TRANSITION = BIT(4), /* Register access not allowed */ MHI_PM_M2 = BIT(5), MHI_PM_M3_ENTER = BIT(6), MHI_PM_M3 = BIT(7), MHI_PM_M3_EXIT = BIT(8), MHI_PM_SYS_ERR_DETECT = BIT(9), MHI_PM_SYS_ERR_PROCESS = BIT(10), MHI_PM_SHUTDOWN_PROCESS = BIT(11), MHI_PM_LD_ERR_FATAL_DETECT = BIT(12), /* Link not accessible */ MHI_PM_SSR_PENDING = BIT(13) }; struct mhi_pm_transitions { enum MHI_PM_STATE from_state; u32 to_states; }; #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1)) #define MHI_WAKE_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2)) #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state > MHI_PM_DISABLE) && \ (pm_state < MHI_PM_M3_EXIT)) #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ MHI_PM_SHUTDOWN_PROCESS))) #define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ pm_state >= MHI_PM_SYS_ERR_DETECT) struct __packed mhi_event_ctxt { u32 mhi_intmodt; u32 mhi_event_er_type; Loading Loading @@ -239,7 +249,6 @@ enum MHI_PKT_TYPE { 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, }; struct __packed mhi_tx_pkt { Loading Loading @@ -393,7 +402,8 @@ enum STATE_TRANSITION { STATE_TRANSITION_LINK_DOWN, STATE_TRANSITION_WAKE, STATE_TRANSITION_BHIE, STATE_TRANSITION_SYS_ERR, STATE_TRANSITION_RDDM, STATE_TRANSITION_SYS_ERR = MHI_STATE_SYS_ERR, STATE_TRANSITION_MAX }; Loading @@ -402,7 +412,8 @@ enum MHI_EXEC_ENV { MHI_EXEC_ENV_SBL = 0x1, MHI_EXEC_ENV_AMSS = 0x2, MHI_EXEC_ENV_BHIE = 0x3, MHI_EXEC_ENV_reserved = 0x80000000 MHI_EXEC_ENV_RDDM = 0x4, MHI_EXEC_ENV_DISABLE_TRANSITION, /* local EE, not related to mhi spec */ }; struct mhi_chan_info { Loading Loading @@ -480,7 +491,7 @@ struct mhi_counters { }; struct mhi_flags { u32 mhi_initialized; bool mhi_initialized; u32 link_up; bool bb_required; }; Loading Loading @@ -546,6 +557,7 @@ struct mhi_device_ctxt { struct mhi_event_ring_cfg *ev_ring_props; struct work_struct st_thread_worker; struct work_struct process_m1_worker; struct work_struct process_sys_err_worker; struct mhi_wait_queues mhi_ev_wq; struct dev_mmio_info mmio_info; Loading Loading @@ -587,7 +599,8 @@ struct mhi_device_ctxt { void (*assert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt, bool force_set); void (*deassert_wake)(struct mhi_device_ctxt *mhi_dev_ctxt); void (*status_cb)(enum MHI_CB_REASON, void *priv); void *priv_data; /* private data for bus master */ struct completion cmd_complete; }; Loading @@ -612,7 +625,6 @@ struct mhi_event_ring_cfg { */ u32 priority; enum MHI_RING_CLASS class; enum MHI_EVENT_RING_STATE state; irqreturn_t (*mhi_handler_ptr)(int , void *); }; #define MHI_EV_PRIORITY_TASKLET (1) Loading Loading @@ -673,13 +685,12 @@ enum MHI_EVENT_CCS get_cmd_pkt(struct mhi_device_ctxt *mhi_dev_ctxt, union mhi_cmd_pkt **cmd_pkt, u32 event_index); int parse_cmd_event(struct mhi_device_ctxt *ctxt, union mhi_event_pkt *event, u32 event_index); int mhi_test_for_device_ready( struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_reset( struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_ready(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_test_for_device_reset(struct mhi_device_ctxt *mhi_dev_ctxt); int validate_ring_el_addr(struct mhi_ring *ring, uintptr_t addr); int validate_ev_el_addr(struct mhi_ring *ring, uintptr_t addr); void mhi_state_change_worker(struct work_struct *work); void mhi_sys_err_worker(struct work_struct *work); int mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt, enum STATE_TRANSITION new_state); int mhi_wait_for_mdm(struct mhi_device_ctxt *mhi_dev_ctxt); Loading Loading @@ -709,7 +720,7 @@ int mhi_reg_notifiers(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_cpu_notifier_cb(struct notifier_block *nfb, unsigned long action, void *hcpu); int init_mhi_base_state(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_turn_off_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_turn_off_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt, bool graceful); int mhi_turn_on_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt); Loading Loading @@ -757,5 +768,13 @@ void mhi_ev_task(unsigned long data); void process_event_ring(struct work_struct *work); int process_m0_transition(struct mhi_device_ctxt *mhi_dev_ctxt); int process_m3_transition(struct mhi_device_ctxt *mhi_dev_ctxt); enum MHI_PM_STATE __must_check mhi_tryset_pm_state(struct mhi_device_ctxt *, enum MHI_PM_STATE); void mhi_reset_chan(struct mhi_device_ctxt *mhi_dev_ctxt, int chan); void free_tre_ring(struct mhi_device_ctxt *mhi_dev_ctxt, int chan); void process_disable_transition(enum MHI_PM_STATE transition_state, struct mhi_device_ctxt *mhi_dev_ctxt); bool mhi_in_sys_err(struct mhi_device_ctxt *mhi_dev_ctxt); void bhi_exit(struct mhi_device_ctxt *mhi_dev_ctxt); #endif
drivers/platform/msm/mhi/mhi_bhi.c +149 −27 Original line number Diff line number Diff line Loading @@ -137,17 +137,36 @@ static int bhi_alloc_pbl_xfer(struct mhi_device_ctxt *mhi_dev_ctxt, return 0; } /* Load firmware via bhie protocol */ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) /* transfer firmware or ramdump via bhie protocol */ static int bhi_bhie_transfer(struct mhi_device_ctxt *mhi_dev_ctxt, struct bhie_vec_table *vec_table, bool tx_vec_table) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; /* last element is the vector table */ const struct bhie_mem_info *bhie_mem_info = &fw_table->bhie_mem_info[fw_table->segment_count - 1]; &vec_table->bhie_mem_info[vec_table->segment_count - 1]; u32 val; const u32 tx_sequence = fw_table->sequence++; const u32 tx_sequence = vec_table->sequence++; unsigned long timeout; rwlock_t *pm_xfer_lock = &mhi_dev_ctxt->pm_xfer_lock; unsigned bhie_vecaddr_high_offs, bhie_vecaddr_low_offs, bhie_vecsize_offs, bhie_vecdb_offs, bhie_vecstatus_offs; if (tx_vec_table) { bhie_vecaddr_high_offs = BHIE_TXVECADDR_HIGH_OFFS; bhie_vecaddr_low_offs = BHIE_TXVECADDR_LOW_OFFS; bhie_vecsize_offs = BHIE_TXVECSIZE_OFFS; bhie_vecdb_offs = BHIE_TXVECDB_OFFS; bhie_vecstatus_offs = BHIE_TXVECSTATUS_OFFS; } else { bhie_vecaddr_high_offs = BHIE_RXVECADDR_HIGH_OFFS; bhie_vecaddr_low_offs = BHIE_RXVECADDR_LOW_OFFS; bhie_vecsize_offs = BHIE_RXVECSIZE_OFFS; bhie_vecdb_offs = BHIE_RXVECDB_OFFS; bhie_vecstatus_offs = BHIE_RXVECSTATUS_OFFS; } /* Program TX/RX Vector table */ read_lock_bh(pm_xfer_lock); Loading @@ -157,27 +176,17 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) } val = HIGH_WORD(bhie_mem_info->phys_addr); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECADDR_HIGH_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecaddr_high_offs, val); val = LOW_WORD(bhie_mem_info->phys_addr); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECADDR_LOW_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecaddr_low_offs, val); val = (u32)bhie_mem_info->size; mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECSIZE_OFFS, val); mhi_reg_write(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecsize_offs, val); /* Ring DB to begin Xfer */ mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHIE_TXVECDB_OFFS, BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, bhie_vecdb_offs, BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, tx_sequence); read_unlock_bh(pm_xfer_lock); Loading @@ -190,10 +199,10 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) read_unlock_bh(pm_xfer_lock); return -EIO; } val = mhi_reg_read(bhi_ctxt->bhi_base, BHIE_TXVECSTATUS_OFFS); val = mhi_reg_read(bhi_ctxt->bhi_base, bhie_vecstatus_offs); read_unlock_bh(pm_xfer_lock); mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "TXVEC_STATUS:0x%x\n", val); "%sVEC_STATUS:0x%x\n", tx_vec_table ? "TX" : "RX", val); current_seq = (val & BHIE_TXVECSTATUS_SEQNUM_BMSK) >> BHIE_TXVECSTATUS_SEQNUM_SHFT; status = (val & BHIE_TXVECSTATUS_STATUS_BMSK) >> Loading @@ -201,17 +210,60 @@ static int bhi_load_bhie_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) if ((status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) && (current_seq == tx_sequence)) { mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Image transfer complete\n"); "%s transfer complete\n", tx_vec_table ? "image" : "rddm"); return 0; } msleep(BHI_POLL_SLEEP_TIME_MS); } mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Error xfering image via BHIE\n"); "Error xfer %s via BHIE\n", tx_vec_table ? "image" : "rddm"); return -EIO; } static int bhi_rddm_graceful(struct mhi_device_ctxt *mhi_dev_ctxt) { int ret; struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; enum MHI_EXEC_ENV exec_env = mhi_dev_ctxt->dev_exec_env; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered with pm_state:0x%x exec_env:0x%x mhi_state:%s\n", mhi_dev_ctxt->mhi_pm_state, exec_env, TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); if (exec_env != MHI_EXEC_ENV_RDDM) { mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Not in RDDM exec env, exec_env:0x%x\n", exec_env); return -EIO; } ret = bhi_bhie_transfer(mhi_dev_ctxt, rddm_table, false); mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "rddm transfer status:%d\n", ret); return ret; } /* collect ramdump from device using bhie protocol */ int bhi_rddm(struct mhi_device_ctxt *mhi_dev_ctxt, bool in_panic) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; if (!rddm_table->bhie_mem_info) { mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "RDDM table == NULL\n"); return -ENOMEM; } if (!in_panic) return bhi_rddm_graceful(mhi_dev_ctxt); mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "RDDM collection in panic not yet supported\n"); return -EINVAL; } static int bhi_load_firmware(struct mhi_device_ctxt *mhi_dev_ctxt) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; Loading Loading @@ -425,7 +477,8 @@ void bhi_firmware_download(struct work_struct *work) return; } ret = bhi_load_bhie_firmware(mhi_dev_ctxt); ret = bhi_bhie_transfer(mhi_dev_ctxt, &mhi_dev_ctxt->bhi_ctxt.fw_table, true); if (ret) { mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Failed to Load amss firmware\n"); Loading @@ -437,6 +490,7 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt) struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct firmware_info *fw_info = &bhi_ctxt->firmware_info; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; const struct firmware *firmware; struct scatterlist *itr; int ret, i; Loading Loading @@ -503,7 +557,75 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt) fw_table->sequence++; release_firmware(firmware); /* allocate memory and setup rddm table */ if (bhi_ctxt->support_rddm) { ret = bhi_alloc_bhie_xfer(mhi_dev_ctxt, bhi_ctxt->rddm_size, rddm_table); if (!ret) { for (i = 0, itr = &rddm_table->sg_list[1]; i < rddm_table->segment_count - 1; i++, itr++) { size_t size = rddm_table->bhie_mem_info[i].size; rddm_table->bhi_vec_entry[i].phys_addr = rddm_table->bhie_mem_info[i].phys_addr; rddm_table->bhi_vec_entry[i].size = size; sg_set_buf(itr, rddm_table-> bhie_mem_info[i].aligned, size); sg_dma_address(itr) = rddm_table->bhie_mem_info[i].phys_addr; sg_dma_len(itr) = size; } rddm_table->sequence++; } else { /* out of memory for rddm, not fatal error */ mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Could not successfully allocate mem for rddm\n"); } } /* Schedule a worker thread and wait for BHI Event */ schedule_work(&bhi_ctxt->fw_load_work); return 0; } void bhi_exit(struct mhi_device_ctxt *mhi_dev_ctxt) { struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt; struct bhie_vec_table *fw_table = &bhi_ctxt->fw_table; struct bhie_vec_table *rddm_table = &bhi_ctxt->rddm_table; struct device *dev = &mhi_dev_ctxt->plat_dev->dev; struct bhie_mem_info *bhie_mem_info; int i; if (bhi_ctxt->manage_boot == false) return; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "freeing firmware and rddm memory\n"); /* free memory allocated for firmware */ kfree(fw_table->sg_list); fw_table->sg_list = NULL; bhie_mem_info = fw_table->bhie_mem_info; for (i = 0; i < fw_table->segment_count; i++, bhie_mem_info++) dma_free_coherent(dev, bhie_mem_info->alloc_size, bhie_mem_info->pre_aligned, bhie_mem_info->dma_handle); fw_table->bhie_mem_info = NULL; /* vector table is the last entry in bhie_mem_info */ fw_table->bhi_vec_entry = NULL; if (!rddm_table->bhie_mem_info) return; /* free memory allocated for rddm */ kfree(rddm_table->sg_list); rddm_table->sg_list = NULL; bhie_mem_info = rddm_table->bhie_mem_info; for (i = 0; i < rddm_table->segment_count; i++, bhie_mem_info++) dma_free_coherent(dev, bhie_mem_info->alloc_size, bhie_mem_info->pre_aligned, bhie_mem_info->dma_handle); rddm_table->bhie_mem_info = NULL; rddm_table->bhi_vec_entry = NULL; }
drivers/platform/msm/mhi/mhi_bhi.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. /* Copyright (c) 2014, 2016-2017 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 @@ -90,5 +90,6 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt); void bhi_firmware_download(struct work_struct *work); int bhi_rddm(struct mhi_device_ctxt *mhi_dev_ctxt, bool in_panic); #endif
drivers/platform/msm/mhi/mhi_event.c +3 −5 Original line number Diff line number Diff line Loading @@ -226,8 +226,7 @@ int init_local_ev_ring_by_type(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered\n"); for (i = 0; i < mhi_dev_ctxt->mmio_info.nr_event_rings; i++) { if (GET_EV_PROPS(EV_TYPE, mhi_dev_ctxt->ev_ring_props[i].flags) == type && !mhi_dev_ctxt->ev_ring_props[i].state) { mhi_dev_ctxt->ev_ring_props[i].flags) == type) { ret_val = mhi_init_local_event_ring(mhi_dev_ctxt, mhi_dev_ctxt->ev_ring_props[i].nr_desc, i); Loading Loading @@ -292,7 +291,6 @@ int mhi_init_local_event_ring(struct mhi_device_ctxt *mhi_dev_ctxt, break; } } mhi_dev_ctxt->ev_ring_props[ring_index].state = MHI_EVENT_RING_INIT; spin_unlock_irqrestore(lock, flags); return ret_val; } Loading @@ -309,6 +307,7 @@ void mhi_reset_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[index]; local_ev_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[index]; spin_lock_irq(&local_ev_ctxt->ring_lock); ev_ctxt->mhi_event_read_ptr = ev_ctxt->mhi_event_ring_base_addr; ev_ctxt->mhi_event_write_ptr = ev_ctxt->mhi_event_ring_base_addr; local_ev_ctxt->rp = local_ev_ctxt->base; Loading @@ -317,6 +316,5 @@ void mhi_reset_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, ev_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[index]; ev_ctxt->mhi_event_read_ptr = ev_ctxt->mhi_event_ring_base_addr; ev_ctxt->mhi_event_write_ptr = ev_ctxt->mhi_event_ring_base_addr; /* Flush writes to MMIO */ wmb(); spin_unlock_irq(&local_ev_ctxt->ring_lock); }
drivers/platform/msm/mhi/mhi_iface.c +1 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ static int mhi_pci_probe(struct pci_dev *pcie_device, mhi_dev_ctxt->mhi_pm_state = MHI_PM_DISABLE; INIT_WORK(&mhi_dev_ctxt->process_m1_worker, process_m1_transition); INIT_WORK(&mhi_dev_ctxt->st_thread_worker, mhi_state_change_worker); INIT_WORK(&mhi_dev_ctxt->process_sys_err_worker, mhi_sys_err_worker); mutex_init(&mhi_dev_ctxt->pm_lock); rwlock_init(&mhi_dev_ctxt->pm_xfer_lock); spin_lock_init(&mhi_dev_ctxt->dev_wake_lock); Loading