tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: change MSI/MSI-X APIs
Hi,
On 2015/05/13 21:42, Christos Zoulas wrote:
> It was not obvious to me that pci_intr_release() free's all the handles.
> The API certainly does not feel symmetric. Calling something with 'alloc'
> int the name usually expects something to call 'free' later.
I design the APIs to be similar to FreeBSD's API. The FreeBSD's APIs
are below:
https://www.freebsd.org/cgi/man.cgi?query=pci&sektion=9
that is
+ allocate APIs are
- int pci_alloc_msi(device_t dev, int *count); => for MSI
- int pci_alloc_msix(device_t dev, int *count); => for MSI-X
+ release(free) API is
- int pci_release_msi(device_t dev); => for both MSI and MSI-X
> Still, there is room for sharing the code no matter what's the count
> of allocated interrupts per group. Again, the way I see it is that
> you want a function that allocates a vector of interrupts the best
> way it can (in general) and have a way to specify quirks for cards
> that need to do something special. How you split the interrupts in
> the driver between functions depends on the driver, but the driver
> does not really care in general what flavor the interrupts are (but
> it might want to ask if it needs to differentiate). Having 150+ lines
> of semi-duplicated code to do interrupt setup does not make a lot
> of sense to me.
Well...yes, but some device drivers need the allocating APIs, such as
"if_vioif". "if_vioif" setup below process:
(1) allocate "virtqueue"s wanted interrupt numbers in if_vioif.c
(2) allocate interrupts the same number of "virtqueue"s in virtio.c
(3) bind each allocated interrupts to "virtqueue"s in virtio.c
So, it require the API which allocate particular MSI-X count.
However, as you indicated, that pci_msix_alloc(), pci_msi_alloc(),
and pci_intx_alloc() fallback code is certainly redundant...
So, I will design new wrapper function which call each allocating APIs,
in addition to existing each allocating APIs.
Currntly very rough design is below:
====================
typedef int pci_intr_type_t;
#define PCI_INTR_TYPE_INTX __BIT(0)
#define PCI_INTR_TYPE_MSI __BIT(1)
#define PCI_INTR_TYPE_MSIX __BIT(2)
#define PCI_INTR_TYPE_ANY (PCI_INTR_TYPE_INTX | PCI_INTR_TYPE_MSI | PCI_INTR_TYPE_MSIX)
int
pci_intr_alloc(const struct pci_attach_args *, pci_intr_handle_t **ihps,
int *counts, pci_intr_type_t which);
pci_intr_type_t
pci_intr_type(pci_intr_handle_t *ihp);
====================
The device driver usage pseudo code is below:
====================
xxxx_attach()
{
int want_msix_count, want_msi_count;
int intr_counts[2]; // MSI and MSI-X.
// The interrupt number of INTx is alway 1.
// calculate wanted msix count and msi count.
intr_counts[0] = want_msi_count;
intr_counts[1] = want_msix_count;
// This driver want to use MSI-X, MSI, or INTx.
// If the driver want to MSI or INTx "which" argument should be
// "PCI_INTR_TYPE_INTX | PCI_INTR_TYPE_MSI".
err = pci_intr_alloc(*pa, &sc->sc_intrs, intr_counts, PCI_INTR_TYPE_ANY);
if (err)
// cannot allocate any interrupt type, so error handling and exit.
if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSIX)
nintrs = intr_counts[1];
else if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSI)
nintrs = intr_count[0];
else if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_INTX)
nintrs = 1;
else
panic("unknown pci_intr_type");
for (i = 0; i < nintrs; i++)
sc->sc_ihs[i] = pci_intr_establish(pc, sc->sc_intrs[i], level, func, arg);
// snip
}
====================
I believe above APIs satisfy the needs of a lot of device drivers.
# Again, there is some drivers which need pci_{intx,msi,msix}_alloc(),
# therefore other some drivers need pci_msix_alloc_map().
Could you comment about both whether above APIs match your suggestions
and any other pointing?
Thanks,
--
//////////////////////////////////////////////////////////////////////
Internet Initiative Japan Inc.
Device Engineering Section,
Core Product Development Department,
Product Division,
Technology Unit
Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>
Home |
Main Index |
Thread Index |
Old Index