Question on MSI support in PCI and PCI-E devices
Andrey Utkin
andrey.krieger.utkin at gmail.com
Thu Feb 12 10:11:58 EST 2015
2015-02-12 16:48 GMT+02:00 Stephen Hemminger <stephen at networkplumber.org>:
> On Wed, 11 Feb 2015 18:19:00 +0000
> Andrey Utkin <andrey.krieger.utkin at gmail.com> wrote:
>
>> Is it true that _every_ PCI or PCI Express device supporting MSI is
>> indicated by some mention of MSI in "lspci -v", and if there's no such
>> mention, it surely doesn't support MSI?
>>
>
> Look at kernel source (drivers/pci/msi.c) function pci_msi_supported
> there are many things which can block MSI.
>
> There can be cases where PCI quirks in kernel block MSI
> because for example the device supports MSI, but the motherboard
> BIOS is broken. This only happens on really old systems.
Thank you for your reply.
However, I was more interested in the case when lspci for device
doesn't mention MSI at all, so I wonder if it makes sense to try to
enable it in the driver at all.
04:05.0 Multimedia video controller: Bluecherry BC-H16480A 16 port
H.264 video and audio encoder / decoder
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop-
ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium
>TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 64 (250ns max), Cache Line Size: 32 bytes
Interrupt: pin A routed to IRQ 16
Region 0: Memory at faff0000 (32-bit, prefetchable) [size=64K]
Kernel driver in use: solo6x10
We have such cards, and we have issues with them - at some moment they
stop producing interrupts. No matter whether they share interrupt
number or not.
There was a recent commit from Krzysztof Hałasa
(3c787b108fe0d1c341a76e718a25897ae14673cf) which improved things, but
the issue still happens regularly on some setups.
Now I've tried the following change, i've introduced such a loop which
I see in bt8xx and ddbridge drivers. This also didn't help. So I'm out
of ideas now (any comments are highly appreciated!); I have read about
MSI, that this interrupts transmission mechanism is more reliable and
fast, but from lspci output it is not clear whether our cards support
MSI at all.
--- a/drivers/media/pci/solo6x10/solo6x10-core.c
+++ b/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -100,10 +100,13 @@ static irqreturn_t solo_isr(int irq, void *data)
struct solo_dev *solo_dev = data;
u32 status;
int i;
+ int handled = 0;
+ while (1) {
status = solo_reg_read(solo_dev, SOLO_IRQ_STAT);
if (!status)
- return IRQ_NONE;
+ break;
+ handled++;
/* Acknowledge all interrupts immediately */
solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
@@ -129,7 +132,11 @@ static irqreturn_t solo_isr(int irq, void *data)
if (status & SOLO_IRQ_G723)
solo_g723_isr(solo_dev);
- return IRQ_HANDLED;
+ }
+
+ if (handled > 1)
+ solo_dev->isr_more_laps++;
+ return IRQ_RETVAL(handled);
}
static void free_solo_dev(struct solo_dev *solo_dev)
@@ -232,6 +239,16 @@ static ssize_t p2m_timeouts_show(struct device *dev,
return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
}
+static ssize_t isr_more_laps_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct solo_dev *solo_dev =
+ container_of(dev, struct solo_dev, dev);
+
+ return sprintf(buf, "%d\n", solo_dev->isr_more_laps);
+}
+
static ssize_t sdram_size_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -415,6 +432,7 @@ static const struct device_attribute solo_dev_attrs[] = {
__ATTR_RO(input_map),
__ATTR_RO(intervals),
__ATTR_RO(sdram_offsets),
+ __ATTR_RO(isr_more_laps),
};
static void solo_device_release(struct device *dev)
index d19c0ae..dffd7d7
--- a/drivers/media/pci/solo6x10/solo6x10-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-enc.c
@@ -28,7 +28,7 @@
#define VI_PROG_HSIZE (1280 - 16)
#define VI_PROG_VSIZE (1024 - 16)
-#define IRQ_LEVEL 2
+#define IRQ_LEVEL 3
static void solo_capture_config(struct solo_dev *solo_dev)
{
index 6c9bc70..4799ea2
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -277,6 +277,8 @@ struct solo_dev {
spinlock_t slock;
int old_write;
struct list_head vidq_active;
+
+ int isr_more_laps;
};
static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
--
Andrey Utkin
More information about the Kernelnewbies
mailing list