[ipxe-devel] [PATCH v3 4/4] [virtio] Add virtio-net 1.0 support
Michael S. Tsirkin
mst at redhat.com
Tue Apr 5 17:52:32 UTC 2016
On Tue, Apr 05, 2016 at 05:38:24PM +0200, Ladi Prosek wrote:
> + /* Enable the PCI device only if we need to */
> + if ( ( virtnet->vdev.common.flags & VIRTIO_PCI_REGION_TYPE_MASK ) !=
> + VIRTIO_PCI_REGION_PCI_CONFIG ||
> + ( virtnet->vdev.isr.flags & VIRTIO_PCI_REGION_TYPE_MASK ) !=
> + VIRTIO_PCI_REGION_PCI_CONFIG ||
> + ( device && ( virtnet->vdev.device.flags & VIRTIO_PCI_REGION_TYPE_MASK ) !=
> + VIRTIO_PCI_REGION_PCI_CONFIG ) ) {
> + /* At least one BAR has been mapped */
> + adjust_pci_device ( pci );
> + virtnet->vdev.pci_device_initialized = 1;
> + }
This is slightly wrong for two reasons:
- it does not enable bus mastering
- unused BAR types are also enabled.
How about using the following to enable exactly what's
needed:
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h
index 89d9d80..e22ff54 100644
--- a/src/include/ipxe/pci.h
+++ b/src/include/ipxe/pci.h
@@ -278,6 +278,8 @@ struct pci_driver {
PCI_FUNC ( (pci)->busdevfn )
extern void adjust_pci_device ( struct pci_device *pci );
+extern unsigned enable_pci_device ( struct pci_device *pci, unsigned flags );
+extern void disable_pci_device ( struct pci_device *pci, unsigned flags );
extern unsigned long pci_bar_start ( struct pci_device *pci,
unsigned int reg );
extern int pci_read_config ( struct pci_device *pci );
diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
index 6fbedd9..6befb67 100644
--- a/src/drivers/bus/pci.c
+++ b/src/drivers/bus/pci.c
@@ -169,6 +169,49 @@ void adjust_pci_device ( struct pci_device *pci ) {
}
/**
+ * Enable PCI device
+ *
+ * @v pci PCI device
+ * @v flags Flags to enable
+ * @ret rc Original flags
+ *
+ * Enable device in case BIOS neglected to do so. Also
+ * adjust PCI latency timer to a reasonable value, 32.
+ */
+unsigned enable_pci_device ( struct pci_device *pci, unsigned flags ) {
+ unsigned short new_command, pci_command;
+ unsigned char pci_latency;
+
+ pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
+ new_command = ( pci_command | flags );
+ if ( pci_command != new_command ) {
+ DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating "
+ "PCI command %04x->%04x\n",
+ PCI_ARGS ( pci ), pci_command, new_command );
+ pci_write_config_word ( pci, PCI_COMMAND, new_command );
+ }
+
+ pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
+ if ( pci_latency < 32 ) {
+ DBGC ( pci, PCI_FMT " latency timer is unreasonably low at "
+ "%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency );
+ pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
+ }
+}
+
+/**
+ * Disable PCI device
+ *
+ * @v pci PCI device
+ * @v flags Flags to restore
+ *
+ * Restore device to state it had before we enabled it.
+ */
+void disable_pci_device ( struct pci_device *pci, unsigned flags ) {
+ pci_write_config_word ( pci, PCI_COMMAND, flags );
+}
+
+/**
* Read PCI device configuration
*
* @v pci PCI device
More information about the ipxe-devel
mailing list