Skip to content

Commit 495c22b

Browse files
Hariprasad Shenaidavem330
authored andcommitted
cxgb4vf: Configure queue based on resource and interrupt type
The Queue Set Configuration code was always reserving room for a Forwarded interrupt Queue even in the cases where we weren't using it. Figure out how many Ports and Queue Sets we can support. This depends on knowing our Virtual Function Resources and may be called a second time if we fall back from MSI-X to MSI Interrupt Mode. This change fixes that problem. Signed-off-by: Hariprasad Shenai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 84f6701 commit 495c22b

File tree

1 file changed

+94
-71
lines changed

1 file changed

+94
-71
lines changed

drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c

Lines changed: 94 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,17 +2176,82 @@ static void cleanup_debugfs(struct adapter *adapter)
21762176
/* nothing to do */
21772177
}
21782178

2179+
/* Figure out how many Ports and Queue Sets we can support. This depends on
2180+
* knowing our Virtual Function Resources and may be called a second time if
2181+
* we fall back from MSI-X to MSI Interrupt Mode.
2182+
*/
2183+
static void size_nports_qsets(struct adapter *adapter)
2184+
{
2185+
struct vf_resources *vfres = &adapter->params.vfres;
2186+
unsigned int ethqsets, pmask_nports;
2187+
2188+
/* The number of "ports" which we support is equal to the number of
2189+
* Virtual Interfaces with which we've been provisioned.
2190+
*/
2191+
adapter->params.nports = vfres->nvi;
2192+
if (adapter->params.nports > MAX_NPORTS) {
2193+
dev_warn(adapter->pdev_dev, "only using %d of %d maximum"
2194+
" allowed virtual interfaces\n", MAX_NPORTS,
2195+
adapter->params.nports);
2196+
adapter->params.nports = MAX_NPORTS;
2197+
}
2198+
2199+
/* We may have been provisioned with more VIs than the number of
2200+
* ports we're allowed to access (our Port Access Rights Mask).
2201+
* This is obviously a configuration conflict but we don't want to
2202+
* crash the kernel or anything silly just because of that.
2203+
*/
2204+
pmask_nports = hweight32(adapter->params.vfres.pmask);
2205+
if (pmask_nports < adapter->params.nports) {
2206+
dev_warn(adapter->pdev_dev, "only using %d of %d provissioned"
2207+
" virtual interfaces; limited by Port Access Rights"
2208+
" mask %#x\n", pmask_nports, adapter->params.nports,
2209+
adapter->params.vfres.pmask);
2210+
adapter->params.nports = pmask_nports;
2211+
}
2212+
2213+
/* We need to reserve an Ingress Queue for the Asynchronous Firmware
2214+
* Event Queue. And if we're using MSI Interrupts, we'll also need to
2215+
* reserve an Ingress Queue for a Forwarded Interrupts.
2216+
*
2217+
* The rest of the FL/Intr-capable ingress queues will be matched up
2218+
* one-for-one with Ethernet/Control egress queues in order to form
2219+
* "Queue Sets" which will be aportioned between the "ports". For
2220+
* each Queue Set, we'll need the ability to allocate two Egress
2221+
* Contexts -- one for the Ingress Queue Free List and one for the TX
2222+
* Ethernet Queue.
2223+
*
2224+
* Note that even if we're currently configured to use MSI-X
2225+
* Interrupts (module variable msi == MSI_MSIX) we may get downgraded
2226+
* to MSI Interrupts if we can't get enough MSI-X Interrupts. If that
2227+
* happens we'll need to adjust things later.
2228+
*/
2229+
ethqsets = vfres->niqflint - 1 - (msi == MSI_MSI);
2230+
if (vfres->nethctrl != ethqsets)
2231+
ethqsets = min(vfres->nethctrl, ethqsets);
2232+
if (vfres->neq < ethqsets*2)
2233+
ethqsets = vfres->neq/2;
2234+
if (ethqsets > MAX_ETH_QSETS)
2235+
ethqsets = MAX_ETH_QSETS;
2236+
adapter->sge.max_ethqsets = ethqsets;
2237+
2238+
if (adapter->sge.max_ethqsets < adapter->params.nports) {
2239+
dev_warn(adapter->pdev_dev, "only using %d of %d available"
2240+
" virtual interfaces (too few Queue Sets)\n",
2241+
adapter->sge.max_ethqsets, adapter->params.nports);
2242+
adapter->params.nports = adapter->sge.max_ethqsets;
2243+
}
2244+
}
2245+
21792246
/*
21802247
* Perform early "adapter" initialization. This is where we discover what
21812248
* adapter parameters we're going to be using and initialize basic adapter
21822249
* hardware support.
21832250
*/
21842251
static int adap_init0(struct adapter *adapter)
21852252
{
2186-
struct vf_resources *vfres = &adapter->params.vfres;
21872253
struct sge_params *sge_params = &adapter->params.sge;
21882254
struct sge *s = &adapter->sge;
2189-
unsigned int ethqsets;
21902255
int err;
21912256
u32 param, val = 0;
21922257

@@ -2295,69 +2360,18 @@ static int adap_init0(struct adapter *adapter)
22952360
return err;
22962361
}
22972362

