Loading drivers/platform/msm/mhi_dev/mhi.c +520 −90 File changed.Preview size limit exceeded, changes collapsed. Show changes drivers/platform/msm/mhi_dev/mhi.h +27 −50 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -561,6 +561,9 @@ struct mhi_dev { /* Use IPA DMA for Software channel data transfer */ bool use_ipa; /* Use PCI eDMA for data transfer */ bool use_edma; /* iATU is required to map control and data region */ bool config_iatu; Loading @@ -572,6 +575,22 @@ struct mhi_dev { bool mhi_int_en; /* Registered client callback list */ struct list_head client_cb_list; /* Tx, Rx DMA channels */ struct dma_chan *tx_dma_chan; struct dma_chan *rx_dma_chan; int (*device_to_host)(uint64_t dst_pa, void *src, uint32_t len, struct mhi_dev *mhi, struct mhi_req *req); int (*host_to_device)(void *device, uint64_t src_pa, uint32_t len, struct mhi_dev *mhi, struct mhi_req *mreq); void (*write_to_host)(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer, struct event_req *ereq, enum mhi_dev_transfer_type type); void (*read_from_host)(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer); struct kobj_uevent_env kobj_env; }; Loading Loading @@ -605,6 +624,8 @@ extern void *mhi_ipc_log; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 used for internal only */ #define MHI_DEV_UEVENT_CTRL 0 #define MHI_USE_DMA(mhi) (mhi->use_ipa || mhi->use_edma) struct mhi_dev_uevent_info { enum mhi_client_channel channel; enum mhi_ctrl_info ctrl_info; Loading Loading @@ -683,57 +704,13 @@ int mhi_dev_process_ring_element(struct mhi_dev_ring *ring, uint32_t offset); int mhi_dev_add_element(struct mhi_dev_ring *ring, union mhi_dev_ring_element_type *element, struct event_req *ereq, int evt_offset); /** * mhi_transfer_device_to_host() - memcpy equivalent API to transfer data * from device to the host. * @dst_pa: Physical destination address. * @src: Source virtual address. * @len: Numer of bytes to be transferred. * @mhi: MHI dev structure. * @req: mhi_req structure */ int mhi_transfer_device_to_host(uint64_t dst_pa, void *src, uint32_t len, struct mhi_dev *mhi, struct mhi_req *req); /** * mhi_transfer_host_to_dev() - memcpy equivalent API to transfer data * from host to the device. * @dst: Physical destination virtual address. * @src_pa: Source physical address. * @len: Numer of bytes to be transferred. * @mhi: MHI dev structure. * @req: mhi_req structure */ int mhi_transfer_host_to_device(void *device, uint64_t src_pa, uint32_t len, struct mhi_dev *mhi, struct mhi_req *mreq); /** * mhi_dev_write_to_host() - Transfer data from device to host. * Based on support available, either IPA DMA or memcpy is used. * @host: Host and device address details. * @buf: Data buffer that needs to be written to the host. * @size: Data buffer size. */ void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer, struct event_req *ereq, enum mhi_dev_transfer_type type); /** * mhi_dev_read_from_host() - memcpy equivalent API to transfer data * from host to device. * @host: Host and device address details. * @buf: Data buffer that needs to be read from the host. * @size: Data buffer size. */ void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer); /** * mhi_dev_read_from_host() - memcpy equivalent API to transfer data * from host to device. * @host: Host and device address details. * @buf: Data buffer that needs to be read from the host. * @size: Data buffer size. /* * mhi_ring_set_cb () - Call back function of the ring. * * @ring: Ring for the respective context - Channel/Event/Command. * @ring_cb: callback function. */ void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)); Loading drivers/platform/msm/mhi_dev/mhi_dev_net.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, 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 @@ -175,7 +175,7 @@ static void mhi_dev_net_process_queue_packets(struct work_struct *work) wreq->buf = skb->data; wreq->len = skb->len; wreq->chan = client->in_chan; wreq->mode = IPA_DMA_ASYNC; wreq->mode = DMA_ASYNC; if (skb_queue_empty(&client->tx_buffers) || list_empty(&client->wr_req_buffers)) { wreq->snd_cmpl = 1; Loading Loading @@ -298,7 +298,7 @@ static ssize_t mhi_dev_net_client_read(struct mhi_dev_net_client *mhi_handle) req->buf = skb->data; req->len = MHI_NET_DEFAULT_MTU; req->context = skb; req->mode = IPA_DMA_ASYNC; req->mode = DMA_ASYNC; bytes_avail = mhi_dev_read_channel(req); if (bytes_avail < 0) { Loading drivers/platform/msm/mhi_dev/mhi_ring.c +17 −11 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -45,9 +45,12 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, uint32_t start, uint32_t end) { struct mhi_addr host_addr; struct mhi_dev *mhi_ctx; mhi_ctx = ring->mhi_dev; /* fetch ring elements from start->end, take care of wrap-around case */ if (ring->mhi_dev->use_ipa) { if (MHI_USE_DMA(mhi_ctx)) { host_addr.host_pa = ring->ring_shadow.host_pa + sizeof(union mhi_dev_ring_element_type) * start; host_addr.phy_addr = ring->ring_cache_dma_handle + Loading @@ -59,12 +62,12 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, } host_addr.size = (end-start) * sizeof(union mhi_dev_ring_element_type); if (start < end) { mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); } else if (start > end) { /* copy from 'start' to ring end, then ring start to 'end'*/ host_addr.size = (ring->ring_size-start) * sizeof(union mhi_dev_ring_element_type); mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); if (end) { /* wrapped around */ host_addr.device_pa = ring->ring_shadow.device_pa; Loading @@ -74,7 +77,8 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, host_addr.phy_addr = ring->ring_cache_dma_handle; host_addr.size = (end * sizeof(union mhi_dev_ring_element_type)); mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); } } return 0; Loading Loading @@ -276,9 +280,11 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, struct mhi_addr host_addr; uint32_t num_elem = 1; uint32_t num_free_elem; struct mhi_dev *mhi_ctx; if (WARN_ON(!ring || !element)) return -EINVAL; mhi_ctx = ring->mhi_dev; mhi_dev_update_wr_offset(ring); Loading Loading @@ -314,7 +320,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, * iomap of the ring_base for memcpy */ if (ring->mhi_dev->use_ipa) if (MHI_USE_DMA(mhi_ctx)) host_addr.host_pa = ring->ring_shadow.host_pa + sizeof(union mhi_dev_ring_element_type) * old_offset; else Loading @@ -331,7 +337,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset); mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, NULL, MHI_DEV_DMA_SYNC); return 0; } Loading @@ -341,25 +347,25 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, /* No wrap-around case */ host_addr.virt_addr = element; host_addr.size = size; mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, ereq, MHI_DEV_DMA_ASYNC); } else { /* Wrap-around case - first chunk uses dma sync */ host_addr.virt_addr = element; host_addr.size = (ring->ring_size - old_offset) * sizeof(union mhi_dev_ring_element_type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, NULL, MHI_DEV_DMA_SYNC); /* Copy remaining elements */ if (ring->mhi_dev->use_ipa) if (MHI_USE_DMA(mhi_ctx)) host_addr.host_pa = ring->ring_shadow.host_pa; else host_addr.device_va = ring->ring_shadow.device_va; host_addr.virt_addr = element + (ring->ring_size - old_offset); host_addr.size = ring->rd_offset * sizeof(union mhi_dev_ring_element_type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, ereq, MHI_DEV_DMA_ASYNC); } return 0; Loading drivers/platform/msm/mhi_dev/mhi_sm.c +21 −16 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -445,36 +445,41 @@ static int mhi_sm_change_to_M0(void) old_state = mhi_sm_ctx->mhi_state; if (old_state == MHI_DEV_M0_STATE) { switch (old_state) { case MHI_DEV_M0_STATE: MHI_SM_DBG("Nothing to do, already in M0 state\n"); res = 0; goto exit; } else if (old_state == MHI_DEV_M3_STATE || old_state == MHI_DEV_READY_STATE) { /* Retrieve MHI configuration*/ res = mhi_dev_config_outbound_iatu(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Fail to configure iATU, returned %d\n", res); goto exit; } case MHI_DEV_M3_STATE: case MHI_DEV_READY_STATE: res = ep_pcie_get_msi_config(mhi_sm_ctx->mhi_dev->phandle, &cfg); if (res) { MHI_SM_ERR("Error retrieving pcie msi logic\n"); goto exit; } if (mhi_sm_ctx->mhi_dev->use_ipa) { /* Retrieve MHI configuration*/ res = mhi_dev_config_outbound_iatu(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Fail to configure iATU, ret: %d\n", res); goto exit; } res = mhi_pcie_config_db_routing(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Error configuring db routing\n"); goto exit; } } else { } break; default: MHI_SM_ERR("unexpected old_state: %s\n", mhi_sm_mstate_str(old_state)); goto exit; } mhi_sm_mmio_set_mhistatus(MHI_DEV_M0_STATE); /* Tell the host, device move to M0 */ Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +520 −90 File changed.Preview size limit exceeded, changes collapsed. Show changes
drivers/platform/msm/mhi_dev/mhi.h +27 −50 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -561,6 +561,9 @@ struct mhi_dev { /* Use IPA DMA for Software channel data transfer */ bool use_ipa; /* Use PCI eDMA for data transfer */ bool use_edma; /* iATU is required to map control and data region */ bool config_iatu; Loading @@ -572,6 +575,22 @@ struct mhi_dev { bool mhi_int_en; /* Registered client callback list */ struct list_head client_cb_list; /* Tx, Rx DMA channels */ struct dma_chan *tx_dma_chan; struct dma_chan *rx_dma_chan; int (*device_to_host)(uint64_t dst_pa, void *src, uint32_t len, struct mhi_dev *mhi, struct mhi_req *req); int (*host_to_device)(void *device, uint64_t src_pa, uint32_t len, struct mhi_dev *mhi, struct mhi_req *mreq); void (*write_to_host)(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer, struct event_req *ereq, enum mhi_dev_transfer_type type); void (*read_from_host)(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer); struct kobj_uevent_env kobj_env; }; Loading Loading @@ -605,6 +624,8 @@ extern void *mhi_ipc_log; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 used for internal only */ #define MHI_DEV_UEVENT_CTRL 0 #define MHI_USE_DMA(mhi) (mhi->use_ipa || mhi->use_edma) struct mhi_dev_uevent_info { enum mhi_client_channel channel; enum mhi_ctrl_info ctrl_info; Loading Loading @@ -683,57 +704,13 @@ int mhi_dev_process_ring_element(struct mhi_dev_ring *ring, uint32_t offset); int mhi_dev_add_element(struct mhi_dev_ring *ring, union mhi_dev_ring_element_type *element, struct event_req *ereq, int evt_offset); /** * mhi_transfer_device_to_host() - memcpy equivalent API to transfer data * from device to the host. * @dst_pa: Physical destination address. * @src: Source virtual address. * @len: Numer of bytes to be transferred. * @mhi: MHI dev structure. * @req: mhi_req structure */ int mhi_transfer_device_to_host(uint64_t dst_pa, void *src, uint32_t len, struct mhi_dev *mhi, struct mhi_req *req); /** * mhi_transfer_host_to_dev() - memcpy equivalent API to transfer data * from host to the device. * @dst: Physical destination virtual address. * @src_pa: Source physical address. * @len: Numer of bytes to be transferred. * @mhi: MHI dev structure. * @req: mhi_req structure */ int mhi_transfer_host_to_device(void *device, uint64_t src_pa, uint32_t len, struct mhi_dev *mhi, struct mhi_req *mreq); /** * mhi_dev_write_to_host() - Transfer data from device to host. * Based on support available, either IPA DMA or memcpy is used. * @host: Host and device address details. * @buf: Data buffer that needs to be written to the host. * @size: Data buffer size. */ void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer, struct event_req *ereq, enum mhi_dev_transfer_type type); /** * mhi_dev_read_from_host() - memcpy equivalent API to transfer data * from host to device. * @host: Host and device address details. * @buf: Data buffer that needs to be read from the host. * @size: Data buffer size. */ void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer); /** * mhi_dev_read_from_host() - memcpy equivalent API to transfer data * from host to device. * @host: Host and device address details. * @buf: Data buffer that needs to be read from the host. * @size: Data buffer size. /* * mhi_ring_set_cb () - Call back function of the ring. * * @ring: Ring for the respective context - Channel/Event/Command. * @ring_cb: callback function. */ void mhi_ring_set_cb(struct mhi_dev_ring *ring, void (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)); Loading
drivers/platform/msm/mhi_dev/mhi_dev_net.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, 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 @@ -175,7 +175,7 @@ static void mhi_dev_net_process_queue_packets(struct work_struct *work) wreq->buf = skb->data; wreq->len = skb->len; wreq->chan = client->in_chan; wreq->mode = IPA_DMA_ASYNC; wreq->mode = DMA_ASYNC; if (skb_queue_empty(&client->tx_buffers) || list_empty(&client->wr_req_buffers)) { wreq->snd_cmpl = 1; Loading Loading @@ -298,7 +298,7 @@ static ssize_t mhi_dev_net_client_read(struct mhi_dev_net_client *mhi_handle) req->buf = skb->data; req->len = MHI_NET_DEFAULT_MTU; req->context = skb; req->mode = IPA_DMA_ASYNC; req->mode = DMA_ASYNC; bytes_avail = mhi_dev_read_channel(req); if (bytes_avail < 0) { Loading
drivers/platform/msm/mhi_dev/mhi_ring.c +17 −11 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -45,9 +45,12 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, uint32_t start, uint32_t end) { struct mhi_addr host_addr; struct mhi_dev *mhi_ctx; mhi_ctx = ring->mhi_dev; /* fetch ring elements from start->end, take care of wrap-around case */ if (ring->mhi_dev->use_ipa) { if (MHI_USE_DMA(mhi_ctx)) { host_addr.host_pa = ring->ring_shadow.host_pa + sizeof(union mhi_dev_ring_element_type) * start; host_addr.phy_addr = ring->ring_cache_dma_handle + Loading @@ -59,12 +62,12 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, } host_addr.size = (end-start) * sizeof(union mhi_dev_ring_element_type); if (start < end) { mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); } else if (start > end) { /* copy from 'start' to ring end, then ring start to 'end'*/ host_addr.size = (ring->ring_size-start) * sizeof(union mhi_dev_ring_element_type); mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); if (end) { /* wrapped around */ host_addr.device_pa = ring->ring_shadow.device_pa; Loading @@ -74,7 +77,8 @@ int mhi_dev_fetch_ring_elements(struct mhi_dev_ring *ring, host_addr.phy_addr = ring->ring_cache_dma_handle; host_addr.size = (end * sizeof(union mhi_dev_ring_element_type)); mhi_dev_read_from_host(ring->mhi_dev, &host_addr); mhi_ctx->read_from_host(ring->mhi_dev, &host_addr); } } return 0; Loading Loading @@ -276,9 +280,11 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, struct mhi_addr host_addr; uint32_t num_elem = 1; uint32_t num_free_elem; struct mhi_dev *mhi_ctx; if (WARN_ON(!ring || !element)) return -EINVAL; mhi_ctx = ring->mhi_dev; mhi_dev_update_wr_offset(ring); Loading Loading @@ -314,7 +320,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, * iomap of the ring_base for memcpy */ if (ring->mhi_dev->use_ipa) if (MHI_USE_DMA(mhi_ctx)) host_addr.host_pa = ring->ring_shadow.host_pa + sizeof(union mhi_dev_ring_element_type) * old_offset; else Loading @@ -331,7 +337,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset); mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, NULL, MHI_DEV_DMA_SYNC); return 0; } Loading @@ -341,25 +347,25 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, /* No wrap-around case */ host_addr.virt_addr = element; host_addr.size = size; mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, ereq, MHI_DEV_DMA_ASYNC); } else { /* Wrap-around case - first chunk uses dma sync */ host_addr.virt_addr = element; host_addr.size = (ring->ring_size - old_offset) * sizeof(union mhi_dev_ring_element_type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, NULL, MHI_DEV_DMA_SYNC); /* Copy remaining elements */ if (ring->mhi_dev->use_ipa) if (MHI_USE_DMA(mhi_ctx)) host_addr.host_pa = ring->ring_shadow.host_pa; else host_addr.device_va = ring->ring_shadow.device_va; host_addr.virt_addr = element + (ring->ring_size - old_offset); host_addr.size = ring->rd_offset * sizeof(union mhi_dev_ring_element_type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, mhi_ctx->write_to_host(ring->mhi_dev, &host_addr, ereq, MHI_DEV_DMA_ASYNC); } return 0; Loading
drivers/platform/msm/mhi_dev/mhi_sm.c +21 −16 Original line number Diff line number Diff line /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2019, 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 @@ -445,36 +445,41 @@ static int mhi_sm_change_to_M0(void) old_state = mhi_sm_ctx->mhi_state; if (old_state == MHI_DEV_M0_STATE) { switch (old_state) { case MHI_DEV_M0_STATE: MHI_SM_DBG("Nothing to do, already in M0 state\n"); res = 0; goto exit; } else if (old_state == MHI_DEV_M3_STATE || old_state == MHI_DEV_READY_STATE) { /* Retrieve MHI configuration*/ res = mhi_dev_config_outbound_iatu(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Fail to configure iATU, returned %d\n", res); goto exit; } case MHI_DEV_M3_STATE: case MHI_DEV_READY_STATE: res = ep_pcie_get_msi_config(mhi_sm_ctx->mhi_dev->phandle, &cfg); if (res) { MHI_SM_ERR("Error retrieving pcie msi logic\n"); goto exit; } if (mhi_sm_ctx->mhi_dev->use_ipa) { /* Retrieve MHI configuration*/ res = mhi_dev_config_outbound_iatu(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Fail to configure iATU, ret: %d\n", res); goto exit; } res = mhi_pcie_config_db_routing(mhi_sm_ctx->mhi_dev); if (res) { MHI_SM_ERR("Error configuring db routing\n"); goto exit; } } else { } break; default: MHI_SM_ERR("unexpected old_state: %s\n", mhi_sm_mstate_str(old_state)); goto exit; } mhi_sm_mmio_set_mhistatus(MHI_DEV_M0_STATE); /* Tell the host, device move to M0 */ Loading