eal/linux: fix irq handling with igb_uio

The introduction of uio_pci_generic broke interrupt handling with
igb_uio. The igb_uio device uses the kernel read/write method to
enable disable IRQ's; the uio_pci_generic has to use PCI intx
config read/write to enable disable interrupts.

Since igb_uio uses MSI-X the PCI intx config read/write won't
work.

Fixes: c112df6875a5 ("eal/linux: toggle interrupt for uio_pci_generic")

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
This commit is contained in:
Stephen Hemminger 2015-04-28 09:36:38 -07:00 committed by Thomas Monjalon
parent 55ae322d61
commit 3f313bef34
3 changed files with 50 additions and 8 deletions

View File

@ -361,7 +361,7 @@ vfio_disable_msix(struct rte_intr_handle *intr_handle) {
#endif
static int
uio_intr_disable(struct rte_intr_handle *intr_handle)
uio_intx_intr_disable(struct rte_intr_handle *intr_handle)
{
unsigned char command_high;
@ -385,7 +385,7 @@ uio_intr_disable(struct rte_intr_handle *intr_handle)
}
static int
uio_intr_enable(struct rte_intr_handle *intr_handle)
uio_intx_intr_enable(struct rte_intr_handle *intr_handle)
{
unsigned char command_high;
@ -408,6 +408,34 @@ uio_intr_enable(struct rte_intr_handle *intr_handle)
return 0;
}
static int
uio_intr_disable(struct rte_intr_handle *intr_handle)
{
const int value = 0;
if (write(intr_handle->fd, &value, sizeof(value)) < 0) {
RTE_LOG(ERR, EAL,
"Error disabling interrupts for fd %d (%s)\n",
intr_handle->fd, strerror(errno));
return -1;
}
return 0;
}
static int
uio_intr_enable(struct rte_intr_handle *intr_handle)
{
const int value = 1;
if (write(intr_handle->fd, &value, sizeof(value)) < 0) {
RTE_LOG(ERR, EAL,
"Error enabling interrupts for fd %d (%s)\n",
intr_handle->fd, strerror(errno));
return -1;
}
return 0;
}
int
rte_intr_callback_register(struct rte_intr_handle *intr_handle,
rte_intr_callback_fn cb, void *cb_arg)
@ -556,6 +584,10 @@ rte_intr_enable(struct rte_intr_handle *intr_handle)
if (uio_intr_enable(intr_handle))
return -1;
break;
case RTE_INTR_HANDLE_UIO_INTX:
if (uio_intx_intr_enable(intr_handle))
return -1;
break;
/* not used at this moment */
case RTE_INTR_HANDLE_ALARM:
return -1;
@ -596,6 +628,10 @@ rte_intr_disable(struct rte_intr_handle *intr_handle)
if (uio_intr_disable(intr_handle))
return -1;
break;
case RTE_INTR_HANDLE_UIO_INTX:
if (uio_intx_intr_disable(intr_handle))
return -1;
break;
/* not used at this moment */
case RTE_INTR_HANDLE_ALARM:
return -1;

View File

@ -299,7 +299,6 @@ pci_uio_map_resource(struct rte_pci_device *dev)
devname, strerror(errno));
return -1;
}
dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
snprintf(cfgname, sizeof(cfgname),
"/sys/class/uio/uio%u/device/config", uio_num);
@ -310,10 +309,16 @@ pci_uio_map_resource(struct rte_pci_device *dev)
return -1;
}
/* set bus master that is not done by uio_pci_generic */
if (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) {
RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n");
return -1;
if (dev->kdrv == RTE_KDRV_IGB_UIO)
dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
else {
dev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX;
/* set bus master that is not done by uio_pci_generic */
if (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) {
RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n");
return -1;
}
}
/* allocate the mapping details for secondary processes*/

View File

@ -40,7 +40,8 @@
enum rte_intr_handle_type {
RTE_INTR_HANDLE_UNKNOWN = 0,
RTE_INTR_HANDLE_UIO, /**< uio device handle */
RTE_INTR_HANDLE_UIO, /**< uio device handle */
RTE_INTR_HANDLE_UIO_INTX, /**< uio generic handle */
RTE_INTR_HANDLE_VFIO_LEGACY, /**< vfio device handle (legacy) */
RTE_INTR_HANDLE_VFIO_MSI, /**< vfio device handle (MSI) */
RTE_INTR_HANDLE_VFIO_MSIX, /**< vfio device handle (MSIX) */