Lines Matching +full:mmio +full:- +full:mux

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-21 Intel Corporation.
16 return chnl->ctype == IPC_CTYPE_WWAN && in ipc_imem_check_wwan_ips()
17 chnl->if_id == IPC_MEM_MUX_IP_CH_IF_ID; in ipc_imem_check_wwan_ips()
28 ipc_imem->device_sleep = state; in ipc_imem_msg_send_device_sleep()
30 return ipc_protocol_tq_msg_send(ipc_imem->ipc_protocol, in ipc_imem_msg_send_device_sleep()
38 if (pipe->nr_of_queued_entries >= pipe->max_nr_of_queued_entries) in ipc_imem_dl_skb_alloc()
41 return ipc_protocol_dl_td_prepare(ipc_imem->ipc_protocol, pipe); in ipc_imem_dl_skb_alloc()
55 struct ipc_pipe *pipe = &ipc_imem->channels[i].dl_pipe; in ipc_imem_tq_td_alloc_timer()
57 if (!pipe->is_open || pipe->nr_of_queued_entries > 0) in ipc_imem_tq_td_alloc_timer()
63 if (pipe->nr_of_queued_entries == 0) in ipc_imem_tq_td_alloc_timer()
68 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_tq_td_alloc_timer()
72 ipc_imem->hrtimer_period = in ipc_imem_tq_td_alloc_timer()
74 if (!hrtimer_active(&ipc_imem->td_alloc_timer)) in ipc_imem_tq_td_alloc_timer()
75 hrtimer_start(&ipc_imem->td_alloc_timer, in ipc_imem_tq_td_alloc_timer()
76 ipc_imem->hrtimer_period, in ipc_imem_tq_td_alloc_timer()
96 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_tq_fast_update_timer_cb()
116 ipc_mmio_update_cp_capability(ipc_imem->mmio); in ipc_imem_setup_cp_mux_cap_init()
118 if (!ipc_imem->mmio->has_mux_lite) { in ipc_imem_setup_cp_mux_cap_init()
119 dev_err(ipc_imem->dev, "Failed to get Mux capability."); in ipc_imem_setup_cp_mux_cap_init()
120 return -EINVAL; in ipc_imem_setup_cp_mux_cap_init()
123 cfg->protocol = MUX_LITE; in ipc_imem_setup_cp_mux_cap_init()
125 cfg->ul_flow = (ipc_imem->mmio->has_ul_flow_credit == 1) ? in ipc_imem_setup_cp_mux_cap_init()
132 cfg->instance_id = IPC_MEM_MUX_IP_CH_IF_ID; in ipc_imem_setup_cp_mux_cap_init()
133 cfg->nr_sessions = IPC_MEM_MUX_IP_SESSION_ENTRIES; in ipc_imem_setup_cp_mux_cap_init()
145 ipc_protocol_tq_msg_send(ipc_imem->ipc_protocol, in ipc_imem_msg_send_feature_set()
149 ipc_protocol_msg_send(ipc_imem->ipc_protocol, in ipc_imem_msg_send_feature_set()
156 if (!ipc_imem->enter_runtime || ipc_imem->td_update_timer_suspended) { in ipc_imem_td_update_timer_start()
158 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_td_update_timer_start()
163 if (!hrtimer_active(&ipc_imem->tdupdate_timer)) { in ipc_imem_td_update_timer_start()
164 ipc_imem->hrtimer_period = in ipc_imem_td_update_timer_start()
166 if (!hrtimer_active(&ipc_imem->tdupdate_timer)) in ipc_imem_td_update_timer_start()
167 hrtimer_start(&ipc_imem->tdupdate_timer, in ipc_imem_td_update_timer_start()
168 ipc_imem->hrtimer_period, in ipc_imem_td_update_timer_start()
189 for (i = 0; i < ipc_imem->nr_of_channels; i++) { in ipc_imem_ul_write_td()
190 channel = &ipc_imem->channels[i]; in ipc_imem_ul_write_td()
192 if (channel->state != IMEM_CHANNEL_ACTIVE) in ipc_imem_ul_write_td()
195 pipe = &channel->ul_pipe; in ipc_imem_ul_write_td()
198 ul_list = &channel->ul_list; in ipc_imem_ul_write_td()
201 hpda_pending |= ipc_protocol_ul_td_send(ipc_imem->ipc_protocol, in ipc_imem_ul_write_td()
211 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_ul_write_td()
222 ipc_imem->ipc_requested_state = IPC_MEM_DEVICE_IPC_INIT; in ipc_imem_ipc_init_check()
225 ipc_doorbell_fire(ipc_imem->pcie, IPC_DOORBELL_IRQ_IPC, in ipc_imem_ipc_init_check()
229 if (ipc_mmio_get_ipc_state(ipc_imem->mmio) == in ipc_imem_ipc_init_check()
230 ipc_imem->ipc_requested_state) { in ipc_imem_ipc_init_check()
231 /* Prepare the MMIO space */ in ipc_imem_ipc_init_check()
232 ipc_mmio_config(ipc_imem->mmio); in ipc_imem_ipc_init_check()
235 ipc_imem->ipc_requested_state = in ipc_imem_ipc_init_check()
237 ipc_doorbell_fire(ipc_imem->pcie, IPC_DOORBELL_IRQ_IPC, in ipc_imem_ipc_init_check()
243 } while (--timeout); in ipc_imem_ipc_init_check()
246 dev_err(ipc_imem->dev, "%s: ipc_status(%d) ne. IPC_MEM_DEVICE_IPC_INIT", in ipc_imem_ipc_init_check()
247 ipc_imem_phase_get_string(ipc_imem->phase), in ipc_imem_ipc_init_check()
248 ipc_mmio_get_ipc_state(ipc_imem->mmio)); in ipc_imem_ipc_init_check()
250 ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_TIMEOUT); in ipc_imem_ipc_init_check()
263 switch (pipe->channel->ctype) { in ipc_imem_dl_skb_process()
265 port_id = pipe->channel->channel_id; in ipc_imem_dl_skb_process()
268 wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, skb); in ipc_imem_dl_skb_process()
272 if (pipe->channel->if_id == IPC_MEM_MUX_IP_CH_IF_ID) in ipc_imem_dl_skb_process()
273 ipc_mux_dl_decode(ipc_imem->mux, skb); in ipc_imem_dl_skb_process()
276 dev_err(ipc_imem->dev, "Invalid channel type"); in ipc_imem_dl_skb_process()
291 channel = pipe->channel; in ipc_imem_dl_pipe_process()
293 ipc_protocol_get_head_tail_index(ipc_imem->ipc_protocol, pipe, &head, in ipc_imem_dl_pipe_process()
295 if (pipe->old_tail != tail) { in ipc_imem_dl_pipe_process()
296 if (pipe->old_tail < tail) in ipc_imem_dl_pipe_process()
297 cnt = tail - pipe->old_tail; in ipc_imem_dl_pipe_process()
299 cnt = pipe->nr_of_entries - pipe->old_tail + tail; in ipc_imem_dl_pipe_process()
305 while (cnt--) { in ipc_imem_dl_pipe_process()
306 skb = ipc_protocol_dl_td_process(ipc_imem->ipc_protocol, pipe); in ipc_imem_dl_pipe_process()
312 /* try to allocate new empty DL SKbs from head..tail - 1*/ in ipc_imem_dl_pipe_process()
318 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_dl_pipe_process()
323 ipc_imem_hrtimer_stop(&ipc_imem->fast_update_timer); in ipc_imem_dl_pipe_process()
330 if (processed && (processed_td_cnt == pipe->nr_of_entries - 1)) { in ipc_imem_dl_pipe_process()
331 ipc_imem->hrtimer_period = in ipc_imem_dl_pipe_process()
333 hrtimer_start(&ipc_imem->fast_update_timer, in ipc_imem_dl_pipe_process()
334 ipc_imem->hrtimer_period, HRTIMER_MODE_REL); in ipc_imem_dl_pipe_process()
337 if (ipc_imem->app_notify_dl_pend) in ipc_imem_dl_pipe_process()
338 complete(&ipc_imem->dl_pend_sem); in ipc_imem_dl_pipe_process()
350 channel = pipe->channel; in ipc_imem_ul_pipe_process()
353 ipc_protocol_get_head_tail_index(ipc_imem->ipc_protocol, pipe, &head, in ipc_imem_ul_pipe_process()
356 if (pipe->old_tail != tail) { in ipc_imem_ul_pipe_process()
357 if (pipe->old_tail < tail) in ipc_imem_ul_pipe_process()
358 cnt = tail - pipe->old_tail; in ipc_imem_ul_pipe_process()
360 cnt = pipe->nr_of_entries - pipe->old_tail + tail; in ipc_imem_ul_pipe_process()
364 while (cnt--) { in ipc_imem_ul_pipe_process()
365 skb = ipc_protocol_ul_td_process(ipc_imem->ipc_protocol, pipe); in ipc_imem_ul_pipe_process()
370 /* If the user app was suspended in uplink direction - blocking in ipc_imem_ul_pipe_process()
373 if (IPC_CB(skb)->op_type == UL_USR_OP_BLOCKED) in ipc_imem_ul_pipe_process()
374 complete(&channel->ul_sem); in ipc_imem_ul_pipe_process()
377 if (IPC_CB(skb)->op_type == UL_MUX_OP_ADB) { in ipc_imem_ul_pipe_process()
378 if (channel->if_id == IPC_MEM_MUX_IP_CH_IF_ID) in ipc_imem_ul_pipe_process()
379 ipc_mux_ul_encoded_process(ipc_imem->mux, skb); in ipc_imem_ul_pipe_process()
381 dev_err(ipc_imem->dev, in ipc_imem_ul_pipe_process()
383 channel->if_id); in ipc_imem_ul_pipe_process()
385 ipc_pcie_kfree_skb(ipc_imem->pcie, skb); in ipc_imem_ul_pipe_process()
390 if (ipc_imem_check_wwan_ips(pipe->channel)) in ipc_imem_ul_pipe_process()
391 ipc_mux_check_n_restart_tx(ipc_imem->mux); in ipc_imem_ul_pipe_process()
393 if (ipc_imem->app_notify_ul_pend) in ipc_imem_ul_pipe_process()
394 complete(&ipc_imem->ul_pend_sem); in ipc_imem_ul_pipe_process()
402 if (ipc_imem->flash_channel_id < 0) { in ipc_imem_rom_irq_exec()
403 ipc_imem->rom_exit_code = IMEM_ROM_EXIT_FAIL; in ipc_imem_rom_irq_exec()
404 dev_err(ipc_imem->dev, "Missing flash app:%d", in ipc_imem_rom_irq_exec()
405 ipc_imem->flash_channel_id); in ipc_imem_rom_irq_exec()
409 ipc_imem->rom_exit_code = ipc_mmio_get_rom_exit_code(ipc_imem->mmio); in ipc_imem_rom_irq_exec()
414 channel = &ipc_imem->channels[ipc_imem->flash_channel_id]; in ipc_imem_rom_irq_exec()
415 complete(&channel->ul_sem); in ipc_imem_rom_irq_exec()
422 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, in ipc_imem_tq_td_update_timer_cb()
431 if (ipc_protocol_pm_dev_sleep_handle(ipc_imem->ipc_protocol) && in ipc_imem_slp_control_exec()
432 hrtimer_active(&ipc_imem->tdupdate_timer)) { in ipc_imem_slp_control_exec()
436 ipc_imem_hrtimer_stop(&ipc_imem->tdupdate_timer); in ipc_imem_slp_control_exec()
438 ipc_imem_hrtimer_stop(&ipc_imem->fast_update_timer); in ipc_imem_slp_control_exec()
448 return -EIO; in ipc_imem_tq_startup_timer_cb()
450 if (ipc_mmio_get_ipc_state(ipc_imem->mmio) == in ipc_imem_tq_startup_timer_cb()
452 ipc_imem->ipc_requested_state = IPC_MEM_DEVICE_IPC_INIT; in ipc_imem_tq_startup_timer_cb()
454 ipc_doorbell_fire(ipc_imem->pcie, IPC_DOORBELL_IRQ_IPC, in ipc_imem_tq_startup_timer_cb()
457 ipc_imem->hrtimer_period = ktime_set(0, 100 * 1000UL * 1000ULL); in ipc_imem_tq_startup_timer_cb()
458 /* reduce period to 100 ms to check for mmio init state */ in ipc_imem_tq_startup_timer_cb()
459 if (!hrtimer_active(&ipc_imem->startup_timer)) in ipc_imem_tq_startup_timer_cb()
460 hrtimer_start(&ipc_imem->startup_timer, in ipc_imem_tq_startup_timer_cb()
461 ipc_imem->hrtimer_period, in ipc_imem_tq_startup_timer_cb()
463 } else if (ipc_mmio_get_ipc_state(ipc_imem->mmio) == in ipc_imem_tq_startup_timer_cb()
465 /* Startup complete - disable timer */ in ipc_imem_tq_startup_timer_cb()
466 ipc_imem_hrtimer_stop(&ipc_imem->startup_timer); in ipc_imem_tq_startup_timer_cb()
468 /* Prepare the MMIO space */ in ipc_imem_tq_startup_timer_cb()
469 ipc_mmio_config(ipc_imem->mmio); in ipc_imem_tq_startup_timer_cb()
470 ipc_imem->ipc_requested_state = IPC_MEM_DEVICE_IPC_RUNNING; in ipc_imem_tq_startup_timer_cb()
471 ipc_doorbell_fire(ipc_imem->pcie, IPC_DOORBELL_IRQ_IPC, in ipc_imem_tq_startup_timer_cb()
484 if (ktime_to_ns(ipc_imem->hrtimer_period)) { in ipc_imem_startup_timer_cb()
485 hrtimer_forward(&ipc_imem->startup_timer, ktime_get(), in ipc_imem_startup_timer_cb()
486 ipc_imem->hrtimer_period); in ipc_imem_startup_timer_cb()
499 return (ipc_imem->phase == IPC_P_RUN && in ipc_imem_get_exec_stage_buffered()
500 ipc_imem->ipc_status == IPC_MEM_DEVICE_IPC_RUNNING) ? in ipc_imem_get_exec_stage_buffered()
501 ipc_protocol_get_ap_exec_stage(ipc_imem->ipc_protocol) : in ipc_imem_get_exec_stage_buffered()
502 ipc_mmio_get_exec_stage(ipc_imem->mmio); in ipc_imem_get_exec_stage_buffered()
513 ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_READY); in ipc_imem_send_mdm_rdy_cb()
530 if (ipc_imem->phase != IPC_P_RUN) { in ipc_imem_run_state_worker()
531 dev_err(ipc_imem->dev, in ipc_imem_run_state_worker()
537 ipc_imem->mux = ipc_mux_init(&mux_cfg, ipc_imem); in ipc_imem_run_state_worker()
540 if (ipc_imem->mux) in ipc_imem_run_state_worker()
541 ipc_imem->mux->wwan = ipc_imem->wwan; in ipc_imem_run_state_worker()
545 ipc_imem->ipc_port[ctrl_chl_idx] = NULL; in ipc_imem_run_state_worker()
550 ipc_imem->ipc_port[ctrl_chl_idx] = in ipc_imem_run_state_worker()
563 set_bit(FULLY_FUNCTIONAL, &ipc_imem->flag); in ipc_imem_run_state_worker()
578 ipc_imem->ev_irq_pending[irq] = false; in ipc_imem_handle_irq()
581 old_phase = ipc_imem->phase; in ipc_imem_handle_irq()
584 dev_dbg(ipc_imem->dev, in ipc_imem_handle_irq()
595 if (!ipc_imem->enter_runtime) { in ipc_imem_handle_irq()
597 ipc_imem->enter_runtime = 1; in ipc_imem_handle_irq()
603 ipc_imem->device_sleep); in ipc_imem_handle_irq()
611 ipc_protocol_get_ipc_status(ipc_imem->ipc_protocol); in ipc_imem_handle_irq()
614 if (ipc_imem->ipc_status != curr_ipc_status) { in ipc_imem_handle_irq()
615 ipc_imem->ipc_status = curr_ipc_status; in ipc_imem_handle_irq()
617 if (ipc_imem->ipc_status == in ipc_imem_handle_irq()
619 schedule_work(&ipc_imem->run_state_worker); in ipc_imem_handle_irq()
630 dev_err(ipc_imem->dev, "confused phase %s", in ipc_imem_handle_irq()
658 struct ipc_pipe *ul_pipe = &ipc_imem->channels[i].ul_pipe; in ipc_imem_handle_irq()
659 struct ipc_pipe *dl_pipe = &ipc_imem->channels[i].dl_pipe; in ipc_imem_handle_irq()
661 if (dl_pipe->is_open && in ipc_imem_handle_irq()
662 (irq == IMEM_IRQ_DONT_CARE || irq == dl_pipe->irq)) { in ipc_imem_handle_irq()
665 if (dl_pipe->nr_of_queued_entries == 0) in ipc_imem_handle_irq()
669 if (ul_pipe->is_open) in ipc_imem_handle_irq()
674 if (ipc_mux_ul_data_encode(ipc_imem->mux)) in ipc_imem_handle_irq()
684 ipc_imem->hrtimer_period = in ipc_imem_handle_irq()
686 if (!hrtimer_active(&ipc_imem->tdupdate_timer)) in ipc_imem_handle_irq()
687 hrtimer_start(&ipc_imem->tdupdate_timer, in ipc_imem_handle_irq()
688 ipc_imem->hrtimer_period, in ipc_imem_handle_irq()
697 ipc_imem->ipc_requested_state == IPC_MEM_DEVICE_IPC_RUNNING && in ipc_imem_handle_irq()
698 ipc_mmio_get_ipc_state(ipc_imem->mmio) == in ipc_imem_handle_irq()
700 ipc_imem->flash_channel_id >= 0) { in ipc_imem_handle_irq()
702 ch_id = ipc_imem->flash_channel_id; in ipc_imem_handle_irq()
703 complete(&ipc_imem->channels[ch_id].ul_sem); in ipc_imem_handle_irq()
707 ipc_imem->ipc_requested_state = IPC_MEM_DEVICE_IPC_DONT_CARE; in ipc_imem_handle_irq()
710 ipc_imem->hrtimer_period = in ipc_imem_handle_irq()
712 if (!hrtimer_active(&ipc_imem->td_alloc_timer)) in ipc_imem_handle_irq()
713 hrtimer_start(&ipc_imem->td_alloc_timer, in ipc_imem_handle_irq()
714 ipc_imem->hrtimer_period, in ipc_imem_handle_irq()
741 if (ipc_imem->phase != IPC_P_ROM) { in ipc_imem_phase_update_check()
743 ipc_uevent_send(ipc_imem->dev, UEVENT_ROM_READY); in ipc_imem_phase_update_check()
746 ipc_imem->phase = IPC_P_ROM; in ipc_imem_phase_update_check()
750 ipc_imem->phase = IPC_P_PSI; in ipc_imem_phase_update_check()
754 ipc_imem->phase = IPC_P_EBL; in ipc_imem_phase_update_check()
758 if (ipc_imem->phase != IPC_P_RUN && in ipc_imem_phase_update_check()
759 ipc_imem->ipc_status == IPC_MEM_DEVICE_IPC_RUNNING) { in ipc_imem_phase_update_check()
760 ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_READY); in ipc_imem_phase_update_check()
762 ipc_imem->phase = IPC_P_RUN; in ipc_imem_phase_update_check()
766 if (ipc_imem->phase != IPC_P_CRASH) in ipc_imem_phase_update_check()
767 ipc_uevent_send(ipc_imem->dev, UEVENT_CRASH); in ipc_imem_phase_update_check()
769 ipc_imem->phase = IPC_P_CRASH; in ipc_imem_phase_update_check()
773 if (ipc_imem->phase != IPC_P_CD_READY) in ipc_imem_phase_update_check()
774 ipc_uevent_send(ipc_imem->dev, UEVENT_CD_READY); in ipc_imem_phase_update_check()
775 ipc_imem->phase = IPC_P_CD_READY; in ipc_imem_phase_update_check()
782 ipc_uevent_send(ipc_imem->dev, UEVENT_CD_READY_LINK_DOWN); in ipc_imem_phase_update_check()
786 return ipc_imem->phase; in ipc_imem_phase_update_check()
797 if (ipc_protocol_msg_send(ipc_imem->ipc_protocol, in ipc_imem_pipe_open()
799 pipe->is_open = true; in ipc_imem_pipe_open()
801 return pipe->is_open; in ipc_imem_pipe_open()
812 for (i = 0; i < dl_pipe->nr_of_entries - 1; i++) in ipc_imem_tq_pipe_td_alloc()
819 ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, arg); in ipc_imem_tq_pipe_td_alloc()
841 return ipc_imem->phase == IPC_P_OFF_REQ ? in ipc_imem_phase_update()
842 ipc_imem->phase : in ipc_imem_phase_update()
850 return "A-RUN"; in ipc_imem_phase_get_string()
853 return "A-OFF"; in ipc_imem_phase_get_string()
856 return "A-ROM"; in ipc_imem_phase_get_string()
859 return "A-PSI"; in ipc_imem_phase_get_string()
862 return "A-EBL"; in ipc_imem_phase_get_string()
865 return "A-CRASH"; in ipc_imem_phase_get_string()
868 return "A-CD_READY"; in ipc_imem_phase_get_string()
871 return "A-OFF_REQ"; in ipc_imem_phase_get_string()
874 return "A-???"; in ipc_imem_phase_get_string()
882 pipe->is_open = false; in ipc_imem_pipe_close()
883 ipc_protocol_msg_send(ipc_imem->ipc_protocol, IPC_MSG_PREP_PIPE_CLOSE, in ipc_imem_pipe_close()
893 if (channel_id < 0 || channel_id >= ipc_imem->nr_of_channels) { in ipc_imem_channel_close()
894 dev_err(ipc_imem->dev, "invalid channel id %d", channel_id); in ipc_imem_channel_close()
898 channel = &ipc_imem->channels[channel_id]; in ipc_imem_channel_close()
900 if (channel->state == IMEM_CHANNEL_FREE) { in ipc_imem_channel_close()
901 dev_err(ipc_imem->dev, "ch[%d]: invalid channel state %d", in ipc_imem_channel_close()
902 channel_id, channel->state); in ipc_imem_channel_close()
907 if (channel->state == IMEM_CHANNEL_RESERVED) in ipc_imem_channel_close()
911 if (ipc_imem->phase == IPC_P_RUN) { in ipc_imem_channel_close()
912 ipc_imem_pipe_close(ipc_imem, &channel->ul_pipe); in ipc_imem_channel_close()
913 ipc_imem_pipe_close(ipc_imem, &channel->dl_pipe); in ipc_imem_channel_close()
916 ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe); in ipc_imem_channel_close()
917 ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe); in ipc_imem_channel_close()
929 dev_err(ipc_imem->dev, "invalid channel ID: %d", channel_id); in ipc_imem_channel_open()
933 channel = &ipc_imem->channels[channel_id]; in ipc_imem_channel_open()
935 channel->state = IMEM_CHANNEL_ACTIVE; in ipc_imem_channel_open()
937 if (!ipc_imem_pipe_open(ipc_imem, &channel->ul_pipe)) in ipc_imem_channel_open()
940 if (!ipc_imem_pipe_open(ipc_imem, &channel->dl_pipe)) in ipc_imem_channel_open()
945 &channel->dl_pipe, 0, false)) { in ipc_imem_channel_open()
946 dev_err(ipc_imem->dev, "td allocation failed : %d", channel_id); in ipc_imem_channel_open()
953 ipc_imem_pipe_close(ipc_imem, &channel->dl_pipe); in ipc_imem_channel_open()
955 ipc_imem_pipe_close(ipc_imem, &channel->ul_pipe); in ipc_imem_channel_open()
963 ipc_protocol_suspend(ipc_imem->ipc_protocol); in ipc_imem_pm_suspend()
968 ipc_protocol_s2idle_sleep(ipc_imem->ipc_protocol, sleep); in ipc_imem_pm_s2idle_sleep()
975 if (ipc_protocol_resume(ipc_imem->ipc_protocol)) { in ipc_imem_pm_resume()
976 stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); in ipc_imem_pm_resume()
984 channel->state = IMEM_CHANNEL_FREE; in ipc_imem_channel_free()
994 for (i = 0; i < ipc_imem->nr_of_channels; i++) { in ipc_imem_channel_alloc()
995 channel = &ipc_imem->channels[i]; in ipc_imem_channel_alloc()
996 if (channel->ctype == ctype && channel->index == index) in ipc_imem_channel_alloc()
1000 if (i >= ipc_imem->nr_of_channels) { in ipc_imem_channel_alloc()
1001 dev_dbg(ipc_imem->dev, in ipc_imem_channel_alloc()
1004 return -ECHRNG; in ipc_imem_channel_alloc()
1007 if (ipc_imem->channels[i].state != IMEM_CHANNEL_FREE) { in ipc_imem_channel_alloc()
1008 dev_dbg(ipc_imem->dev, "channel is in use"); in ipc_imem_channel_alloc()
1009 return -EBUSY; in ipc_imem_channel_alloc()
1012 if (channel->ctype == IPC_CTYPE_WWAN && in ipc_imem_channel_alloc()
1014 channel->if_id = index; in ipc_imem_channel_alloc()
1016 channel->channel_id = index; in ipc_imem_channel_alloc()
1017 channel->state = IMEM_CHANNEL_RESERVED; in ipc_imem_channel_alloc()
1029 dev_err(ipc_imem->dev, "invalid pipe: ul_pipe=%d, dl_pipe=%d", in ipc_imem_channel_init()
1034 if (ipc_imem->nr_of_channels >= IPC_MEM_MAX_CHANNELS) { in ipc_imem_channel_init()
1035 dev_err(ipc_imem->dev, "too many channels"); in ipc_imem_channel_init()
1039 channel = &ipc_imem->channels[ipc_imem->nr_of_channels]; in ipc_imem_channel_init()
1040 channel->channel_id = ipc_imem->nr_of_channels; in ipc_imem_channel_init()
1041 channel->ctype = ctype; in ipc_imem_channel_init()
1042 channel->index = chnl_cfg.id; in ipc_imem_channel_init()
1043 channel->net_err_count = 0; in ipc_imem_channel_init()
1044 channel->state = IMEM_CHANNEL_FREE; in ipc_imem_channel_init()
1045 ipc_imem->nr_of_channels++; in ipc_imem_channel_init()
1047 ipc_imem_channel_update(ipc_imem, channel->channel_id, chnl_cfg, in ipc_imem_channel_init()
1050 skb_queue_head_init(&channel->ul_list); in ipc_imem_channel_init()
1052 init_completion(&channel->ul_sem); in ipc_imem_channel_init()
1060 if (id < 0 || id >= ipc_imem->nr_of_channels) { in ipc_imem_channel_update()
1061 dev_err(ipc_imem->dev, "invalid channel id %d", id); in ipc_imem_channel_update()
1065 channel = &ipc_imem->channels[id]; in ipc_imem_channel_update()
1067 if (channel->state != IMEM_CHANNEL_FREE && in ipc_imem_channel_update()
1068 channel->state != IMEM_CHANNEL_RESERVED) { in ipc_imem_channel_update()
1069 dev_err(ipc_imem->dev, "invalid channel state %d", in ipc_imem_channel_update()
1070 channel->state); in ipc_imem_channel_update()
1074 channel->ul_pipe.nr_of_entries = chnl_cfg.ul_nr_of_entries; in ipc_imem_channel_update()
1075 channel->ul_pipe.pipe_nr = chnl_cfg.ul_pipe; in ipc_imem_channel_update()
1076 channel->ul_pipe.is_open = false; in ipc_imem_channel_update()
1077 channel->ul_pipe.irq = IPC_UL_PIPE_IRQ_VECTOR; in ipc_imem_channel_update()
1078 channel->ul_pipe.channel = channel; in ipc_imem_channel_update()
1079 channel->ul_pipe.dir = IPC_MEM_DIR_UL; in ipc_imem_channel_update()
1080 channel->ul_pipe.accumulation_backoff = chnl_cfg.accumulation_backoff; in ipc_imem_channel_update()
1081 channel->ul_pipe.irq_moderation = irq_moderation; in ipc_imem_channel_update()
1082 channel->ul_pipe.buf_size = 0; in ipc_imem_channel_update()
1084 channel->dl_pipe.nr_of_entries = chnl_cfg.dl_nr_of_entries; in ipc_imem_channel_update()
1085 channel->dl_pipe.pipe_nr = chnl_cfg.dl_pipe; in ipc_imem_channel_update()
1086 channel->dl_pipe.is_open = false; in ipc_imem_channel_update()
1087 channel->dl_pipe.irq = IPC_DL_PIPE_IRQ_VECTOR; in ipc_imem_channel_update()
1088 channel->dl_pipe.channel = channel; in ipc_imem_channel_update()
1089 channel->dl_pipe.dir = IPC_MEM_DIR_DL; in ipc_imem_channel_update()
1090 channel->dl_pipe.accumulation_backoff = chnl_cfg.accumulation_backoff; in ipc_imem_channel_update()
1091 channel->dl_pipe.irq_moderation = irq_moderation; in ipc_imem_channel_update()
1092 channel->dl_pipe.buf_size = chnl_cfg.dl_buf_size; in ipc_imem_channel_update()
1099 for (i = 0; i < ipc_imem->nr_of_channels; i++) { in ipc_imem_channel_reset()
1102 channel = &ipc_imem->channels[i]; in ipc_imem_channel_reset()
1104 ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe); in ipc_imem_channel_reset()
1105 ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe); in ipc_imem_channel_reset()
1118 pipe->is_open = false; in ipc_imem_pipe_cleanup()
1121 while ((skb = skb_dequeue(&pipe->channel->ul_list))) in ipc_imem_pipe_cleanup()
1122 ipc_pcie_kfree_skb(ipc_imem->pcie, skb); in ipc_imem_pipe_cleanup()
1124 ipc_protocol_pipe_cleanup(ipc_imem->ipc_protocol, pipe); in ipc_imem_pipe_cleanup()
1136 if (ipc_pcie_check_data_link_active(ipc_imem->pcie)) { in ipc_imem_device_ipc_uninit()
1141 ipc_doorbell_fire(ipc_imem->pcie, IPC_DOORBELL_IRQ_IPC, in ipc_imem_device_ipc_uninit()
1143 ipc_state = ipc_mmio_get_ipc_state(ipc_imem->mmio); in ipc_imem_device_ipc_uninit()
1152 timeout--; in ipc_imem_device_ipc_uninit()
1153 ipc_state = ipc_mmio_get_ipc_state(ipc_imem->mmio); in ipc_imem_device_ipc_uninit()
1160 ipc_imem->phase = IPC_P_OFF_REQ; in ipc_imem_cleanup()
1163 ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY); in ipc_imem_cleanup()
1165 hrtimer_cancel(&ipc_imem->td_alloc_timer); in ipc_imem_cleanup()
1166 hrtimer_cancel(&ipc_imem->tdupdate_timer); in ipc_imem_cleanup()
1167 hrtimer_cancel(&ipc_imem->fast_update_timer); in ipc_imem_cleanup()
1168 hrtimer_cancel(&ipc_imem->startup_timer); in ipc_imem_cleanup()
1171 cancel_work_sync(&ipc_imem->run_state_worker); in ipc_imem_cleanup()
1173 if (test_and_clear_bit(FULLY_FUNCTIONAL, &ipc_imem->flag)) { in ipc_imem_cleanup()
1174 ipc_mux_deinit(ipc_imem->mux); in ipc_imem_cleanup()
1175 ipc_wwan_deinit(ipc_imem->wwan); in ipc_imem_cleanup()
1176 ipc_port_deinit(ipc_imem->ipc_port); in ipc_imem_cleanup()
1182 ipc_protocol_deinit(ipc_imem->ipc_protocol); in ipc_imem_cleanup()
1183 ipc_task_deinit(ipc_imem->ipc_task); in ipc_imem_cleanup()
1185 kfree(ipc_imem->ipc_task); in ipc_imem_cleanup()
1186 kfree(ipc_imem->mmio); in ipc_imem_cleanup()
1188 ipc_imem->phase = IPC_P_OFF; in ipc_imem_cleanup()
1201 init_completion(&ipc_imem->ul_pend_sem); in ipc_imem_config()
1203 init_completion(&ipc_imem->dl_pend_sem); in ipc_imem_config()
1206 ipc_imem->ipc_status = IPC_MEM_DEVICE_IPC_UNINIT; in ipc_imem_config()
1207 ipc_imem->enter_runtime = 0; in ipc_imem_config()
1214 ipc_imem->hrtimer_period = ktime_set(0, 1000 * 1000 * 1000ULL); in ipc_imem_config()
1216 if (!hrtimer_active(&ipc_imem->startup_timer)) in ipc_imem_config()
1217 hrtimer_start(&ipc_imem->startup_timer, in ipc_imem_config()
1218 ipc_imem->hrtimer_period, in ipc_imem_config()
1226 ipc_imem->ipc_requested_state = IPC_MEM_DEVICE_IPC_UNINIT; in ipc_imem_config()
1229 if (ipc_imem->ipc_requested_state == in ipc_imem_config()
1230 ipc_mmio_get_ipc_state(ipc_imem->mmio)) { in ipc_imem_config()
1235 dev_err(ipc_imem->dev, in ipc_imem_config()
1237 ipc_mmio_get_ipc_state(ipc_imem->mmio)); in ipc_imem_config()
1241 dev_dbg(ipc_imem->dev, in ipc_imem_config()
1246 dev_err(ipc_imem->dev, "unexpected operation phase %d", phase); in ipc_imem_config()
1250 complete(&ipc_imem->dl_pend_sem); in ipc_imem_config()
1251 complete(&ipc_imem->ul_pend_sem); in ipc_imem_config()
1252 ipc_imem->phase = IPC_P_OFF; in ipc_imem_config()
1253 return -EIO; in ipc_imem_config()
1258 void __iomem *mmio, struct device *dev) in ipc_imem_init() argument
1260 struct iosm_imem *ipc_imem = kzalloc(sizeof(*pcie->imem), GFP_KERNEL); in ipc_imem_init()
1266 ipc_imem->pcie = pcie; in ipc_imem_init()
1267 ipc_imem->dev = dev; in ipc_imem_init()
1269 ipc_imem->pci_device_id = device_id; in ipc_imem_init()
1271 ipc_imem->ev_cdev_write_pending = false; in ipc_imem_init()
1272 ipc_imem->cp_version = 0; in ipc_imem_init()
1273 ipc_imem->device_sleep = IPC_HOST_SLEEP_ENTER_SLEEP; in ipc_imem_init()
1276 ipc_imem->flash_channel_id = -1; in ipc_imem_init()
1279 ipc_imem->nr_of_channels = 0; in ipc_imem_init()
1281 /* allocate IPC MMIO */ in ipc_imem_init()
1282 ipc_imem->mmio = ipc_mmio_init(mmio, ipc_imem->dev); in ipc_imem_init()
1283 if (!ipc_imem->mmio) { in ipc_imem_init()
1284 dev_err(ipc_imem->dev, "failed to initialize mmio region"); in ipc_imem_init()
1288 ipc_imem->ipc_task = kzalloc(sizeof(*ipc_imem->ipc_task), in ipc_imem_init()
1292 if (!ipc_imem->ipc_task) in ipc_imem_init()
1295 if (ipc_task_init(ipc_imem->ipc_task)) in ipc_imem_init()
1298 ipc_imem->ipc_task->dev = ipc_imem->dev; in ipc_imem_init()
1300 INIT_WORK(&ipc_imem->run_state_worker, ipc_imem_run_state_worker); in ipc_imem_init()
1302 ipc_imem->ipc_protocol = ipc_protocol_init(ipc_imem); in ipc_imem_init()
1304 if (!ipc_imem->ipc_protocol) in ipc_imem_init()
1308 ipc_imem->phase = IPC_P_OFF; in ipc_imem_init()
1310 hrtimer_init(&ipc_imem->startup_timer, CLOCK_MONOTONIC, in ipc_imem_init()
1312 ipc_imem->startup_timer.function = ipc_imem_startup_timer_cb; in ipc_imem_init()
1314 hrtimer_init(&ipc_imem->tdupdate_timer, CLOCK_MONOTONIC, in ipc_imem_init()
1316 ipc_imem->tdupdate_timer.function = ipc_imem_td_update_timer_cb; in ipc_imem_init()
1318 hrtimer_init(&ipc_imem->fast_update_timer, CLOCK_MONOTONIC, in ipc_imem_init()
1320 ipc_imem->fast_update_timer.function = ipc_imem_fast_update_timer_cb; in ipc_imem_init()
1322 hrtimer_init(&ipc_imem->td_alloc_timer, CLOCK_MONOTONIC, in ipc_imem_init()
1324 ipc_imem->td_alloc_timer.function = ipc_imem_td_alloc_timer_cb; in ipc_imem_init()
1327 dev_err(ipc_imem->dev, "failed to initialize the imem"); in ipc_imem_init()
1334 hrtimer_cancel(&ipc_imem->td_alloc_timer); in ipc_imem_init()
1335 hrtimer_cancel(&ipc_imem->fast_update_timer); in ipc_imem_init()
1336 hrtimer_cancel(&ipc_imem->tdupdate_timer); in ipc_imem_init()
1337 hrtimer_cancel(&ipc_imem->startup_timer); in ipc_imem_init()
1339 cancel_work_sync(&ipc_imem->run_state_worker); in ipc_imem_init()
1340 ipc_task_deinit(ipc_imem->ipc_task); in ipc_imem_init()
1342 kfree(ipc_imem->ipc_task); in ipc_imem_init()
1344 kfree(ipc_imem->mmio); in ipc_imem_init()
1353 if (ipc_imem && !ipc_imem->ev_irq_pending[irq]) { in ipc_imem_irq_process()
1354 ipc_imem->ev_irq_pending[irq] = true; in ipc_imem_irq_process()
1362 ipc_imem->td_update_timer_suspended = suspend; in ipc_imem_td_update_timer_suspend()