Skip to content

Commit b9c1de8

Browse files
committed
Merge: automotive: MHI bus upgrade to 6.15-rc7
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/922 JIRA: https://issues.redhat.com/browse/RHEL-93880 Update MHI bus to 6.15-rc7 for supporting automotive use case on Qualcomm boards such as Ride4. Signed-off-by: Mattijs Korpershoek <mkorpershoek@redhat.com> The associated owners change is at: - https://gitlab.com/redhat/centos-stream/src/kernel/documentation/-/merge_requests/936 Approved-by: Jared Kangas <jkangas@redhat.com> Approved-by: Brian Masney <bmasney@redhat.com> Approved-by: Eric Chanudet <echanude@redhat.com> Approved-by: John W. Linville <linville@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 8a50033 + 3720b3a commit b9c1de8

File tree

8 files changed

+206
-115
lines changed

8 files changed

+206
-115
lines changed

drivers/bus/mhi/host/boot.c

Lines changed: 150 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,36 @@ int mhi_download_rddm_image(struct mhi_controller *mhi_cntrl, bool in_panic)
177177
}
178178
EXPORT_SYMBOL_GPL(mhi_download_rddm_image);
179179

180+
static void mhi_fw_load_error_dump(struct mhi_controller *mhi_cntrl)
181+
{
182+
struct device *dev = &mhi_cntrl->mhi_dev->dev;
183+
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
184+
void __iomem *base = mhi_cntrl->bhi;
185+
int ret, i;
186+
u32 val;
187+
struct {
188+
char *name;
189+
u32 offset;
190+
} error_reg[] = {
191+
{ "ERROR_CODE", BHI_ERRCODE },
192+
{ "ERROR_DBG1", BHI_ERRDBG1 },
193+
{ "ERROR_DBG2", BHI_ERRDBG2 },
194+
{ "ERROR_DBG3", BHI_ERRDBG3 },
195+
{ NULL },
196+
};
197+
198+
read_lock_bh(pm_lock);
199+
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
200+
for (i = 0; error_reg[i].name; i++) {
201+
ret = mhi_read_reg(mhi_cntrl, base, error_reg[i].offset, &val);
202+
if (ret)
203+
break;
204+
dev_err(dev, "Reg: %s value: 0x%x\n", error_reg[i].name, val);
205+
}
206+
}
207+
read_unlock_bh(pm_lock);
208+
}
209+
180210
static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl,
181211
const struct mhi_buf *mhi_buf)
182212
{
@@ -226,24 +256,13 @@ static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl,
226256
}
227257

228258
static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl,
229-
dma_addr_t dma_addr,
230-
size_t size)
259+
const struct mhi_buf *mhi_buf)
231260
{
232-
u32 tx_status, val, session_id;
233-
int i, ret;
234-
void __iomem *base = mhi_cntrl->bhi;
235-
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
236261
struct device *dev = &mhi_cntrl->mhi_dev->dev;
237-
struct {
238-
char *name;
239-
u32 offset;
240-
} error_reg[] = {
241-
{ "ERROR_CODE", BHI_ERRCODE },
242-
{ "ERROR_DBG1", BHI_ERRDBG1 },
243-
{ "ERROR_DBG2", BHI_ERRDBG2 },
244-
{ "ERROR_DBG3", BHI_ERRDBG3 },
245-
{ NULL },
246-
};
262+
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
263+
void __iomem *base = mhi_cntrl->bhi;
264+
u32 tx_status, session_id;
265+
int ret;
247266

248267
read_lock_bh(pm_lock);
249268
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
@@ -255,11 +274,9 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl,
255274
dev_dbg(dev, "Starting image download via BHI. Session ID: %u\n",
256275
session_id);
257276
mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0);
258-
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH,
259-
upper_32_bits(dma_addr));
260-
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW,
261-
lower_32_bits(dma_addr));
262-
mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size);
277+
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, upper_32_bits(mhi_buf->dma_addr));
278+
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, lower_32_bits(mhi_buf->dma_addr));
279+
mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, mhi_buf->len);
263280
mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, session_id);
264281
read_unlock_bh(pm_lock);
265282