2298-
/*
2299-
* The number of "ports" which we support is equal to the number of
2300-
* Virtual Interfaces with which we've been provisioned.
2301-
*/
2302-
adapter->params.nports = vfres->nvi;
2303-
if (adapter->params.nports > MAX_NPORTS) {
2304-
dev_warn(adapter->pdev_dev, "only using %d of %d allowed"
2305-
" virtual interfaces\n", MAX_NPORTS,
2306-
adapter->params.nports);
2307-
adapter->params.nports = MAX_NPORTS;
2308-
}
2309-
2310-
/*
2311-
* We need to reserve a number of the ingress queues with Free List
2312-
* and Interrupt capabilities for special interrupt purposes (like
2313-
* asynchronous firmware messages, or forwarded interrupts if we're
2314-
* using MSI). The rest of the FL/Intr-capable ingress queues will be
2315-
* matched up one-for-one with Ethernet/Control egress queues in order
2316-
* to form "Queue Sets" which will be aportioned between the "ports".
2317-
* For each Queue Set, we'll need the ability to allocate two Egress
2318-
* Contexts -- one for the Ingress Queue Free List and one for the TX
2319-
* Ethernet Queue.
2320-
*/
2321-
ethqsets = vfres->niqflint - INGQ_EXTRAS;
2322-
if (vfres->nethctrl != ethqsets) {
2323-
dev_warn(adapter->pdev_dev, "unequal number of [available]"
2324-
" ingress/egress queues (%d/%d); using minimum for"
2325-
" number of Queue Sets\n", ethqsets, vfres->nethctrl);
2326-
ethqsets = min(vfres->nethctrl, ethqsets);
2327-
}
2328-
if (vfres->neq < ethqsets*2) {
2329-
dev_warn(adapter->pdev_dev, "Not enough Egress Contexts (%d)"
2330-
" to support Queue Sets (%d); reducing allowed Queue"
2331-
" Sets\n", vfres->neq, ethqsets);
2332-
ethqsets = vfres->neq/2;
2333-
}
2334-
if (ethqsets > MAX_ETH_QSETS) {
2335-
dev_warn(adapter->pdev_dev, "only using %d of %d allowed Queue"
2336-
" Sets\n", MAX_ETH_QSETS, adapter->sge.max_ethqsets);
2337-
ethqsets = MAX_ETH_QSETS;
2338-
}
2339-
if (vfres->niq != 0 || vfres->neq > ethqsets*2) {
2340-
dev_warn(adapter->pdev_dev, "unused resources niq/neq (%d/%d)"
2341-
" ignored\n", vfres->niq, vfres->neq - ethqsets*2);
2342-
}
2343-
adapter->sge.max_ethqsets = ethqsets;
2344-
2345-
/*
2346-
* Check for various parameter sanity issues. Most checks simply
2347-
* result in us using fewer resources than our provissioning but we
2348-
* do need at least one "port" with which to work ...
2349-
*/
2350-
if (adapter->sge.max_ethqsets < adapter->params.nports) {
2351-
dev_warn(adapter->pdev_dev, "only using %d of %d available"
2352-
" virtual interfaces (too few Queue Sets)\n",
2353-
adapter->sge.max_ethqsets, adapter->params.nports);
2354-
adapter->params.nports = adapter->sge.max_ethqsets;
2355-
}
2356-
if (adapter->params.nports == 0) {
2363+
/* Check for various parameter sanity issues */
2364+
if (adapter->params.vfres.nvi == 0) {
23572365
dev_err(adapter->pdev_dev, "no virtual interfaces configured/"
23582366
"usable!\n");
23592367
return -EINVAL;
23602368
}
2369+
2370+
/* Initialize nports and max_ethqsets now that we have our Virtual
2371+
* Function Resources.
2372+
*/
2373+
size_nports_qsets(adapter);
2374+
23612375
return 0;
23622376
}
23632377

@@ -2779,16 +2793,32 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
27792793
if (msi == MSI_MSIX && enable_msix(adapter) == 0)
27802794
adapter->flags |= USING_MSIX;
27812795
else {
2796+
if (msi == MSI_MSIX) {
2797+
dev_info(adapter->pdev_dev,
2798+
"Unable to use MSI-X Interrupts; falling "
2799+
"back to MSI Interrupts\n");
2800+
2801+
/* We're going to need a Forwarded Interrupt Queue so
2802+
* that may cut into how many Queue Sets we can
2803+
* support.
2804+
*/
2805+
msi = MSI_MSI;
2806+
size_nports_qsets(adapter);
2807+
}
27822808
err = pci_enable_msi(pdev);
27832809
if (err) {
2784-
dev_err(&pdev->dev, "Unable to allocate %s interrupts;"
2785-
" err=%d\n",
2786-
msi == MSI_MSIX ? "MSI-X or MSI" : "MSI", err);
2810+
dev_err(&pdev->dev, "Unable to allocate MSI Interrupts;"
2811+
" err=%d\n", err);
27872812
goto err_free_dev;
27882813
}
27892814
adapter->flags |= USING_MSI;
27902815
}
27912816

2817+
/* Now that we know how many "ports" we have and what interrupt
2818+
* mechanism we're going to use, we can configure our queue resources.
2819+
*/
2820+
cfg_queues(adapter);
2821+
27922822
/*
27932823
* The "card" is now ready to go. If any errors occur during device
27942824
* registration we do not fail the whole "card" but rather proceed
@@ -2828,13 +2858,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev,
28282858
setup_debugfs(adapter);
28292859
}
28302860

2831-
/*
2832-
* Now that we know how many "ports" we have and what their types are,
2833-
* and how many Queue Sets we can support, we can configure our queue
2834-
* resources.
2835-
*/
2836-
cfg_queues(adapter);
2837-
28382861
/*
28392862
* Print a short notice on the existence and configuration of the new
28402863
* VF network device ...

0 commit comments

Comments
 (0)