FAILED: patch "[PATCH] bus: mhi: Fix MHI DMA structure endianness" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From ed2d980503235829aa3e0c7ae3b82374c30a081c Mon Sep 17 00:00:00 2001
From: Paul Davey <[email protected]>
Date: Tue, 1 Mar 2022 21:33:01 +0530
Subject: [PATCH] bus: mhi: Fix MHI DMA structure endianness
The MHI driver does not work on big endian architectures. The controller never transitions into mission mode. This appears to be due to the modem device expecting the various contexts and transfer rings to have fields in little endian order in memory, but the driver constructs them in native endianness.
Fix MHI event, channel and command contexts and TRE handling macros to use explicit conversion to little endian. Mark fields in relevant structures as little endian to document this requirement.
drivers/bus/mhi/core/debugfs.c +13 -13
@@ -60,16 +60,16 @@ static int mhi_debugfs_events_show(struct seq_file *m, void *d) }seq_printf (m,"Index: %d intmod count: %lu time: %lu" , - i, (er_ctxt->intmod &EV_CTX_INTMODC_MASK ) >> + i, (le32_to_cpu (er_ctxt->intmod) &EV_CTX_INTMODC_MASK ) >>EV_CTX_INTMODC_SHIFT , - (er_ctxt->intmod &EV_CTX_INTMODT_MASK ) >> + (le32_to_cpu (er_ctxt->intmod) &EV_CTX_INTMODT_MASK ) >>EV_CTX_INTMODT_SHIFT ); -seq_printf (m," base: 0x%0llx len: 0x%llx" , er_ctxt->rbase, - er_ctxt->rlen); +seq_printf (m," base: 0x%0llx len: 0x%llx" ,le64_to_cpu (er_ctxt->rbase), +le64_to_cpu (er_ctxt->rlen)); -seq_printf (m," rp: 0x%llx wp: 0x%llx" , er_ctxt->rp, - er_ctxt->wp); +seq_printf (m," rp: 0x%llx wp: 0x%llx" ,le64_to_cpu (er_ctxt->rp), +le64_to_cpu (er_ctxt->wp));seq_printf (m," local rp: 0x%pK db: 0x%pad\n" , ring->rp, &mhi_event->db_cfg.db_val);
@@ -106,18 +106,18 @@ static int mhi_debugfs_channels_show(struct seq_file *m, void *d)seq_printf (m,"%s(%u) state: 0x%lx brstmode: 0x%lx pollcfg: 0x%lx" , - mhi_chan->name, mhi_chan->chan, (chan_ctxt->chcfg & + mhi_chan->name, mhi_chan->chan, (le32_to_cpu (chan_ctxt->chcfg) &CHAN_CTX_CHSTATE_MASK ) >>CHAN_CTX_CHSTATE_SHIFT , - (chan_ctxt->chcfg &CHAN_CTX_BRSTMODE_MASK ) >> -CHAN_CTX_BRSTMODE_SHIFT , (chan_ctxt->chcfg & + (le32_to_cpu (chan_ctxt->chcfg) &CHAN_CTX_BRSTMODE_MASK ) >> +CHAN_CTX_BRSTMODE_SHIFT , (le32_to_cpu (chan_ctxt->chcfg) &CHAN_CTX_POLLCFG_MASK ) >>CHAN_CTX_POLLCFG_SHIFT ); -seq_printf (m," type: 0x%x event ring: %u" , chan_ctxt->chtype, - chan_ctxt->erindex); +seq_printf (m," type: 0x%x event ring: %u" ,le32_to_cpu (chan_ctxt->chtype), +le32_to_cpu (chan_ctxt->erindex));seq_printf (m," base: 0x%llx len: 0x%llx rp: 0x%llx wp: 0x%llx" , - chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->rp, - chan_ctxt->wp); +le64_to_cpu (chan_ctxt->rbase),le64_to_cpu (chan_ctxt->rlen), +le64_to_cpu (chan_ctxt->rp),le64_to_cpu (chan_ctxt->wp)); seq_printf(m, " local rp: 0x%pK local wp: 0x%pK db: 0x%pad\n", ring->rp, ring->wp,
drivers/bus/mhi/core/init.c +18 -18
@@ -293,17 +293,17 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)if (mhi_chan->offload_ch)continue ; - tmp = chan_ctxt->chcfg; + tmp =le32_to_cpu (chan_ctxt->chcfg); tmp &= ~CHAN_CTX_CHSTATE_MASK ; tmp |= (MHI_CH_STATE_DISABLED <<CHAN_CTX_CHSTATE_SHIFT ); tmp &= ~CHAN_CTX_BRSTMODE_MASK ; tmp |= (mhi_chan->db_cfg.brstmode <<CHAN_CTX_BRSTMODE_SHIFT ); tmp &= ~CHAN_CTX_POLLCFG_MASK ; tmp |= (mhi_chan->db_cfg.pollcfg <<CHAN_CTX_POLLCFG_SHIFT ); - chan_ctxt->chcfg = tmp; + chan_ctxt->chcfg =cpu_to_le32 (tmp); - chan_ctxt->chtype = mhi_chan->type; - chan_ctxt->erindex = mhi_chan->er_index; + chan_ctxt->chtype =cpu_to_le32 (mhi_chan->type); + chan_ctxt->erindex =cpu_to_le32 (mhi_chan->er_index); mhi_chan->ch_state =MHI_CH_STATE_DISABLED ; mhi_chan->tre_ring.db_addr = (void __iomem *)&chan_ctxt->wp;
@@ -328,14 +328,14 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)if (mhi_event->offload_ev)continue ; - tmp = er_ctxt->intmod; + tmp =le32_to_cpu (er_ctxt->intmod); tmp &= ~EV_CTX_INTMODC_MASK ; tmp &= ~EV_CTX_INTMODT_MASK ; tmp |= (mhi_event->intmod <<EV_CTX_INTMODT_SHIFT ); - er_ctxt->intmod = tmp; + er_ctxt->intmod =cpu_to_le32 (tmp); - er_ctxt->ertype =MHI_ER_TYPE_VALID ; - er_ctxt->msivec = mhi_event->irq; + er_ctxt->ertype =cpu_to_le32 (MHI_ER_TYPE_VALID ); + er_ctxt->msivec =cpu_to_le32 (mhi_event->irq); mhi_event->db_cfg.db_mode = true; ring->el_size =sizeof (struct mhi_tre );
@@ -349,9 +349,9 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)* ring is empty */ ring->rp = ring->wp = ring->base; - er_ctxt->rbase = ring->iommu_base; + er_ctxt->rbase =cpu_to_le64 (ring->iommu_base); er_ctxt->rp = er_ctxt->wp = er_ctxt->rbase; - er_ctxt->rlen = ring->len; + er_ctxt->rlen =cpu_to_le64 (ring->len); ring->ctxt_wp = &er_ctxt->wp; }
@@ -378,9 +378,9 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) goto error_alloc_cmd; ring->rp = ring->wp = ring->base; - cmd_ctxt->rbase = ring->iommu_base; + cmd_ctxt->rbase =cpu_to_le64 (ring->iommu_base); cmd_ctxt->rp = cmd_ctxt->wp = cmd_ctxt->rbase; - cmd_ctxt->rlen = ring->len; + cmd_ctxt->rlen =cpu_to_le64 (ring->len); ring->ctxt_wp = &cmd_ctxt->wp; }
@@ -581,10 +581,10 @@ void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, chan_ctxt->rp =0 ; chan_ctxt->wp =0 ; - tmp = chan_ctxt->chcfg; + tmp =le32_to_cpu (chan_ctxt->chcfg); tmp &= ~CHAN_CTX_CHSTATE_MASK ; tmp |= (MHI_CH_STATE_DISABLED <<CHAN_CTX_CHSTATE_SHIFT ); - chan_ctxt->chcfg = tmp; + chan_ctxt->chcfg =cpu_to_le32 (tmp);/* Update to all cores */ smp_wmb ();
@@ -618,14 +618,14 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,return -ENOMEM ; } - tmp = chan_ctxt->chcfg; + tmp =le32_to_cpu (chan_ctxt->chcfg); tmp &= ~CHAN_CTX_CHSTATE_MASK ; tmp |= (MHI_CH_STATE_ENABLED <<CHAN_CTX_CHSTATE_SHIFT ); - chan_ctxt->chcfg = tmp; + chan_ctxt->chcfg =cpu_to_le32 (tmp); - chan_ctxt->rbase = tre_ring->iommu_base; + chan_ctxt->rbase =cpu_to_le64 (tre_ring->iommu_base); chan_ctxt->rp = chan_ctxt->wp = chan_ctxt->rbase; - chan_ctxt->rlen = tre_ring->len; + chan_ctxt->rlen =cpu_to_le64 (tre_ring->len); tre_ring->ctxt_wp = &chan_ctxt->wp; tre_ring->rp = tre_ring->wp = tre_ring->base;
drivers/bus/mhi/core/internal.h +60 -59
171 lines not on this page · raw message
drivers/bus/mhi/core/main.c +11 -11
@@ -114,7 +114,7 @@ void mhi_ring_er_db(struct mhi_event *mhi_event)struct mhi_ring *ring = &mhi_event->ring; mhi_event->db_cfg.process_db (mhi_event->mhi_cntrl, &mhi_event->db_cfg, - ring->db_addr, *ring->ctxt_wp); + ring->db_addr,le64_to_cpu (*ring->ctxt_wp)); }void mhi_ring_cmd_db (struct mhi_controller *mhi_cntrl,struct mhi_cmd *mhi_cmd)
@@ -123,7 +123,7 @@ void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd)struct mhi_ring *ring = &mhi_cmd->ring; db = ring->iommu_base + (ring->wp - ring->base); - *ring->ctxt_wp = db; + *ring->ctxt_wp =cpu_to_le64 (db);mhi_write_db (mhi_cntrl, ring->db_addr, db); }
@@ -140,7 +140,7 @@ void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,* before letting h/w know there is new element to fetch. */ dma_wmb (); - *ring->ctxt_wp = db; + *ring->ctxt_wp =cpu_to_le64 (db); mhi_chan->db_cfg.process_db (mhi_cntrl, &mhi_chan->db_cfg, ring->db_addr, db);
@@ -432,7 +432,7 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)struct mhi_event_ctxt *er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];struct mhi_ring *ev_ring = &mhi_event->ring; -dma_addr_t ptr = er_ctxt->rp; +dma_addr_t ptr =le64_to_cpu (er_ctxt->rp);void *dev_rp;if (!is_valid_ring_ptr (ev_ring, ptr)) {
@@ -537,14 +537,14 @@ static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl,/* Update the WP */ ring->wp += ring->el_size; - ctxt_wp = *ring->ctxt_wp + ring->el_size; + ctxt_wp =le64_to_cpu (*ring->ctxt_wp) + ring->el_size;if (ring->wp >= (ring->base + ring->len)) { ring->wp = ring->base; ctxt_wp = ring->iommu_base; } - *ring->ctxt_wp = ctxt_wp; + *ring->ctxt_wp =cpu_to_le64 (ctxt_wp);/* Update the RP */ ring->rp += ring->el_size;
@@ -801,7 +801,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,struct device *dev = &mhi_cntrl->mhi_dev->dev;u32 chan;int count =0 ; -dma_addr_t ptr = er_ctxt->rp; +dma_addr_t ptr =le64_to_cpu (er_ctxt->rp);/* * This is a quick check to avoid unnecessary event processing
@@ -940,7 +940,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,mhi_recycle_ev_ring_element (mhi_cntrl, ev_ring); local_rp = ev_ring->rp; - ptr = er_ctxt->rp; + ptr =le64_to_cpu (er_ctxt->rp);if (!is_valid_ring_ptr (ev_ring, ptr)) {dev_err (&mhi_cntrl->mhi_dev->dev,"Event ring rp points outside of the event ring\n" );
@@ -970,7 +970,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,int count =0 ;u32 chan;struct mhi_chan *mhi_chan; -dma_addr_t ptr = er_ctxt->rp; +dma_addr_t ptr =le64_to_cpu (er_ctxt->rp);if (unlikely (MHI_EVENT_ACCESS_INVALID (mhi_cntrl->pm_state)))return -EIO ;
@@ -1011,7 +1011,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,mhi_recycle_ev_ring_element (mhi_cntrl, ev_ring); local_rp = ev_ring->rp; - ptr = er_ctxt->rp; + ptr =le64_to_cpu (er_ctxt->rp);if (!is_valid_ring_ptr (ev_ring, ptr)) {dev_err (&mhi_cntrl->mhi_dev->dev,"Event ring rp points outside of the event ring\n" );
@@ -1533,7 +1533,7 @@ static void mhi_mark_stale_events(struct mhi_controller *mhi_cntrl,/* mark all stale events related to channel as STALE event */ spin_lock_irqsave (&mhi_event->lock, flags); - ptr = er_ctxt->rp; + ptr =le64_to_cpu (er_ctxt->rp);if (!is_valid_ring_ptr (ev_ring, ptr)) {dev_err (&mhi_cntrl->mhi_dev->dev,"Event ring rp points outside of the event ring\n" );
drivers/bus/mhi/core/pm.c +2 -2
@@ -218,7 +218,7 @@ int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl)continue ; ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size; + *ring->ctxt_wp =cpu_to_le64 (ring->iommu_base + ring->len - ring->el_size);/* Update all cores */ smp_wmb ();
@@ -420,7 +420,7 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)continue ; ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size; + *ring->ctxt_wp =cpu_to_le64 (ring->iommu_base + ring->len - ring->el_size);/* Update to all cores */ smp_wmb ();