@@ -274,18 +291,7 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl,
274291

275292
if (tx_status == BHI_STATUS_ERROR) {
276293
dev_err(dev, "Image transfer failed\n");
277-
read_lock_bh(pm_lock);
278-
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
279-
for (i = 0; error_reg[i].name; i++) {
280-
ret = mhi_read_reg(mhi_cntrl, base,
281-
error_reg[i].offset, &val);
282-
if (ret)
283-
break;
284-
dev_err(dev, "Reg: %s value: 0x%x\n",
285-
error_reg[i].name, val);
286-
}
287-
}
288-
read_unlock_bh(pm_lock);
294+
mhi_fw_load_error_dump(mhi_cntrl);
289295
goto invalid_pm_state;
290296
}
291297

@@ -296,6 +302,16 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl,
296302
return -EIO;
297303
}
298304

305+
static void mhi_free_bhi_buffer(struct mhi_controller *mhi_cntrl,
306+
struct image_info *image_info)
307+
{
308+
struct mhi_buf *mhi_buf = image_info->mhi_buf;
309+
310+
dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr);
311+
kfree(image_info->mhi_buf);
312+
kfree(image_info);
313+
}
314+
299315
void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
300316
struct image_info *image_info)
301317
{
@@ -310,6 +326,45 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
310326
kfree(image_info);
311327
}
312328

329+
static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl,
330+
struct image_info **image_info,
331+
size_t alloc_size)
332+
{
333+
struct image_info *img_info;
334+
struct mhi_buf *mhi_buf;
335+
336+
img_info = kzalloc(sizeof(*img_info), GFP_KERNEL);
337+
if (!img_info)
338+
return -ENOMEM;
339+
340+
/* Allocate memory for entry */
341+
img_info->mhi_buf = kzalloc(sizeof(*img_info->mhi_buf), GFP_KERNEL);
342+
if (!img_info->mhi_buf)
343+
goto error_alloc_mhi_buf;
344+
345+
/* Allocate and populate vector table */
346+
mhi_buf = img_info->mhi_buf;
347+
348+
mhi_buf->len = alloc_size;
349+
mhi_buf->buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len,
350+
&mhi_buf->dma_addr, GFP_KERNEL);
351+
if (!mhi_buf->buf)
352+
goto error_alloc_segment;
353+
354+
img_info->bhi_vec = NULL;
355+
img_info->entries = 1;
356+
*image_info = img_info;
357+
358+
return 0;
359+
360+
error_alloc_segment:
361+
kfree(mhi_buf);
362+
error_alloc_mhi_buf:
363+
kfree(img_info);
364+
365+
return -ENOMEM;
366+
}
367+
313368
int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
314369
struct image_info **image_info,
315370
size_t alloc_size)
@@ -365,9 +420,9 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
365420
return -ENOMEM;
366421
}
367422

368-
static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
369-
const u8 *buf, size_t remainder,
370-
struct image_info *img_info)
423+
static void mhi_firmware_copy_bhie(struct mhi_controller *mhi_cntrl,
424+
const u8 *buf, size_t remainder,
425+
struct image_info *img_info)
371426
{
372427
size_t to_cpy;
373428
struct mhi_buf *mhi_buf = img_info->mhi_buf;
@@ -386,15 +441,61 @@ static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
386441
}
387442
}
388443

