Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: smipcie: fix interrupt handling and IR timeout

After the first IR message, interrupts are no longer received. In addition,
the code generates a timeout IR message of 10ms but sets the timeout value
to 100ms, so no timeout was ever generated.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=204317

Fixes: a49a7a4635de ("media: smipcie: add universal ir capability")
Tested-by: Laz Lev <lazlev@web.de>
Cc: stable@vger.kernel.org # v5.1+
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
65329232 2e74a01f

+26 -20
+26 -20
drivers/media/pci/smipcie/smipcie-ir.c
··· 60 60 { 61 61 struct smi_dev *dev = ir->dev; 62 62 struct rc_dev *rc_dev = ir->rc_dev; 63 - u32 dwIRControl, dwIRData; 64 - u8 index, ucIRCount, readLoop; 63 + u32 control, data; 64 + u8 index, ir_count, read_loop; 65 65 66 - dwIRControl = smi_read(IR_Init_Reg); 66 + control = smi_read(IR_Init_Reg); 67 67 68 - if (dwIRControl & rbIRVld) { 69 - ucIRCount = (u8) smi_read(IR_Data_Cnt); 68 + dev_dbg(&rc_dev->dev, "ircontrol: 0x%08x\n", control); 70 69 71 - readLoop = ucIRCount/4; 72 - if (ucIRCount % 4) 73 - readLoop += 1; 74 - for (index = 0; index < readLoop; index++) { 75 - dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index * 4)); 70 + if (control & rbIRVld) { 71 + ir_count = (u8)smi_read(IR_Data_Cnt); 76 72 77 - ir->irData[index*4 + 0] = (u8)(dwIRData); 78 - ir->irData[index*4 + 1] = (u8)(dwIRData >> 8); 79 - ir->irData[index*4 + 2] = (u8)(dwIRData >> 16); 80 - ir->irData[index*4 + 3] = (u8)(dwIRData >> 24); 73 + dev_dbg(&rc_dev->dev, "ircount %d\n", ir_count); 74 + 75 + read_loop = ir_count / 4; 76 + if (ir_count % 4) 77 + read_loop += 1; 78 + for (index = 0; index < read_loop; index++) { 79 + data = smi_read(IR_DATA_BUFFER_BASE + (index * 4)); 80 + dev_dbg(&rc_dev->dev, "IRData 0x%08x\n", data); 81 + 82 + ir->irData[index * 4 + 0] = (u8)(data); 83 + ir->irData[index * 4 + 1] = (u8)(data >> 8); 84 + ir->irData[index * 4 + 2] = (u8)(data >> 16); 85 + ir->irData[index * 4 + 3] = (u8)(data >> 24); 81 86 } 82 - smi_raw_process(rc_dev, ir->irData, ucIRCount); 83 - smi_set(IR_Init_Reg, rbIRVld); 87 + smi_raw_process(rc_dev, ir->irData, ir_count); 84 88 } 85 89 86 - if (dwIRControl & rbIRhighidle) { 90 + if (control & rbIRhighidle) { 87 91 struct ir_raw_event rawir = {}; 92 + 93 + dev_dbg(&rc_dev->dev, "high idle\n"); 88 94 89 95 rawir.pulse = 0; 90 96 rawir.duration = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN; 91 97 ir_raw_event_store_with_filter(rc_dev, &rawir); 92 - smi_set(IR_Init_Reg, rbIRhighidle); 93 98 } 94 99 100 + smi_set(IR_Init_Reg, rbIRVld); 95 101 ir_raw_event_handle(rc_dev); 96 102 } 97 103 ··· 156 150 rc_dev->dev.parent = &dev->pci_dev->dev; 157 151 158 152 rc_dev->map_name = dev->info->rc_map; 159 - rc_dev->timeout = MS_TO_US(100); 153 + rc_dev->timeout = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN; 160 154 rc_dev->rx_resolution = SMI_SAMPLE_PERIOD; 161 155 162 156 ir->rc_dev = rc_dev; ··· 179 173 struct smi_rc *ir = &dev->ir; 180 174 struct rc_dev *rc_dev = ir->rc_dev; 181 175 182 - smi_ir_stop(ir); 183 176 rc_unregister_device(rc_dev); 177 + smi_ir_stop(ir); 184 178 ir->rc_dev = NULL; 185 179 }