[intelxl] Use non-zero MSI-X vector for virtual function interrupts

The 100 Gigabit physical function driver requires a virtual function
driver to request that transmit and receive queues are mapped to MSI-X
vector 1 or higher.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/697/head^2
Michael Brown 2022-03-09 00:24:22 +00:00
parent 1b61c2118c
commit b4216fa506
4 changed files with 39 additions and 18 deletions

View File

@ -104,10 +104,11 @@ static int intelxl_fetch_mac ( struct intelxl_nic *intelxl,
*
* @v intelxl Intel device
* @v pci PCI device
* @v vector MSI-X vector
* @ret rc Return status code
*/
int intelxl_msix_enable ( struct intelxl_nic *intelxl,
struct pci_device *pci ) {
struct pci_device *pci, unsigned int vector ) {
int rc;
/* Map dummy target location */
@ -126,12 +127,12 @@ int intelxl_msix_enable ( struct intelxl_nic *intelxl,
goto err_enable;
}
/* Configure interrupt zero to write to dummy location */
pci_msix_map ( &intelxl->msix.cap, 0,
/* Configure interrupt to write to dummy location */
pci_msix_map ( &intelxl->msix.cap, vector,
dma ( &intelxl->msix.map, &intelxl->msix.msg ), 0 );
/* Enable dummy interrupt zero */
pci_msix_unmask ( &intelxl->msix.cap, 0 );
/* Enable dummy interrupt */
pci_msix_unmask ( &intelxl->msix.cap, vector );
return 0;
@ -147,12 +148,13 @@ int intelxl_msix_enable ( struct intelxl_nic *intelxl,
*
* @v intelxl Intel device
* @v pci PCI device
* @v vector MSI-X vector
*/
void intelxl_msix_disable ( struct intelxl_nic *intelxl,
struct pci_device *pci ) {
struct pci_device *pci, unsigned int vector ) {
/* Disable dummy interrupt zero */
pci_msix_mask ( &intelxl->msix.cap, 0 );
/* Disable dummy interrupts */
pci_msix_mask ( &intelxl->msix.cap, vector );
/* Disable MSI-X capability */
pci_msix_disable ( pci, &intelxl->msix.cap );
@ -1707,7 +1709,8 @@ static int intelxl_probe ( struct pci_device *pci ) {
goto err_fetch_mac;
/* Enable MSI-X dummy interrupt */
if ( ( rc = intelxl_msix_enable ( intelxl, pci ) ) != 0 )
if ( ( rc = intelxl_msix_enable ( intelxl, pci,
INTELXL_MSIX_VECTOR ) ) != 0 )
goto err_msix;
/* Open admin queues */
@ -1767,7 +1770,7 @@ static int intelxl_probe ( struct pci_device *pci ) {
err_admin_clear_pxe:
intelxl_close_admin ( intelxl );
err_open_admin:
intelxl_msix_disable ( intelxl, pci );
intelxl_msix_disable ( intelxl, pci, INTELXL_MSIX_VECTOR );
err_msix:
err_fetch_mac:
pci_reset ( pci, intelxl->exp );
@ -1796,7 +1799,7 @@ static void intelxl_remove ( struct pci_device *pci ) {
intelxl_close_admin ( intelxl );
/* Disable MSI-X dummy interrupt */
intelxl_msix_disable ( intelxl, pci );
intelxl_msix_disable ( intelxl, pci, INTELXL_MSIX_VECTOR );
/* Reset the NIC */
pci_reset ( pci, intelxl->exp );

View File

@ -1035,7 +1035,10 @@ struct intelxl_msix {
struct dma_mapping map;
};
/** An Intel 40Gigabit network card */
/** MSI-X interrupt vector */
#define INTELXL_MSIX_VECTOR 0
/** An Intel 40 Gigabit network card */
struct intelxl_nic {
/** Registers */
void *regs;
@ -1084,9 +1087,11 @@ struct intelxl_nic {
};
extern int intelxl_msix_enable ( struct intelxl_nic *intelxl,
struct pci_device *pci );
struct pci_device *pci,
unsigned int vector );
extern void intelxl_msix_disable ( struct intelxl_nic *intelxl,
struct pci_device *pci );
struct pci_device *pci,
unsigned int vector );
extern struct intelxl_admin_descriptor *
intelxl_admin_command_descriptor ( struct intelxl_nic *intelxl );
extern union intelxl_admin_buffer *

View File

@ -399,6 +399,7 @@ static int intelxlvf_admin_irq_map ( struct net_device *netdev ) {
buf = intelxl_admin_command_buffer ( intelxl );
buf->irq.count = cpu_to_le16 ( 1 );
buf->irq.vsi = cpu_to_le16 ( intelxl->vsi );
buf->irq.vec = cpu_to_le16 ( INTELXLVF_MSIX_VECTOR );
buf->irq.rxmap = cpu_to_le16 ( 0x0001 );
buf->irq.txmap = cpu_to_le16 ( 0x0001 );
@ -583,7 +584,7 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
pci_set_drvdata ( pci, netdev );
netdev->dev = &pci->dev;
memset ( intelxl, 0, sizeof ( *intelxl ) );
intelxl->intr = INTELXLVF_VFINT_DYN_CTL0;
intelxl->intr = INTELXLVF_VFINT_DYN_CTLN ( INTELXLVF_MSIX_VECTOR );
intelxl_init_admin ( &intelxl->command, INTELXLVF_ADMIN,
&intelxlvf_admin_command_offsets );
intelxl_init_admin ( &intelxl->event, INTELXLVF_ADMIN,
@ -623,7 +624,8 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
pci_reset ( pci, intelxl->exp );
/* Enable MSI-X dummy interrupt */
if ( ( rc = intelxl_msix_enable ( intelxl, pci ) ) != 0 )
if ( ( rc = intelxl_msix_enable ( intelxl, pci,
INTELXLVF_MSIX_VECTOR ) ) != 0 )
goto err_msix;
/* Open admin queues */
@ -650,7 +652,7 @@ static int intelxlvf_probe ( struct pci_device *pci ) {
err_reset_admin:
intelxl_close_admin ( intelxl );
err_open_admin:
intelxl_msix_disable ( intelxl, pci );
intelxl_msix_disable ( intelxl, pci, INTELXLVF_MSIX_VECTOR );
err_msix:
pci_reset ( pci, intelxl->exp );
err_exp:
@ -681,7 +683,7 @@ static void intelxlvf_remove ( struct pci_device *pci ) {
intelxl_close_admin ( intelxl );
/* Disable MSI-X dummy interrupt */
intelxl_msix_disable ( intelxl, pci );
intelxl_msix_disable ( intelxl, pci, INTELXLVF_MSIX_VECTOR );
/* Reset the function via PCIe FLR */
pci_reset ( pci, intelxl->exp );

View File

@ -14,12 +14,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** BAR size */
#define INTELXLVF_BAR_SIZE 0x10000
/** MSI-X vector
*
* The 100 Gigabit physical function driver requires a virtual
* function driver to request that transmit and receive queues are
* mapped to MSI-X vector 1 or higher.
*/
#define INTELXLVF_MSIX_VECTOR 1
/** Transmit Queue Tail Register */
#define INTELXLVF_QTX_TAIL 0x00000
/** Receive Queue Tail Register */
#define INTELXLVF_QRX_TAIL 0x02000
/** VF Interrupt N Dynamic Control Register */
#define INTELXLVF_VFINT_DYN_CTLN( x ) ( 0x3800 + ( 0x4 * ( (x) - 1 ) ) )
/** VF Interrupt Zero Dynamic Control Register */
#define INTELXLVF_VFINT_DYN_CTL0 0x5c00