444+
static enum mhi_fw_load_type mhi_fw_load_type_get(const struct mhi_controller *mhi_cntrl)
445+
{
446+
if (mhi_cntrl->fbc_download) {
447+
return MHI_FW_LOAD_FBC;
448+
} else {
449+
if (mhi_cntrl->seg_len)
450+
return MHI_FW_LOAD_BHIE;
451+
else
452+
return MHI_FW_LOAD_BHI;
453+
}
454+
}
455+
456+
static int mhi_load_image_bhi(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size)
457+
{
458+
struct image_info *image;
459+
int ret;
460+
461+
ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size);
462+
if (ret)
463+
return ret;
464+
465+
/* Load the firmware into BHI vec table */
466+
memcpy(image->mhi_buf->buf, fw_data, size);
467+
468+
ret = mhi_fw_load_bhi(mhi_cntrl, &image->mhi_buf[image->entries - 1]);
469+
mhi_free_bhi_buffer(mhi_cntrl, image);
470+
471+
return ret;
472+
}
473+
474+
static int mhi_load_image_bhie(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size)
475+
{
476+
struct image_info *image;
477+
int ret;
478+
479+
ret = mhi_alloc_bhie_table(mhi_cntrl, &image, size);
480+
if (ret)
481+
return ret;
482+
483+
mhi_firmware_copy_bhie(mhi_cntrl, fw_data, size, image);
484+
485+
ret = mhi_fw_load_bhie(mhi_cntrl, &image->mhi_buf[image->entries - 1]);
486+
mhi_free_bhie_table(mhi_cntrl, image);
487+
488+
return ret;
489+
}
490+
389491
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
390492
{
391493
const struct firmware *firmware = NULL;
392494
struct device *dev = &mhi_cntrl->mhi_dev->dev;
495+
enum mhi_fw_load_type fw_load_type;
393496
enum mhi_pm_state new_state;
394497
const char *fw_name;
395498
const u8 *fw_data;
396-
void *buf;
397-
dma_addr_t dma_addr;
398499
size_t size, fw_sz;
399500
int ret;
400501

@@ -453,21 +554,17 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
453554
fw_sz = firmware->size;
454555

455556
skip_req_fw:
456-
buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, size, &dma_addr,
457-
GFP_KERNEL);
458-
if (!buf) {
459-
release_firmware(firmware);
460-
goto error_fw_load;
461-
}
462-
463-
/* Download image using BHI */
464-
memcpy(buf, fw_data, size);
465-
ret = mhi_fw_load_bhi(mhi_cntrl, dma_addr, size);
466-
dma_free_coherent(mhi_cntrl->cntrl_dev, size, buf, dma_addr);
557+
fw_load_type = mhi_fw_load_type_get(mhi_cntrl);
558+
if (fw_load_type == MHI_FW_LOAD_BHIE)
559+
ret = mhi_load_image_bhie(mhi_cntrl, fw_data, size);
560+
else
561+
ret = mhi_load_image_bhi(mhi_cntrl, fw_data, size);
467562

468563
/* Error or in EDL mode, we're done */
469564
if (ret) {
470-
dev_err(dev, "MHI did not load image over BHI, ret: %d\n", ret);
565+
dev_err(dev, "MHI did not load image over BHI%s, ret: %d\n",
566+
fw_load_type == MHI_FW_LOAD_BHIE ? "e" : "",
567+
ret);
471568
release_firmware(firmware);
472569
goto error_fw_load;
473570
}
@@ -486,15 +583,15 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
486583
* If we're doing fbc, populate vector tables while
487584
* device transitioning into MHI READY state
488585
*/
489-
if (mhi_cntrl->fbc_download) {
586+
if (fw_load_type == MHI_FW_LOAD_FBC) {
490587
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);
491588
if (ret) {
492589
release_firmware(firmware);
493590
goto error_fw_load;
494591
}
495592

496593
/* Load the firmware into BHIE vec table */
497-
mhi_firmware_copy(mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image);
594+
mhi_firmware_copy_bhie(mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image);
498595
}
499596

500597
release_firmware(firmware);
@@ -511,7 +608,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
511608
return;
512609

513610
error_ready_state:
514-
if (mhi_cntrl->fbc_download) {
611+
if (mhi_cntrl->fbc_image) {
515612
mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image);
516613
mhi_cntrl->fbc_image = NULL;
517614
}

drivers/bus/mhi/host/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
11441144
}
11451145
mhi_cntrl->bhi = mhi_cntrl->regs + bhi_off;
11461146

1147-
if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size) {
1147+
if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size || mhi_cntrl->seg_len) {
11481148
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF,
11491149
&bhie_off);
11501150
if (ret) {

drivers/bus/mhi/host/internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ struct bhi_vec_entry {
2929
u64 size;
3030
};
3131

32+
enum mhi_fw_load_type {
33+
MHI_FW_LOAD_BHI, /* BHI only in PBL */
34+
MHI_FW_LOAD_BHIE, /* BHIe only in PBL */
35+
MHI_FW_LOAD_FBC, /* BHI in PBL followed by BHIe in SBL */
36+
MHI_FW_LOAD_MAX,
37+
};
38+
3239
enum mhi_ch_state_type {
3340
MHI_CH_STATE_TYPE_RESET,
3441
MHI_CH_STATE_TYPE_STOP,

drivers/bus/mhi/host/main.c

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,37 +1181,23 @@ int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
11811181
}
11821182
EXPORT_SYMBOL_GPL(mhi_queue_skb);
11831183

1184-
int mhi_queue_dma(struct mhi_device *mhi_dev, enum dma_data_direction dir,
1185-
struct mhi_buf *mhi_buf, size_t len, enum mhi_flags mflags)
1186-
{
1187-
struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan :
1188-
mhi_dev->dl_chan;
1189-
struct mhi_buf_info buf_info = { };
1190-
1191-
buf_info.p_addr = mhi_buf->dma_addr;
1192-
buf_info.cb_buf = mhi_buf;
1193-
buf_info.pre_mapped = true;
1194-
buf_info.len = len;
1195-
1196-
if (unlikely(mhi_chan->pre_alloc))
1197-
return -EINVAL;
1198-
1199-
return mhi_queue(mhi_dev, &buf_info, dir, mflags);
1200-
}
1201-
EXPORT_SYMBOL_GPL(mhi_queue_dma);
1202-
12031184
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
12041185
struct mhi_buf_info *info, enum mhi_flags flags)
12051186
{
12061187
struct mhi_ring *buf_ring, *tre_ring;
12071188
struct mhi_ring_element *mhi_tre;
12081189
struct mhi_buf_info *buf_info;
12091190
int eot, eob, chain, bei;
1210-
int ret;
1191+
int ret = 0;
12111192

12121193
/* Protect accesses for reading and incrementing WP */
12131194
write_lock_bh(&mhi_chan->lock);
12141195

1196+
if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) {
1197+
ret = -ENODEV;
1198+
goto out;
1199+
}
1200+
12151201
buf_ring = &mhi_chan->buf_ring;
12161202
tre_ring = &mhi_chan->tre_ring;
12171203

@@ -1229,10 +1215,8 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
12291215

12301216
if (!info->pre_mapped) {
12311217
ret = mhi_cntrl->map_single(mhi_cntrl, buf_info);
1232-
if (ret) {
1233-
write_unlock_bh(&mhi_chan->lock);
1234-
return ret;
1235-
}
1218+
if (ret)
1219+
goto out;
12361220
}
12371221

12381222
eob = !!(flags & MHI_EOB);
@@ -1250,9 +1234,10 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
12501234
mhi_add_ring_element(mhi_cntrl, tre_ring);
12511235
mhi_add_ring_element(mhi_cntrl, buf_ring);
12521236

1237+
out:
12531238
write_unlock_bh(&mhi_chan->lock);
12541239

1255-
return 0;
1240+
return ret;
12561241
}
12571242

12581243
int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir,

0 commit comments

Comments
 (0)