pci: mvebu: fix the emulation of the status register
The status register of the PCI configuration space of PCI-to-PCI bridges contain some read-only bits, and so write-1-to-clear bits. So, the Linux PCI core sometimes writes 0xffff to this status register, and in the current PCI-to-PCI bridge emulation code of the Marvell driver, we do take all those 1s being written. Even the read-only bits are being overwritten. For now, all the read-only bits should be emulated to have the zero value. The other bits, that are write-1-to-clear bits are used to report various kind of errors, and are never set by the emulated bridge, so there is no need to support this write-1-to-clear bits mechanism. As a conclusion, the easiest solution is to simply emulate this status register by returning zero when read, and ignore the writes to it. This has two visible effects: * The devsel is no longer 'unknown' in, i.e Flags: bus master, 66MHz, user-definable features, ?? devsel, latency 0 becomes: Flags: bus master, 66MHz, user-definable features, fast devsel, latency 0 in lspci -v. This was caused by a value of 11b being read for devsel, which is an invalid value. This 11b value being read was due to a previous write of 0xffff into the status register. * The capability list is no longer broken, because we indicate to the Linux PCI core that we don't have a Capabilities Pointer in the PCI configuration space of this bridge. The following message is therefore no longer visible in lspci -v: Capabilities: [fc] <chain broken> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
This commit is contained in:
parent
197fc226d9
commit
6eb237c41a
|
@ -69,7 +69,6 @@ struct mvebu_sw_pci_bridge {
|
|||
u16 vendor;
|
||||
u16 device;
|
||||
u16 command;
|
||||
u16 status;
|
||||
u16 class;
|
||||
u8 interface;
|
||||
u8 revision;
|
||||
|
@ -359,7 +358,6 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
|
|||
|
||||
memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
|
||||
|
||||
bridge->status = PCI_STATUS_CAP_LIST;
|
||||
bridge->class = PCI_CLASS_BRIDGE_PCI;
|
||||
bridge->vendor = PCI_VENDOR_ID_MARVELL;
|
||||
bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
|
||||
|
@ -386,7 +384,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
|
|||
break;
|
||||
|
||||
case PCI_COMMAND:
|
||||
*value = bridge->status << 16 | bridge->command;
|
||||
*value = bridge->command;
|
||||
break;
|
||||
|
||||
case PCI_CLASS_REVISION:
|
||||
|
@ -479,7 +477,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
|
|||
switch (where & ~3) {
|
||||
case PCI_COMMAND:
|
||||
bridge->command = value & 0xffff;
|
||||
bridge->status = value >> 16;
|
||||
break;
|
||||
|
||||
case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
|
||||
|
|
Loading…
Reference in New Issue