summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/accel/qaic/mhi_controller.c44
-rw-r--r--drivers/bus/mhi/ep/main.c12
-rw-r--r--drivers/bus/mhi/host/boot.c10
-rw-r--r--drivers/bus/mhi/host/init.c22
-rw-r--r--drivers/bus/mhi/host/internal.h3
-rw-r--r--drivers/bus/mhi/host/main.c81
-rw-r--r--drivers/bus/mhi/host/pci_generic.c20
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c4
-rw-r--r--include/linux/mhi.h14
-rw-r--r--net/qrtr/mhi.c69
11 files changed, 82 insertions, 201 deletions
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 13a14c6c6168..4d787f77ce41 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
@@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
.wake_capable = false,
},
{
@@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
.wake_capable = false,
},
};
diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c
index 3c208b5c8446..35922e7a24c1 100644
--- a/drivers/bus/mhi/ep/main.c
+++ b/drivers/bus/mhi/ep/main.c
@@ -1596,7 +1596,7 @@ void mhi_ep_unregister_controller(struct mhi_ep_cntrl *mhi_cntrl)
}
EXPORT_SYMBOL_GPL(mhi_ep_unregister_controller);
-static int mhi_ep_driver_probe(struct device *dev)
+static int mhi_ep_probe(struct device *dev)
{
struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev);
struct mhi_ep_driver *mhi_drv = to_mhi_ep_driver(dev->driver);
@@ -1609,7 +1609,7 @@ static int mhi_ep_driver_probe(struct device *dev)
return mhi_drv->probe(mhi_dev, mhi_dev->id);
}
-static int mhi_ep_driver_remove(struct device *dev)
+static void mhi_ep_remove(struct device *dev)
{
struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev);
struct mhi_ep_driver *mhi_drv = to_mhi_ep_driver(dev->driver);
@@ -1619,7 +1619,7 @@ static int mhi_ep_driver_remove(struct device *dev)
/* Skip if it is a controller device */
if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER)
- return 0;
+ return;
/* Disconnect the channels associated with the driver */
for (dir = 0; dir < 2; dir++) {
@@ -1643,8 +1643,6 @@ static int mhi_ep_driver_remove(struct device *dev)
/* Remove the client driver now */
mhi_drv->remove(mhi_dev);
-
- return 0;
}
int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner)
@@ -1660,8 +1658,6 @@ int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner
driver->bus = &mhi_ep_bus_type;
driver->owner = owner;
- driver->probe = mhi_ep_driver_probe;
- driver->remove = mhi_ep_driver_remove;
return driver_register(driver);
}
@@ -1708,6 +1704,8 @@ const struct bus_type mhi_ep_bus_type = {
.dev_name = "mhi_ep",
.match = mhi_ep_match,
.uevent = mhi_ep_uevent,
+ .probe = mhi_ep_probe,
+ .remove = mhi_ep_remove,
};
static int __init mhi_ep_init(void)
diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c
index 205d83ac069f..c76db35bc29a 100644
--- a/drivers/bus/mhi/host/boot.c
+++ b/drivers/bus/mhi/host/boot.c
@@ -584,6 +584,16 @@ skip_req_fw:
* device transitioning into MHI READY state
*/
if (fw_load_type == MHI_FW_LOAD_FBC) {
+ /*
+ * Some FW combine two separate ELF images (SBL + WLAN FW) in a single
+ * file. Hence, check for the existence of the second ELF header after
+ * SBL. If present, load the second image separately.
+ */
+ if (!memcmp(fw_data + mhi_cntrl->sbl_size, ELFMAG, SELFMAG)) {
+ fw_data += mhi_cntrl->sbl_size;
+ fw_sz -= mhi_cntrl->sbl_size;
+ }
+
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);
if (ret) {
release_firmware(firmware);
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
index 099be8dd1900..c47f66833cda 100644
--- a/drivers/bus/mhi/host/init.c
+++ b/drivers/bus/mhi/host/init.c
@@ -841,19 +841,9 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->lpm_notify = ch_cfg->lpm_notify;
mhi_chan->offload_ch = ch_cfg->offload_channel;
mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch;
- mhi_chan->pre_alloc = ch_cfg->auto_queue;
mhi_chan->wake_capable = ch_cfg->wake_capable;
/*
- * If MHI host allocates buffers, then the channel direction
- * should be DMA_FROM_DEVICE
- */
- if (mhi_chan->pre_alloc && mhi_chan->dir != DMA_FROM_DEVICE) {
- dev_err(dev, "Invalid channel configuration\n");
- goto error_chan_cfg;
- }
-
- /*
* Bi-directional and direction less channel must be an
* offload channel
*/
@@ -1265,7 +1255,7 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)
return mhi_dev;
}
-static int mhi_driver_probe(struct device *dev)
+static int mhi_probe(struct device *dev)
{
struct mhi_device *mhi_dev = to_mhi_device(dev);
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
@@ -1341,7 +1331,7 @@ exit_probe:
return ret;
}
-static int mhi_driver_remove(struct device *dev)
+static void mhi_remove(struct device *dev)
{
struct mhi_device *mhi_dev = to_mhi_device(dev);
struct mhi_driver *mhi_drv = to_mhi_driver(dev->driver);
@@ -1355,7 +1345,7 @@ static int mhi_driver_remove(struct device *dev)
/* Skip if it is a controller device */
if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER)
- return 0;
+ return;
/* Reset both channels */
for (dir = 0; dir < 2; dir++) {
@@ -1407,8 +1397,6 @@ static int mhi_driver_remove(struct device *dev)
while (mhi_dev->dev_wake)
mhi_device_put(mhi_dev);
-
- return 0;
}
int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)
@@ -1420,8 +1408,6 @@ int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)
driver->bus = &mhi_bus_type;
driver->owner = owner;
- driver->probe = mhi_driver_probe;
- driver->remove = mhi_driver_remove;
return driver_register(driver);
}
@@ -1468,6 +1454,8 @@ const struct bus_type mhi_bus_type = {
.dev_name = "mhi",
.match = mhi_match,
.uevent = mhi_uevent,
+ .probe = mhi_probe,
+ .remove = mhi_remove,
.dev_groups = mhi_dev_groups,
};
diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
index 7937bb1f742c..7b0ee5e3a12d 100644
--- a/drivers/bus/mhi/host/internal.h
+++ b/drivers/bus/mhi/host/internal.h
@@ -286,7 +286,6 @@ struct mhi_chan {
bool lpm_notify;
bool configured;
bool offload_ch;
- bool pre_alloc;
bool wake_capable;
};
@@ -389,8 +388,6 @@ int mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
struct image_info *img_info);
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl);
-/* Automatically allocate and queue inbound buffers */
-#define MHI_CH_INBOUND_ALLOC_BUFS BIT(0)
int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
struct mhi_chan *mhi_chan);
void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
index 861551274319..53c0ffe30070 100644
--- a/drivers/bus/mhi/host/main.c
+++ b/drivers/bus/mhi/host/main.c
@@ -664,23 +664,6 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
mhi_cntrl->runtime_put(mhi_cntrl);
}
- /*
- * Recycle the buffer if buffer is pre-allocated,
- * if there is an error, not much we can do apart
- * from dropping the packet
- */
- if (mhi_chan->pre_alloc) {
- if (mhi_queue_buf(mhi_chan->mhi_dev,
- mhi_chan->dir,
- buf_info->cb_buf,
- buf_info->len, MHI_EOT)) {
- dev_err(dev,
- "Error recycling buffer for chan:%d\n",
- mhi_chan->chan);
- kfree(buf_info->cb_buf);
- }
- }
-
read_lock_bh(&mhi_chan->lock);
}
break;
@@ -1177,17 +1160,12 @@ static int mhi_queue(struct mhi_device *mhi_dev, struct mhi_buf_info *buf_info,
int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
struct sk_buff *skb, size_t len, enum mhi_flags mflags)
{
- struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan :
- mhi_dev->dl_chan;
struct mhi_buf_info buf_info = { };
buf_info.v_addr = skb->data;
buf_info.cb_buf = skb;
buf_info.len = len;
- if (unlikely(mhi_chan->pre_alloc))
- return -EINVAL;
-
return mhi_queue(mhi_dev, &buf_info, dir, mflags);
}
EXPORT_SYMBOL_GPL(mhi_queue_skb);
@@ -1472,45 +1450,6 @@ static int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
if (ret)
goto error_pm_state;
- if (mhi_chan->dir == DMA_FROM_DEVICE)
- mhi_chan->pre_alloc = !!(flags & MHI_CH_INBOUND_ALLOC_BUFS);
-
- /* Pre-allocate buffer for xfer ring */
- if (mhi_chan->pre_alloc) {
- int nr_el = get_nr_avail_ring_elements(mhi_cntrl,
- &mhi_chan->tre_ring);
- size_t len = mhi_cntrl->buffer_len;
-
- while (nr_el--) {
- void *buf;
- struct mhi_buf_info info = { };
-
- buf = kmalloc(len, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto error_pre_alloc;
- }
-
- /* Prepare transfer descriptors */
- info.v_addr = buf;
- info.cb_buf = buf;
- info.len = len;
- ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &info, MHI_EOT);
- if (ret) {
- kfree(buf);
- goto error_pre_alloc;
- }
- }
-
- read_lock_bh(&mhi_cntrl->pm_lock);
- if (MHI_DB_ACCESS_VALID(mhi_cntrl)) {
- read_lock_irq(&mhi_chan->lock);
- mhi_ring_chan_db(mhi_cntrl, mhi_chan);
- read_unlock_irq(&mhi_chan->lock);
- }
- read_unlock_bh(&mhi_cntrl->pm_lock);
- }
-
mutex_unlock(&mhi_chan->mutex);
return 0;
@@ -1523,12 +1462,6 @@ error_init_chan:
mutex_unlock(&mhi_chan->mutex);
return ret;
-
-error_pre_alloc:
- mutex_unlock(&mhi_chan->mutex);
- mhi_unprepare_channel(mhi_cntrl, mhi_chan);
-
- return ret;
}
static void mhi_mark_stale_events(struct mhi_controller *mhi_cntrl,
@@ -1600,12 +1533,8 @@ static void mhi_reset_data_chan(struct mhi_controller *mhi_cntrl,
mhi_del_ring_element(mhi_cntrl, buf_ring);
mhi_del_ring_element(mhi_cntrl, tre_ring);
- if (mhi_chan->pre_alloc) {
- kfree(buf_info->cb_buf);
- } else {
- result.buf_addr = buf_info->cb_buf;
- mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result);
- }
+ result.buf_addr = buf_info->cb_buf;
+ mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result);
}
}
@@ -1666,12 +1595,6 @@ int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
}
EXPORT_SYMBOL_GPL(mhi_prepare_for_transfer);
-int mhi_prepare_for_transfer_autoqueue(struct mhi_device *mhi_dev)
-{
- return __mhi_prepare_for_transfer(mhi_dev, MHI_CH_INBOUND_ALLOC_BUFS);
-}
-EXPORT_SYMBOL_GPL(mhi_prepare_for_transfer_autoqueue);
-
void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index e3bc737313a2..0884a384b77f 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
-#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
- { \
- .num = ch_num, \
- .name = ch_name, \
- .num_elements = el_count, \
- .event_ring = ev_ring, \
- .dir = DMA_FROM_DEVICE, \
- .ee_mask = BIT(MHI_EE_AMSS), \
- .pollcfg = 0, \
- .doorbell = MHI_DB_BRST_DISABLE, \
- .lpm_notify = false, \
- .offload_channel = false, \
- .doorbell_mode_switch = false, \
- .auto_queue = true, \
- }
-
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
- MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
+ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index acd76e9392d3..d2c44f7f9b62 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -34,7 +34,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -48,7 +47,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -99,7 +97,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -113,7 +110,6 @@ static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 08f44baf182a..2dbdb95ae7be 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -31,7 +31,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -45,7 +44,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
@@ -96,7 +94,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = false,
},
{
.num = 21,
@@ -110,7 +107,6 @@ static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
- .auto_queue = true,
},
};
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index dd372b0123a6..88ccb3e14f48 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -215,7 +215,6 @@ enum mhi_db_brst_mode {
* @lpm_notify: The channel master requires low power mode notifications
* @offload_channel: The client manages the channel completely
* @doorbell_mode_switch: Channel switches to doorbell mode on M0 transition
- * @auto_queue: Framework will automatically queue buffers for DL traffic
* @wake-capable: Channel capable of waking up the system
*/
struct mhi_channel_config {
@@ -232,7 +231,6 @@ struct mhi_channel_config {
bool lpm_notify;
bool offload_channel;
bool doorbell_mode_switch;
- bool auto_queue;
bool wake_capable;
};
@@ -744,18 +742,6 @@ void mhi_device_put(struct mhi_device *mhi_dev);
int mhi_prepare_for_transfer(struct mhi_device *mhi_dev);
/**
- * mhi_prepare_for_transfer_autoqueue - Setup UL and DL channels with auto queue
- * buffers for DL traffic
- * @mhi_dev: Device associated with the channels
- *
- * Allocate and initialize the channel context and also issue the START channel
- * command to both channels. Channels can be started only if both host and
- * device execution environments match and channels are in a DISABLED state.
- * The MHI core will automatically allocate and queue buffers for the DL traffic.
- */
-int mhi_prepare_for_transfer_autoqueue(struct mhi_device *mhi_dev);
-
-/**
* mhi_unprepare_from_transfer - Reset UL and DL channels for data transfer.
* Issue the RESET channel command and let the
* device clean-up the context so no incoming
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index 69f53625a049..80e341d2f8a4 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -24,13 +24,25 @@ static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
int rc;
- if (!qdev || mhi_res->transaction_status)
+ if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
return;
+ /* Channel got reset. So just free the buffer */
+ if (mhi_res->transaction_status == -ENOTCONN) {
+ devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
+ return;
+ }
+
rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
mhi_res->bytes_xferd);
if (rc == -EINVAL)
dev_err(qdev->dev, "invalid ipcrouter packet\n");
+
+ /* Done with the buffer, now recycle it for future use */
+ rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
+ mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
+ if (rc)
+ dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}
/* From QRTR to MHI */
@@ -72,6 +84,29 @@ free_skb:
return rc;
}
+static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
+{
+ u32 free_desc;
+ void *buf;
+ int ret;
+
+ free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
+ while (free_desc--) {
+ buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
+ MHI_EOT);
+ if (ret) {
+ dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
@@ -87,20 +122,30 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->ep.xmit = qcom_mhi_qrtr_send;
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
- if (rc)
- return rc;
/* start channels */
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc) {
- qrtr_endpoint_unregister(&qdev->ep);
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc)
return rc;
- }
+
+ rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
+ if (rc)
+ goto err_unprepare;
+
+ rc = qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
+ if (rc)
+ goto err_unregister;
dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
return 0;
+
+err_unregister:
+ qrtr_endpoint_unregister(&qdev->ep);
+err_unprepare:
+ mhi_unprepare_from_transfer(mhi_dev);
+
+ return rc;
}
static void qcom_mhi_qrtr_remove(struct mhi_device *mhi_dev)
@@ -151,11 +196,13 @@ static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
if (state == MHI_STATE_M3)
return 0;
- rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
- if (rc)
+ rc = mhi_prepare_for_transfer(mhi_dev);
+ if (rc) {
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
+ return rc;
+ }
- return rc;
+ return qcom_mhi_qrtr_queue_dl_buffers(mhi_dev);
}
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {