Skip to content

Commit 95f408b

Browse files
b-rad-NDimchehab
authored andcommitted
media: cx23885: Ryzen DMA related RiSC engine stall fixes
This bug affects all of Hauppauge QuadHD boards when used on all Ryzen platforms and some XEON platforms. On these platforms it is possible to error out the RiSC engine and cause it to stall, whereafter the only way to reset the board to a working state is to reboot. This is the fatal condition with current driver: [ 255.663598] cx23885: cx23885[0]: mpeg risc op code error [ 255.663607] cx23885: cx23885[0]: TS1 B - dma channel status dump [ 255.663612] cx23885: cx23885[0]: cmds: init risc lo : 0xffe54000 [ 255.663615] cx23885: cx23885[0]: cmds: init risc hi : 0x00000000 [ 255.663619] cx23885: cx23885[0]: cmds: cdt base : 0x00010870 [ 255.663622] cx23885: cx23885[0]: cmds: cdt size : 0x0000000a [ 255.663625] cx23885: cx23885[0]: cmds: iq base : 0x00010630 [ 255.663629] cx23885: cx23885[0]: cmds: iq size : 0x00000010 [ 255.663632] cx23885: cx23885[0]: cmds: risc pc lo : 0xffe54018 [ 255.663636] cx23885: cx23885[0]: cmds: risc pc hi : 0x00000000 [ 255.663639] cx23885: cx23885[0]: cmds: iq wr ptr : 0x00004192 [ 255.663642] cx23885: cx23885[0]: cmds: iq rd ptr : 0x0000418c [ 255.663645] cx23885: cx23885[0]: cmds: cdt current : 0x00010898 [ 255.663649] cx23885: cx23885[0]: cmds: pci target lo : 0xf85ca340 [ 255.663652] cx23885: cx23885[0]: cmds: pci target hi : 0x00000000 [ 255.663655] cx23885: cx23885[0]: cmds: line / byte : 0x000c0000 [ 255.663659] cx23885: cx23885[0]: risc0: [ 255.663661] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663666] cx23885: cx23885[0]: risc1: [ 255.663667] 0xf85ca050 [ INVALID sol 22 20 19 18 resync 13 count=80 ] [ 255.663674] cx23885: cx23885[0]: risc2: [ 255.663674] 0x00000000 [ INVALID count=0 ] [ 255.663678] cx23885: cx23885[0]: risc3: [ 255.663679] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663684] cx23885: cx23885[0]: (0x00010630) iq 0: [ 255.663685] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663690] cx23885: cx23885[0]: iq 1: 0xf85ca630 [ arg #1 ] [ 255.663693] cx23885: cx23885[0]: iq 2: 0x00000000 [ arg #2 ] [ 255.663696] cx23885: cx23885[0]: (0x0001063c) iq 3: [ 255.663697] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663702] cx23885: cx23885[0]: iq 4: 0xf85ca920 [ arg #1 ] [ 255.663705] cx23885: cx23885[0]: iq 5: 0x00000000 [ arg #2 ] [ 255.663709] cx23885: cx23885[0]: (0x00010648) iq 6: [ 255.663709] 0xf85ca340 [ INVALID sol 22 20 19 18 resync 13 count=832 ] [ 255.663716] cx23885: cx23885[0]: (0x0001064c) iq 7: [ 255.663717] 0x00000000 [ INVALID count=0 ] [ 255.663721] cx23885: cx23885[0]: (0x00010650) iq 8: [ 255.663721] 0x00000000 [ INVALID count=0 ] [ 255.663725] cx23885: cx23885[0]: (0x00010654) iq 9: [ 255.663726] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663731] cx23885: cx23885[0]: iq a: 0xf85c9780 [ arg #1 ] [ 255.663734] cx23885: cx23885[0]: iq b: 0x00000000 [ arg #2 ] [ 255.663737] cx23885: cx23885[0]: (0x00010660) iq c: [ 255.663738] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663743] cx23885: cx23885[0]: iq d: 0xf85c9a70 [ arg #1 ] [ 255.663746] cx23885: cx23885[0]: iq e: 0x00000000 [ arg #2 ] [ 255.663749] cx23885: cx23885[0]: (0x0001066c) iq f: [ 255.663750] 0x1c0002f0 [ write sol eol count=752 ] [ 255.663755] cx23885: cx23885[0]: iq 10: 0xf4fa2920 [ arg #1 ] [ 255.663758] cx23885: cx23885[0]: iq 11: 0x00000000 [ arg #2 ] [ 255.663759] cx23885: cx23885[0]: fifo: 0x00005000 -> 0x6000 [ 255.663760] cx23885: cx23885[0]: ctrl: 0x00010630 -> 0x10690 [ 255.663764] cx23885: cx23885[0]: ptr1_reg: 0x00005980 [ 255.663767] cx23885: cx23885[0]: ptr2_reg: 0x000108a8 [ 255.663770] cx23885: cx23885[0]: cnt1_reg: 0x0000000b [ 255.663773] cx23885: cx23885[0]: cnt2_reg: 0x00000003 Included is checks of the TC_REQ and TC_REQ_SET registers during states of board initialization, reset, DMA start, and DMA stop. If both registers are set, this indicates a stall in the RiSC engine, at which point the bridge error is cleared. A small delay is introduced in stop_dma as well, to allow transfers in progress to finish. After application all models work on Ryzen, occasionally yielding: cx23885_clear_bridge_error: dma in progress detected 0x00000001 0x00000001, clearing Signed-off-by: Brad Love <brad@nextdimension.cc> Signed-off-by: Hans Verkuil <hansverk@cisco.com> [hansverk@cisco.com: fix compiler warning of unused 'reg' variable] Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
1 parent 3b8315f commit 95f408b

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

drivers/media/pci/cx23885/cx23885-core.c

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,25 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
601601
}
602602
}
603603

604+
static void cx23885_clear_bridge_error(struct cx23885_dev *dev)
605+
{
606+
uint32_t reg1_val = cx_read(TC_REQ); /* read-only */
607+
uint32_t reg2_val = cx_read(TC_REQ_SET);
608+
609+
if (reg1_val && reg2_val) {
610+
cx_write(TC_REQ, reg1_val);
611+
cx_write(TC_REQ_SET, reg2_val);
612+
cx_read(VID_B_DMA);
613+
cx_read(VBI_B_DMA);
614+
cx_read(VID_C_DMA);
615+
cx_read(VBI_C_DMA);
616+
617+
dev_info(&dev->pci->dev,
618+
"dma in progress detected 0x%08x 0x%08x, clearing\n",
619+
reg1_val, reg2_val);
620+
}
621+
}
622+
604623
static void cx23885_shutdown(struct cx23885_dev *dev)
605624
{
606625
/* disable RISC controller */
@@ -646,6 +665,8 @@ static void cx23885_reset(struct cx23885_dev *dev)
646665
cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
647666
cx_write(PAD_CTRL, 0x00500300);
648667

668+
/* clear dma in progress */
669+
cx23885_clear_bridge_error(dev);
649670
mdelay(100);
650671

651672
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
@@ -662,6 +683,11 @@ static void cx23885_reset(struct cx23885_dev *dev)
662683
cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
663684

664685
cx23885_gpio_setup(dev);
686+
687+
cx23885_irq_get_mask(dev);
688+
689+
/* clear dma in progress */
690+
cx23885_clear_bridge_error(dev);
665691
}
666692

667693

@@ -676,6 +702,8 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev)
676702
if (dev->bridge == CX23885_BRIDGE_885)
677703
cx_clear(RDR_TLCTL0, 1 << 4);
678704

705+
/* clear dma in progress */
706+
cx23885_clear_bridge_error(dev);
679707
return 0;
680708
}
681709

@@ -1352,6 +1380,9 @@ int cx23885_start_dma(struct cx23885_tsport *port,
13521380
dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
13531381
dev->width, dev->height, dev->field);
13541382

1383+
/* clear dma in progress */
1384+
cx23885_clear_bridge_error(dev);
1385+
13551386
/* Stop the fifo and risc engine for this port */
13561387
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
13571388

