diff options
| author | Sujeev Dias <sdias@codeaurora.org> | 2017-01-11 19:46:17 -0800 |
|---|---|---|
| committer | Sujeev Dias <sdias@codeaurora.org> | 2017-03-11 13:26:48 -0800 |
| commit | 65d8df7619ff26339014247bfe62916d9e38882f (patch) | |
| tree | a91a6d3eb1acfaddeac2ebbe4326d10b469b4917 | |
| parent | 41fb6e92abab37b865bcdb77960dea1521832f42 (diff) | |
mhi: core: add support for priority based event processing
Not all events require same priority to process. Process
high priority events using a tasklet while processing low
priority events using a kworker. Priority for events can be
configured by device tree.
CRs-Fixed: 2004759
Change-Id: I6bf04624c2fd92afd7c698d6a57f66619ea13b5b
Signed-off-by: Sujeev Dias <sdias@codeaurora.org>
| -rw-r--r-- | Documentation/devicetree/bindings/mhi/msm_mhi.txt | 7 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi.h | 31 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_event.c | 26 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_iface.c | 6 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_init.c | 48 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_isr.c | 126 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_main.c | 3 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_states.c | 107 |
8 files changed, 106 insertions, 248 deletions
diff --git a/Documentation/devicetree/bindings/mhi/msm_mhi.txt b/Documentation/devicetree/bindings/mhi/msm_mhi.txt index 6467f4d103e5..5f950604d186 100644 --- a/Documentation/devicetree/bindings/mhi/msm_mhi.txt +++ b/Documentation/devicetree/bindings/mhi/msm_mhi.txt @@ -88,12 +88,13 @@ Main node properties: Usage: required Value type: Array of <u32> Definition: mhi event ring configuration parameters for platform - defined as below <A B C D E>: + defined as below <A B C D E F>: A = maximum event descriptors B = MSI associated with event C = interrupt moderation (see MHI specification) D = Associated channel - E = flags defined by mhi_macros.h GET_EV_PROPS + E = priority of the event ring. 0 being the highest. + F = flags defined by mhi_macros.h GET_EV_PROPS - qcom,mhi-address-window Usage: required @@ -147,5 +148,5 @@ mhi: qcom,mhi { <100 512 1200000000 1200000000>; mhi-event-rings = <1>; mhi-chan-cfg-102 = <0x66 0x80 0x5 0x62>; - mhi-event-cfg-0 = <0x80 0x0 0x0 0x0 0x11>; + mhi-event-cfg-0 = <0x80 0x0 0x0 0x0 0 1 0x11>; }; diff --git a/drivers/platform/msm/mhi/mhi.h b/drivers/platform/msm/mhi/mhi.h index de46fd39259a..4bce96102525 100644 --- a/drivers/platform/msm/mhi/mhi.h +++ b/drivers/platform/msm/mhi/mhi.h @@ -349,6 +349,10 @@ struct mhi_ring { u32 msi_enable_cntr; spinlock_t ring_lock; struct dma_pool *dma_pool; + struct tasklet_struct ev_task; + struct work_struct ev_worker; + struct mhi_device_ctxt *mhi_dev_ctxt; + int index; }; enum MHI_CMD_STATUS { @@ -469,7 +473,6 @@ struct mhi_counters { u32 bb_used[MHI_MAX_CHANNELS]; atomic_t device_wake; atomic_t outbound_acks; - atomic_t events_pending; u32 *msi_counter; u32 mhi_reset_cntr; u32 link_down_cntr; @@ -479,16 +482,10 @@ struct mhi_counters { struct mhi_flags { u32 mhi_initialized; u32 link_up; - int stop_threads; - u32 kill_threads; - u32 ev_thread_stopped; - u32 st_thread_stopped; bool bb_required; }; struct mhi_wait_queues { - wait_queue_head_t *mhi_event_wq; - wait_queue_head_t *state_change_event; wait_queue_head_t *m0_event; wait_queue_head_t *m3_event; wait_queue_head_t *bhi_event; @@ -547,9 +544,7 @@ struct mhi_device_ctxt { struct mhi_client_handle *client_handle_list[MHI_MAX_CHANNELS]; struct mhi_event_ring_cfg *ev_ring_props; - struct task_struct *event_thread_handle; - struct task_struct *st_thread_handle; - struct tasklet_struct ev_task; /* Process control Events */ + struct work_struct st_thread_worker; struct work_struct process_m1_worker; struct mhi_wait_queues mhi_ev_wq; struct dev_mmio_info mmio_info; @@ -609,10 +604,18 @@ struct mhi_event_ring_cfg { u32 intmod; enum MHI_CLIENT_CHANNEL chan; u32 flags; + /* + * Priority of event handling: + * 0 = highest, handle events in isr (reserved for future) + * 1 = handles event using tasklet + * 2 = handles events using workerthread + */ + 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) struct mhi_data_buf { dma_addr_t bounce_buffer; @@ -670,14 +673,13 @@ 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 parse_event_thread(void *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); -int mhi_state_change_thread(void *ctxt); +void mhi_state_change_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); @@ -751,6 +753,9 @@ int set_mhi_base_state(struct mhi_device_ctxt *mhi_dev_ctxt); void mhi_set_m_state(struct mhi_device_ctxt *mhi_dev_ctxt, enum MHI_STATE new_state); const char *state_transition_str(enum STATE_TRANSITION state); -void mhi_ctrl_ev_task(unsigned long data); +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); #endif diff --git a/drivers/platform/msm/mhi/mhi_event.c b/drivers/platform/msm/mhi/mhi_event.c index 3103ade8c8d4..ae677bae63dc 100644 --- a/drivers/platform/msm/mhi/mhi_event.c +++ b/drivers/platform/msm/mhi/mhi_event.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -43,13 +43,13 @@ int mhi_populate_event_cfg(struct mhi_device_ctxt *mhi_dev_ctxt) return -ENOMEM; for (i = 0; i < mhi_dev_ctxt->mmio_info.nr_event_rings; ++i) { - u32 dt_configs[5]; - int len; + u32 dt_configs[6]; + int no_elements; scnprintf(dt_prop, MAX_BUF_SIZE, "%s%d", "mhi-event-cfg-", i); - if (!of_find_property(np, dt_prop, &len)) - goto dt_error; - if (len != sizeof(dt_configs)) + no_elements = of_property_count_elems_of_size(np, dt_prop, + sizeof(dt_configs)); + if (no_elements != 1) goto dt_error; r = of_property_read_u32_array( np, @@ -66,14 +66,16 @@ int mhi_populate_event_cfg(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_dev_ctxt->ev_ring_props[i].msi_vec = dt_configs[1]; mhi_dev_ctxt->ev_ring_props[i].intmod = dt_configs[2]; mhi_dev_ctxt->ev_ring_props[i].chan = dt_configs[3]; - mhi_dev_ctxt->ev_ring_props[i].flags = dt_configs[4]; + mhi_dev_ctxt->ev_ring_props[i].priority = dt_configs[4]; + mhi_dev_ctxt->ev_ring_props[i].flags = dt_configs[5]; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "ev ring %d,desc:0x%x,msi:0x%x,intmod%d chan:%u flags0x%x\n", + "ev ring %d,desc:0x%x,msi:0x%x,intmod%d chan:%u priority:%u flags0x%x\n", i, mhi_dev_ctxt->ev_ring_props[i].nr_desc, mhi_dev_ctxt->ev_ring_props[i].msi_vec, mhi_dev_ctxt->ev_ring_props[i].intmod, mhi_dev_ctxt->ev_ring_props[i].chan, + mhi_dev_ctxt->ev_ring_props[i].priority, mhi_dev_ctxt->ev_ring_props[i].flags); if (GET_EV_PROPS(EV_MANAGED, mhi_dev_ctxt->ev_ring_props[i].flags)) @@ -128,6 +130,9 @@ int create_local_ev_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_local_event_ctxt[i]; spin_lock_init(&mhi_ring->ring_lock); + tasklet_init(&mhi_ring->ev_task, mhi_ev_task, + (unsigned long)mhi_ring); + INIT_WORK(&mhi_ring->ev_worker, process_event_ring); } return r; @@ -157,6 +162,8 @@ void ring_ev_db(struct mhi_device_ctxt *mhi_dev_ctxt, u32 event_ring_index) static int mhi_event_ring_init(struct mhi_event_ctxt *ev_list, struct mhi_ring *ring, + struct mhi_device_ctxt *mhi_dev_ctxt, + int index, u32 el_per_ring, u32 intmodt_val, u32 msi_vec, @@ -166,6 +173,8 @@ static int mhi_event_ring_init(struct mhi_event_ctxt *ev_list, ev_list->mhi_msi_vector = msi_vec; ev_list->mhi_event_ring_len = el_per_ring*sizeof(union mhi_event_pkt); MHI_SET_EV_CTXT(EVENT_CTXT_INTMODT, ev_list, intmodt_val); + ring->mhi_dev_ctxt = mhi_dev_ctxt; + ring->index = index; ring->len = ((size_t)(el_per_ring)*sizeof(union mhi_event_pkt)); ring->el_size = sizeof(union mhi_event_pkt); ring->overwrite_en = 0; @@ -198,6 +207,7 @@ void init_event_ctxt_array(struct mhi_device_ctxt *mhi_dev_ctxt) event_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[i]; mhi_local_event_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[i]; mhi_event_ring_init(event_ctxt, mhi_local_event_ctxt, + mhi_dev_ctxt, i, mhi_dev_ctxt->ev_ring_props[i].nr_desc, mhi_dev_ctxt->ev_ring_props[i].intmod, mhi_dev_ctxt->ev_ring_props[i].msi_vec, diff --git a/drivers/platform/msm/mhi/mhi_iface.c b/drivers/platform/msm/mhi/mhi_iface.c index 50e330a6742b..4dacc33b386e 100644 --- a/drivers/platform/msm/mhi/mhi_iface.c +++ b/drivers/platform/msm/mhi/mhi_iface.c @@ -110,8 +110,6 @@ int mhi_ctxt_init(struct mhi_device_ctxt *mhi_dev_ctxt) irq_error: kfree(mhi_dev_ctxt->state_change_work_item_list.q_lock); - kfree(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq); - kfree(mhi_dev_ctxt->mhi_ev_wq.state_change_event); kfree(mhi_dev_ctxt->mhi_ev_wq.m0_event); kfree(mhi_dev_ctxt->mhi_ev_wq.m3_event); kfree(mhi_dev_ctxt->mhi_ev_wq.bhi_event); @@ -190,12 +188,10 @@ static int mhi_pci_probe(struct pci_dev *pcie_device, pcie_device->dev.of_node = plat_dev->dev.of_node; 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); mutex_init(&mhi_dev_ctxt->pm_lock); rwlock_init(&mhi_dev_ctxt->pm_xfer_lock); spin_lock_init(&mhi_dev_ctxt->dev_wake_lock); - tasklet_init(&mhi_dev_ctxt->ev_task, - mhi_ctrl_ev_task, - (unsigned long)mhi_dev_ctxt); init_completion(&mhi_dev_ctxt->cmd_complete); mhi_dev_ctxt->flags.link_up = 1; diff --git a/drivers/platform/msm/mhi/mhi_init.c b/drivers/platform/msm/mhi/mhi_init.c index e6bf75d9d7e7..b6edf707798b 100644 --- a/drivers/platform/msm/mhi/mhi_init.c +++ b/drivers/platform/msm/mhi/mhi_init.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -250,19 +250,6 @@ err_ev_alloc: static int mhi_init_events(struct mhi_device_ctxt *mhi_dev_ctxt) { - mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq = kmalloc( - sizeof(wait_queue_head_t), - GFP_KERNEL); - if (NULL == mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq) { - mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Failed to init event"); - return -ENOMEM; - } - mhi_dev_ctxt->mhi_ev_wq.state_change_event = - kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); - if (NULL == mhi_dev_ctxt->mhi_ev_wq.state_change_event) { - mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Failed to init event"); - goto error_event_handle_alloc; - } /* Initialize the event which signals M0 */ mhi_dev_ctxt->mhi_ev_wq.m0_event = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); @@ -284,10 +271,7 @@ static int mhi_init_events(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, "Failed to init event"); goto error_bhi_event; } - /* Initialize the event which starts the event parsing thread */ - init_waitqueue_head(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq); - /* Initialize the event which starts the state change thread */ - init_waitqueue_head(mhi_dev_ctxt->mhi_ev_wq.state_change_event); + /* Initialize the event which triggers clients waiting to send */ init_waitqueue_head(mhi_dev_ctxt->mhi_ev_wq.m0_event); /* Initialize the event which triggers D3hot */ @@ -300,9 +284,6 @@ error_bhi_event: error_m0_event: kfree(mhi_dev_ctxt->mhi_ev_wq.m0_event); error_state_change_event_handle: - kfree(mhi_dev_ctxt->mhi_ev_wq.state_change_event); -error_event_handle_alloc: - kfree(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq); return -ENOMEM; } @@ -339,21 +320,6 @@ static void mhi_init_wakelock(struct mhi_device_ctxt *mhi_dev_ctxt) wakeup_source_init(&mhi_dev_ctxt->w_lock, "mhi_wakeup_source"); } -static int mhi_spawn_threads(struct mhi_device_ctxt *mhi_dev_ctxt) -{ - mhi_dev_ctxt->event_thread_handle = kthread_run(parse_event_thread, - mhi_dev_ctxt, - "mhi_ev_thrd"); - if (IS_ERR(mhi_dev_ctxt->event_thread_handle)) - return PTR_ERR(mhi_dev_ctxt->event_thread_handle); - mhi_dev_ctxt->st_thread_handle = kthread_run(mhi_state_change_thread, - mhi_dev_ctxt, - "mhi_st_thrd"); - if (IS_ERR(mhi_dev_ctxt->event_thread_handle)) - return PTR_ERR(mhi_dev_ctxt->event_thread_handle); - return 0; -} - /** * @brief Main initialization function for a mhi struct device context * All threads, events mutexes, mhi specific data structures @@ -408,21 +374,11 @@ int mhi_init_device_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt) init_event_ctxt_array(mhi_dev_ctxt); mhi_dev_ctxt->mhi_state = MHI_STATE_RESET; - r = mhi_spawn_threads(mhi_dev_ctxt); - if (r) { - mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, - "Failed to spawn threads ret %d\n", r); - goto error_during_thread_spawn; - } mhi_init_wakelock(mhi_dev_ctxt); return r; -error_during_thread_spawn: - kfree(mhi_dev_ctxt->state_change_work_item_list.q_lock); error_during_thread_init: - kfree(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq); - kfree(mhi_dev_ctxt->mhi_ev_wq.state_change_event); kfree(mhi_dev_ctxt->mhi_ev_wq.m0_event); kfree(mhi_dev_ctxt->mhi_ev_wq.m3_event); kfree(mhi_dev_ctxt->mhi_ev_wq.bhi_event); diff --git a/drivers/platform/msm/mhi/mhi_isr.c b/drivers/platform/msm/mhi/mhi_isr.c index 5bd0dcf300d7..95efe62eb8d4 100644 --- a/drivers/platform/msm/mhi/mhi_isr.c +++ b/drivers/platform/msm/mhi/mhi_isr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -125,8 +125,11 @@ static int mhi_process_event_ring( "MHI STE received ring 0x%x State:%s\n", ev_index, state_transition_str(new_state)); - /* If transitioning to M1 schedule worker thread */ - if (new_state == STATE_TRANSITION_M1) { + switch (new_state) { + case STATE_TRANSITION_M0: + process_m0_transition(mhi_dev_ctxt); + break; + case STATE_TRANSITION_M1: write_lock_irqsave(&mhi_dev_ctxt->pm_xfer_lock, flags); mhi_dev_ctxt->mhi_state = @@ -140,9 +143,15 @@ static int mhi_process_event_ring( write_unlock_irqrestore(&mhi_dev_ctxt-> pm_xfer_lock, flags); - } else { - mhi_init_state_transition(mhi_dev_ctxt, - new_state); + break; + case STATE_TRANSITION_M3: + process_m3_transition(mhi_dev_ctxt); + break; + default: + mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR, + "Unsupported STE received ring 0x%x State:%s\n", + ev_index, + state_transition_str(new_state)); } break; } @@ -207,84 +216,39 @@ static int mhi_process_event_ring( return ret_val; } -int parse_event_thread(void *ctxt) +void mhi_ev_task(unsigned long data) { - struct mhi_device_ctxt *mhi_dev_ctxt = ctxt; - u32 i = 0; - int ret_val = 0; - int ret_val_process_event = 0; - atomic_t *ev_pen_ptr = &mhi_dev_ctxt->counters.events_pending; + struct mhi_ring *mhi_ring = (struct mhi_ring *)data; + struct mhi_device_ctxt *mhi_dev_ctxt = + mhi_ring->mhi_dev_ctxt; + int ev_index = mhi_ring->index; + struct mhi_event_ring_cfg *ring_props = + &mhi_dev_ctxt->ev_ring_props[ev_index]; - /* Go through all event rings */ - for (;;) { - ret_val = - wait_event_interruptible( - *mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq, - ((atomic_read( - &mhi_dev_ctxt->counters.events_pending) > 0) && - !mhi_dev_ctxt->flags.stop_threads) || - mhi_dev_ctxt->flags.kill_threads || - (mhi_dev_ctxt->flags.stop_threads && - !mhi_dev_ctxt->flags.ev_thread_stopped)); + mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Enter\n"); + /* Process event ring */ + mhi_process_event_ring(mhi_dev_ctxt, ev_index, ring_props->nr_desc); - switch (ret_val) { - case -ERESTARTSYS: - return 0; - default: - if (mhi_dev_ctxt->flags.kill_threads) { - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Caught exit signal, quitting\n"); - return 0; - } - if (mhi_dev_ctxt->flags.stop_threads) { - mhi_dev_ctxt->flags.ev_thread_stopped = 1; - continue; - } - break; - } - mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "awake\n"); - mhi_dev_ctxt->flags.ev_thread_stopped = 0; - atomic_dec(&mhi_dev_ctxt->counters.events_pending); - for (i = 1; i < mhi_dev_ctxt->mmio_info.nr_event_rings; ++i) { - if (mhi_dev_ctxt->mhi_state == MHI_STATE_SYS_ERR) { - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "SYS_ERR detected, not processing events\n"); - atomic_set(&mhi_dev_ctxt-> - counters.events_pending, - 0); - break; - } - if (GET_EV_PROPS(EV_MANAGED, - mhi_dev_ctxt->ev_ring_props[i].flags)) { - ret_val_process_event = - mhi_process_event_ring(mhi_dev_ctxt, - i, - mhi_dev_ctxt-> - ev_ring_props[i].nr_desc); - if (ret_val_process_event == -EINPROGRESS) - atomic_inc(ev_pen_ptr); - } - } - mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "sleep\n"); - } + enable_irq(MSI_TO_IRQ(mhi_dev_ctxt, ev_index)); + mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Exit\n"); } -void mhi_ctrl_ev_task(unsigned long data) +void process_event_ring(struct work_struct *work) { + struct mhi_ring *mhi_ring = + container_of(work, struct mhi_ring, ev_worker); struct mhi_device_ctxt *mhi_dev_ctxt = - (struct mhi_device_ctxt *)data; - const unsigned CTRL_EV_RING = 0; + mhi_ring->mhi_dev_ctxt; + int ev_index = mhi_ring->index; struct mhi_event_ring_cfg *ring_props = - &mhi_dev_ctxt->ev_ring_props[CTRL_EV_RING]; + &mhi_dev_ctxt->ev_ring_props[ev_index]; mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Enter\n"); - /* Process control event ring */ - mhi_process_event_ring(mhi_dev_ctxt, - CTRL_EV_RING, - ring_props->nr_desc); - enable_irq(MSI_TO_IRQ(mhi_dev_ctxt, CTRL_EV_RING)); - mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Exit\n"); + /* Process event ring */ + mhi_process_event_ring(mhi_dev_ctxt, ev_index, ring_props->nr_desc); + enable_irq(MSI_TO_IRQ(mhi_dev_ctxt, ev_index)); + mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Exit\n"); } struct mhi_result *mhi_poll(struct mhi_client_handle *client_handle) @@ -332,19 +296,19 @@ irqreturn_t mhi_msi_handlr(int irq_number, void *dev_id) { struct mhi_device_ctxt *mhi_dev_ctxt = dev_id; int msi = IRQ_TO_MSI(mhi_dev_ctxt, irq_number); + struct mhi_ring *mhi_ring = &mhi_dev_ctxt->mhi_local_event_ctxt[msi]; + struct mhi_event_ring_cfg *ring_props = + &mhi_dev_ctxt->ev_ring_props[msi]; mhi_dev_ctxt->counters.msi_counter[ IRQ_TO_MSI(mhi_dev_ctxt, irq_number)]++; mhi_log(mhi_dev_ctxt, MHI_MSG_VERBOSE, "Got MSI 0x%x\n", msi); trace_mhi_msi(IRQ_TO_MSI(mhi_dev_ctxt, irq_number)); - - if (msi) { - atomic_inc(&mhi_dev_ctxt->counters.events_pending); - wake_up_interruptible(mhi_dev_ctxt->mhi_ev_wq.mhi_event_wq); - } else { - disable_irq_nosync(irq_number); - tasklet_schedule(&mhi_dev_ctxt->ev_task); - } + disable_irq_nosync(irq_number); + if (ring_props->priority <= MHI_EV_PRIORITY_TASKLET) + tasklet_schedule(&mhi_ring->ev_task); + else + schedule_work(&mhi_ring->ev_worker); return IRQ_HANDLED; } diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index 889c4708692e..66d56bdd8f85 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -1788,11 +1788,10 @@ int mhi_register_device(struct mhi_device *mhi_device, mhi_dev_ctxt->pcie_device = pci_dev; 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); mutex_init(&mhi_dev_ctxt->pm_lock); rwlock_init(&mhi_dev_ctxt->pm_xfer_lock); spin_lock_init(&mhi_dev_ctxt->dev_wake_lock); - tasklet_init(&mhi_dev_ctxt->ev_task, mhi_ctrl_ev_task, - (unsigned long)mhi_dev_ctxt); init_completion(&mhi_dev_ctxt->cmd_complete); mhi_dev_ctxt->flags.link_up = 1; core_info = &mhi_dev_ctxt->core; diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index 707c5b3b7dbc..a4da6c21b50d 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -169,10 +169,9 @@ static int process_bhie_transition(struct mhi_device_ctxt *mhi_dev_ctxt, return 0; } -static int process_m0_transition( - struct mhi_device_ctxt *mhi_dev_ctxt, - enum STATE_TRANSITION cur_work_item) +int process_m0_transition(struct mhi_device_ctxt *mhi_dev_ctxt) { + unsigned long flags; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered With State %s\n", @@ -189,10 +188,10 @@ static int process_m0_transition( break; } - write_lock_irq(&mhi_dev_ctxt->pm_xfer_lock); + write_lock_irqsave(&mhi_dev_ctxt->pm_xfer_lock, flags); mhi_dev_ctxt->mhi_state = MHI_STATE_M0; mhi_dev_ctxt->mhi_pm_state = MHI_PM_M0; - write_unlock_irq(&mhi_dev_ctxt->pm_xfer_lock); + write_unlock_irqrestore(&mhi_dev_ctxt->pm_xfer_lock, flags); read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); mhi_dev_ctxt->assert_wake(mhi_dev_ctxt, true); @@ -266,11 +265,9 @@ void process_m1_transition(struct work_struct *work) mutex_unlock(&mhi_dev_ctxt->pm_lock); } -static int process_m3_transition( - struct mhi_device_ctxt *mhi_dev_ctxt, - enum STATE_TRANSITION cur_work_item) +int process_m3_transition(struct mhi_device_ctxt *mhi_dev_ctxt) { - + unsigned long flags; mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Entered with State %s\n", TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); @@ -286,34 +283,14 @@ static int process_m3_transition( break; } - write_lock_irq(&mhi_dev_ctxt->pm_xfer_lock); + write_lock_irqsave(&mhi_dev_ctxt->pm_xfer_lock, flags); mhi_dev_ctxt->mhi_state = MHI_STATE_M3; mhi_dev_ctxt->mhi_pm_state = MHI_PM_M3; - write_unlock_irq(&mhi_dev_ctxt->pm_xfer_lock); + write_unlock_irqrestore(&mhi_dev_ctxt->pm_xfer_lock, flags); wake_up(mhi_dev_ctxt->mhi_ev_wq.m3_event); return 0; } -static int process_link_down_transition( - struct mhi_device_ctxt *mhi_dev_ctxt, - enum STATE_TRANSITION cur_work_item) -{ - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Entered with State %s\n", - TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); - return -EIO; -} - -static int process_wake_transition( - struct mhi_device_ctxt *mhi_dev_ctxt, - enum STATE_TRANSITION cur_work_item) -{ - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Entered with State %s\n", - TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); - return -EIO; -} - static int process_bhi_transition( struct mhi_device_ctxt *mhi_dev_ctxt, enum STATE_TRANSITION cur_work_item) @@ -364,7 +341,6 @@ static int process_ready_transition( } write_lock_irq(&mhi_dev_ctxt->pm_xfer_lock); - mhi_dev_ctxt->flags.stop_threads = 0; mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.mmio_addr, MHICTRL, MHICTRL_MHISTATE_MASK, @@ -439,16 +415,6 @@ static int process_reset_transition( return r; } -static int process_syserr_transition( - struct mhi_device_ctxt *mhi_dev_ctxt, - enum STATE_TRANSITION cur_work_item) -{ - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Entered with State %s\n", - TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); - return -EIO; -} - static void enable_clients(struct mhi_device_ctxt *mhi_dev_ctxt, enum MHI_EXEC_ENV exec_env) { @@ -510,9 +476,6 @@ static int process_amss_transition( mhi_dev_ctxt->deassert_wake(mhi_dev_ctxt); return r; } - read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); - ring_all_chan_dbs(mhi_dev_ctxt, true); - read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, "Notifying clients that MHI is enabled\n"); enable_clients(mhi_dev_ctxt, mhi_dev_ctxt->dev_exec_env); @@ -521,9 +484,6 @@ static int process_amss_transition( "MHI is initialized\n"); } - read_lock_bh(&mhi_dev_ctxt->pm_xfer_lock); - ring_all_ev_dbs(mhi_dev_ctxt); - read_unlock_bh(&mhi_dev_ctxt->pm_xfer_lock); complete(&mhi_dev_ctxt->cmd_complete); /* @@ -574,23 +534,6 @@ static int process_stt_work_item( case STATE_TRANSITION_AMSS: r = process_amss_transition(mhi_dev_ctxt, cur_work_item); break; - case STATE_TRANSITION_M0: - r = process_m0_transition(mhi_dev_ctxt, cur_work_item); - break; - case STATE_TRANSITION_M3: - r = process_m3_transition(mhi_dev_ctxt, cur_work_item); - break; - case STATE_TRANSITION_SYS_ERR: - r = process_syserr_transition(mhi_dev_ctxt, - cur_work_item); - break; - case STATE_TRANSITION_LINK_DOWN: - r = process_link_down_transition(mhi_dev_ctxt, - cur_work_item); - break; - case STATE_TRANSITION_WAKE: - r = process_wake_transition(mhi_dev_ctxt, cur_work_item); - break; case STATE_TRANSITION_BHIE: r = process_bhie_transition(mhi_dev_ctxt, cur_work_item); break; @@ -603,42 +546,26 @@ static int process_stt_work_item( return r; } -int mhi_state_change_thread(void *ctxt) +void mhi_state_change_worker(struct work_struct *work) { int r = 0; - unsigned long flags = 0; - struct mhi_device_ctxt *mhi_dev_ctxt = (struct mhi_device_ctxt *)ctxt; + struct mhi_device_ctxt *mhi_dev_ctxt = container_of(work, + struct mhi_device_ctxt, + st_thread_worker); enum STATE_TRANSITION cur_work_item; struct mhi_state_work_queue *work_q = &mhi_dev_ctxt->state_change_work_item_list; struct mhi_ring *state_change_q = &work_q->q_info; - for (;;) { - r = wait_event_interruptible( - *mhi_dev_ctxt->mhi_ev_wq.state_change_event, - ((work_q->q_info.rp != work_q->q_info.wp) && - !mhi_dev_ctxt->flags.st_thread_stopped)); - if (r) { - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Caught signal %d, quitting\n", r); - return 0; - } - - if (mhi_dev_ctxt->flags.kill_threads) { - mhi_log(mhi_dev_ctxt, MHI_MSG_INFO, - "Caught exit signal, quitting\n"); - return 0; - } - mhi_dev_ctxt->flags.st_thread_stopped = 0; - spin_lock_irqsave(work_q->q_lock, flags); + while (work_q->q_info.rp != work_q->q_info.wp) { + spin_lock_irq(work_q->q_lock); cur_work_item = *(enum STATE_TRANSITION *)(state_change_q->rp); r = ctxt_del_element(&work_q->q_info, NULL); MHI_ASSERT(r == 0, "Failed to delete element from STT workqueue\n"); - spin_unlock_irqrestore(work_q->q_lock, flags); + spin_unlock_irq(work_q->q_lock); r = process_stt_work_item(mhi_dev_ctxt, cur_work_item); } - return 0; } /** @@ -673,6 +600,6 @@ int mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt, r = ctxt_add_element(stt_ring, (void **)&cur_work_item); BUG_ON(r); spin_unlock_irqrestore(work_q->q_lock, flags); - wake_up_interruptible(mhi_dev_ctxt->mhi_ev_wq.state_change_event); + schedule_work(&mhi_dev_ctxt->st_thread_worker); return r; } |