@@ -1432,39 +1463,67 @@ int cx23885_start_dma(struct cx23885_tsport *port,
14321463
case CX23885_BRIDGE_888:
14331464
/* enable irqs */
14341465
dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
1466+
/* clear dma in progress */
1467+
cx23885_clear_bridge_error(dev);
14351468
cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
14361469
cx_set(port->reg_dma_ctl, port->dma_ctl_val);
1470+
1471+
/* clear dma in progress */
1472+
cx23885_clear_bridge_error(dev);
14371473
cx23885_irq_add(dev, port->pci_irqmask);
14381474
cx23885_irq_enable_all(dev);
1475+
1476+
/* clear dma in progress */
1477+
cx23885_clear_bridge_error(dev);
14391478
break;
14401479
default:
14411480
BUG();
14421481
}
14431482

14441483
cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
1484+
/* clear dma in progress */
1485+
cx23885_clear_bridge_error(dev);
14451486

14461487
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
14471488
cx23885_av_clk(dev, 1);
14481489

14491490
if (debug > 4)
14501491
cx23885_tsport_reg_dump(port);
14511492

1493+
cx23885_irq_get_mask(dev);
1494+
1495+
/* clear dma in progress */
1496+
cx23885_clear_bridge_error(dev);
1497+
14521498
return 0;
14531499
}
14541500

14551501
static int cx23885_stop_dma(struct cx23885_tsport *port)
14561502
{
14571503
struct cx23885_dev *dev = port->dev;
14581504
u32 reg;
1505+
int delay = 0;
1506+
uint32_t reg1_val;
1507+
uint32_t reg2_val;
14591508

14601509
dprintk(1, "%s()\n", __func__);
14611510

14621511
/* Stop interrupts and DMA */
14631512
cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
14641513
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
1514+
/* just in case wait for any dma to complete before allowing dealloc */
1515+
mdelay(20);
1516+
for (delay = 0; delay < 100; delay++) {
1517+
reg1_val = cx_read(TC_REQ);
1518+
reg2_val = cx_read(TC_REQ_SET);
1519+
if (reg1_val == 0 || reg2_val == 0)
1520+
break;
1521+
mdelay(1);
1522+
}
1523+
dev_dbg(&dev->pci->dev, "delay=%d reg1=0x%08x reg2=0x%08x\n",
1524+
delay, reg1_val, reg2_val);
14651525

14661526
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
1467-
14681527
reg = cx_read(PAD_CTRL);
14691528

14701529
/* Set TS1_OE */
@@ -1475,7 +1534,6 @@ static int cx23885_stop_dma(struct cx23885_tsport *port)
14751534
cx_write(PAD_CTRL, reg);
14761535
cx_write(port->reg_src_sel, 0);
14771536
cx_write(port->reg_gen_ctrl, 8);
1478-
14791537
}
14801538

14811539
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)

drivers/media/pci/cx23885/cx23885-reg.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,18 @@ Channel manager Data Structure entry = 20 DWORD
288288
#define AUDIO_EXT_INT_MSTAT 0x00040068
289289
#define AUDIO_EXT_INT_SSTAT 0x0004006C
290290

291+
/* Bits [7:0] set in both TC_REQ and TC_REQ_SET
292+
* indicate a stall in the RISC engine for a
293+
* particular rider traffic class. This causes
294+
* the 885 and 888 bridges (unknown about 887)
295+
* to become inoperable. Setting bits in
296+
* TC_REQ_SET resets the corresponding bits
297+
* in TC_REQ (and TC_REQ_SET) allowing
298+
* operation to continue.
299+
*/
300+
#define TC_REQ 0x00040090
301+
#define TC_REQ_SET 0x00040094
302+
291303
#define RDR_CFG0 0x00050000
292304
#define RDR_CFG1 0x00050004
293305
#define RDR_CFG2 0x00050008
@@ -386,6 +398,8 @@ Channel manager Data Structure entry = 20 DWORD
386398
#define VID_B_PIXEL_FRMT 0x00130184
387399

388400
/* Video C Interface */
401+
#define VID_C_DMA 0x00130200
402+
#define VBI_C_DMA 0x00130208
389403
#define VID_C_GPCNT 0x00130220
390404
#define VID_C_GPCNT_CTL 0x00130230
391405
#define VBI_C_GPCNT_CTL 0x00130234

0 commit comments

Comments
 (0)