make MSI-X the default and allocate up to mp_ncpus queues per port

MFC after: 3 days
This commit is contained in:
Kip Macy 2007-03-21 07:25:40 +00:00
parent 02023242ea
commit 693d746cc1
4 changed files with 86 additions and 59 deletions

View File

@ -226,6 +226,7 @@ struct sge_qset {
unsigned long txq_stopped; /* which Tx queues are stopped */
uint64_t port_stats[SGE_PSTAT_MAX];
struct port_info *port;
int idx; /* qset # */
};
struct sge {
@ -410,7 +411,7 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
/*
* XXX figure out how we can return this to being private to sge
*/
#define desc_reclaimable(q) ((q)->processed - (q)->cleaned - TX_MAX_DESC)
#define desc_reclaimable(q) ((int)((q)->processed - (q)->cleaned - TX_MAX_DESC))
#define container_of(p, stype, field) ((stype *)(((uint8_t *)(p)) - offsetof(stype, field)))

View File

@ -176,7 +176,7 @@ DRIVER_MODULE(cxgb, cxgbc, cxgb_port_driver, cxgb_port_devclass, 0, 0);
* msi = 1 : only consider MSI and pin interrupts
* msi = 0: force pin interrupts
*/
static int msi_allowed = 0;
static int msi_allowed = 2;
TUNABLE_INT("hw.cxgb.msi_allowed", &msi_allowed);
SYSCTL_NODE(_hw, OID_AUTO, cxgb, CTLFLAG_RD, 0, "CXGB driver parameters");
@ -303,9 +303,10 @@ cxgb_controller_attach(device_t dev)
device_t child;
const struct adapter_info *ai;
struct adapter *sc;
int i, msi_count = 0, error = 0;
int i, msi_needed, msi_count = 0, error = 0;
uint32_t vers;
int port_qsets = 1;
sc = device_get_softc(dev);
sc->dev = dev;
@ -336,14 +337,18 @@ cxgb_controller_attach(device_t dev)
* interrupt pin model.
*/
#ifdef MSI_SUPPORTED
sc->msix_regs_rid = 0x20;
if ((msi_allowed >= 2) &&
(sc->msix_regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->msix_regs_rid, RF_ACTIVE)) != NULL) {
msi_count = SGE_MSIX_COUNT;
msi_needed = msi_count = 5;
if ((pci_alloc_msix(dev, &msi_count) != 0) ||
(msi_count != SGE_MSIX_COUNT)) {
(msi_count != msi_needed)) {
device_printf(dev, "msix allocation failed"
" will try msi\n");
msi_count = 0;
pci_release_msi(dev);
bus_release_resource(dev, SYS_RES_MEMORY,
@ -353,14 +358,12 @@ cxgb_controller_attach(device_t dev)
sc->flags |= USING_MSIX;
cxgb_intr = t3_intr_msix;
}
printf("allocated %d msix intrs\n", msi_count);
}
if ((msi_allowed >= 1) && (msi_count == 0)) {
msi_count = 1;
if (pci_alloc_msi(dev, &msi_count)) {
device_printf(dev, "alloc msi failed\n");
device_printf(dev, "alloc msi failed - will try INTx\n");
msi_count = 0;
pci_release_msi(dev);
} else {
@ -371,6 +374,7 @@ cxgb_controller_attach(device_t dev)
}
#endif
if (msi_count == 0) {
device_printf(dev, "using line interrupts\n");
sc->irq_rid = 0;
cxgb_intr = t3b_intr;
}
@ -420,11 +424,14 @@ cxgb_controller_attach(device_t dev)
}
t3_write_reg(sc, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
if (sc->flags & USING_MSIX)
port_qsets = min((SGE_QSETS/(sc)->params.nports), mp_ncpus);
/*
* Create a child device for each MAC. The ethernet attachment
* will be done in these children.
*/
for (i = 0; i < (sc)->params.nports; ++i) {
*/
for (i = 0; i < (sc)->params.nports; i++) {
if ((child = device_add_child(dev, "cxgb", -1)) == NULL) {
device_printf(dev, "failed to add child port\n");
error = EINVAL;
@ -432,12 +439,8 @@ cxgb_controller_attach(device_t dev)
}
sc->portdev[i] = child;
sc->port[i].adapter = sc;
#ifdef MULTIQ
sc->port[i].nqsets = mp_ncpus;
#else
sc->port[i].nqsets = 1;
#endif
sc->port[i].first_qset = i;
sc->port[i].nqsets = port_qsets;
sc->port[i].first_qset = i*port_qsets;
sc->port[i].port = i;
device_set_softc(child, &sc->port[i]);
}
@ -512,20 +515,20 @@ cxgb_free(struct adapter *sc)
{
int i;
for (i = 0; i < (sc)->params.nports; ++i) {
if (sc->portdev[i] != NULL)
device_delete_child(sc->dev, sc->portdev[i]);
}
callout_drain(&sc->cxgb_tick_ch);
t3_sge_deinit_sw(sc);
if (sc->tq != NULL) {
taskqueue_drain(sc->tq, &sc->ext_intr_task);
taskqueue_free(sc->tq);
}
callout_drain(&sc->cxgb_tick_ch);
for (i = 0; i < (sc)->params.nports; ++i) {
if (sc->portdev[i] != NULL)
device_delete_child(sc->dev, sc->portdev[i]);
}
bus_generic_detach(sc->dev);
t3_free_sge_resources(sc);
@ -589,7 +592,7 @@ setup_sge_qsets(adapter_t *sc)
u_int ntxq = 3;
if ((err = t3_sge_alloc(sc)) != 0) {
printf("t3_sge_alloc returned %d\n", err);
device_printf(sc->dev, "t3_sge_alloc returned %d\n", err);
return (err);
}
@ -602,12 +605,12 @@ setup_sge_qsets(adapter_t *sc)
struct port_info *pi = &sc->port[i];
for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
err = t3_sge_alloc_qset(sc, qset_idx, 1,
err = t3_sge_alloc_qset(sc, qset_idx, (sc)->params.nports,
(sc->flags & USING_MSIX) ? qset_idx + 1 : irq_idx,
&sc->params.sge.qset[qset_idx], ntxq, pi);
if (err) {
t3_free_sge_resources(sc);
printf("t3_sge_alloc_qset failed with %d\n", err);
device_printf(sc->dev, "t3_sge_alloc_qset failed with %d\n", err);
return (err);
}
}
@ -628,6 +631,7 @@ cxgb_setup_msix(adapter_t *sc, int msix_count)
device_printf(sc->dev, "Cannot allocate msix interrupt\n");
return (EINVAL);
}
if (bus_setup_intr(sc->dev, sc->irq_res, INTR_MPSAFE|INTR_TYPE_NET,
#ifdef INTR_FILTERS
NULL,
@ -636,7 +640,6 @@ cxgb_setup_msix(adapter_t *sc, int msix_count)
device_printf(sc->dev, "Cannot set up interrupt\n");
return (EINVAL);
}
for (i = 0, k = 0; i < (sc)->params.nports; ++i) {
nqsets = sc->port[i].nqsets;
for (j = 0; j < nqsets; ++j, k++) {
@ -665,6 +668,8 @@ cxgb_setup_msix(adapter_t *sc, int msix_count)
}
}
}
return (0);
}
@ -1109,9 +1114,11 @@ cxgb_init_locked(struct port_info *p)
ADAPTER_UNLOCK(p->adapter);
t3_intr_enable(sc);
t3_port_intr_enable(sc, p->port);
if ((p->adapter->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
bind_qsets(sc);
p->adapter->flags |= QUEUES_BOUND;
callout_reset(&sc->cxgb_tick_ch, sc->params.stats_update_period * hz,
cxgb_tick, sc);
@ -1125,6 +1132,8 @@ cxgb_set_rxmode(struct port_info *p)
{
struct t3_rx_mode rm;
struct cmac *mac = &p->mac;
mtx_assert(&p->lock, MA_OWNED);
t3_init_rx_mode(&rm, p);
t3_mac_set_rx_mode(mac, &rm);
@ -1138,7 +1147,6 @@ cxgb_stop_locked(struct port_info *p)
mtx_assert(&p->lock, MA_OWNED);
mtx_assert(&p->adapter->lock, MA_NOTOWNED);
callout_stop(&p->adapter->cxgb_tick_ch);
ifp = p->ifp;
ADAPTER_LOCK(p->adapter);
@ -1185,8 +1193,9 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFFLAGS:
PORT_LOCK(p);
if (ifp->if_flags & IFF_UP) {
PORT_LOCK(p);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
flags = p->if_flags;
if (((ifp->if_flags ^ flags) & IFF_PROMISC) ||
@ -1195,13 +1204,23 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
} else
cxgb_init_locked(p);
p->if_flags = ifp->if_flags;
PORT_UNLOCK(p);
} else {
callout_drain(&p->adapter->cxgb_tick_ch);
PORT_LOCK(p);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
cxgb_stop_locked(p);
} else {
adapter_t *sc = p->adapter;
callout_reset(&sc->cxgb_tick_ch,
sc->params.stats_update_period * hz,
cxgb_tick, sc);
}
PORT_UNLOCK(p);
}
p->if_flags = ifp->if_flags;
PORT_UNLOCK(p);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@ -1370,8 +1389,13 @@ cxgb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
static void
cxgb_async_intr(void *data)
{
adapter_t *sc = data;
if (cxgb_debug)
printf("cxgb_async_intr\n");
device_printf(sc->dev, "cxgb_async_intr\n");
t3_slow_intr_handler(sc);
}
static void

View File

@ -82,6 +82,7 @@ struct t3_mbuf_hdr {
#define CXGB_TX_CLEANUP_THRESHOLD 32
#define LOG_WARNING 1
#ifdef DEBUG_PRINT
#define DPRINTF printf

View File

@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/systm.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@ -456,7 +457,7 @@ refill_fl(adapter_t *sc, struct sge_fl *q, int n)
m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, q->buf_size);
if (m == NULL) {
printf("Failed to allocate mbuf\n");
log(LOG_WARNING, "Failed to allocate mbuf\n");
goto done;
}
@ -470,7 +471,7 @@ refill_fl(adapter_t *sc, struct sge_fl *q, int n)
err = bus_dmamap_load_mbuf_sg(sc->rx_jumbo_dmat, sd->map, m, &seg,
&nsegs, BUS_DMA_NOWAIT);
if (err != 0) {
printf("failure in refill_fl %d\n", err);
log(LOG_WARNING, "failure in refill_fl %d\n", err);
m_freem(m);
return;
}
@ -581,12 +582,10 @@ static void
sge_slow_intr_handler(void *arg, int ncount)
{
adapter_t *sc = arg;
t3_slow_intr_handler(sc);
}
static void
sge_timer_cb(void *arg)
{
@ -660,24 +659,24 @@ static void
sge_timer_reclaim(void *arg, int ncount)
{
adapter_t *sc = arg;
int i, j, nqsets = 0;
int i, nqsets = 0;
struct sge_qset *qs;
struct sge_txq *txq;
struct mtx *lock;
struct mbuf *m_vec[TX_CLEAN_MAX_DESC];
int n;
int n, reclaimable;
/*
* XXX assuming these quantities are allowed to change during operation
*/
for (i = 0; i < sc->params.nports; i++) {
for (j = 0; j < sc->port[i].nqsets; j++)
nqsets++;
}
for (i = 0; i < sc->params.nports; i++)
nqsets += sc->port[i].nqsets;
for (i = 0; i < nqsets; i++) {
qs = &sc->sge.qs[i];
txq = &qs->txq[TXQ_ETH];
if (desc_reclaimable(txq) > 0) {
mtx_lock(&txq->lock);
reclaimable = desc_reclaimable(txq);
if (reclaimable > 0) {
mtx_lock(&txq->lock);
n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec);
mtx_unlock(&txq->lock);
@ -687,7 +686,8 @@ sge_timer_reclaim(void *arg, int ncount)
}
txq = &qs->txq[TXQ_OFLD];
if (desc_reclaimable(txq) > 0) {
reclaimable = desc_reclaimable(txq);
if (reclaimable > 0) {
mtx_lock(&txq->lock);
n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec);
mtx_unlock(&txq->lock);
@ -697,17 +697,16 @@ sge_timer_reclaim(void *arg, int ncount)
}
}
lock = (sc->flags & USING_MSIX) ? &qs->rspq.lock :
&sc->sge.qs[0].rspq.lock;
if (mtx_trylock(lock)) {
/* XXX currently assume that we are *NOT* polling */
uint32_t status = t3_read_reg(sc, A_SG_RSPQ_FL_STATUS);
if (qs->fl[0].credits < qs->fl[0].size)
if (qs->fl[0].credits < qs->fl[0].size - 16)
__refill_fl(sc, &qs->fl[0]);
if (qs->fl[1].credits < qs->fl[1].size)
if (qs->fl[1].credits < qs->fl[1].size - 16)
__refill_fl(sc, &qs->fl[1]);
if (status & (1 << qs->rspq.cntxt_id)) {
@ -1850,11 +1849,12 @@ check_ring_db(adapter_t *adap, struct sge_qset *qs,
* to work around lack of ithread affinity
*/
static void
bind_ithread(void)
bind_ithread(int cpu)
{
KASSERT(cpu < mp_ncpus, ("invalid cpu identifier"));
if (mp_ncpus > 1) {
mtx_lock_spin(&sched_lock);
sched_bind(curthread, 1);
sched_bind(curthread, cpu);
mtx_unlock_spin(&sched_lock);
}
@ -1884,7 +1884,7 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
unsigned int sleeping = 0;
int lro = qs->lro.enabled;
static int pinned = 0;
static uint8_t pinned[MAXCPU];
#ifdef DEBUG
static int last_holdoff = 0;
@ -1893,9 +1893,12 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
last_holdoff = rspq->holdoff_tmr;
}
#endif
if (pinned == 0) {
bind_ithread();
pinned = 1;
if (pinned[qs->rspq.cntxt_id * adap->params.nports] == 0) {
/*
* Assumes that cntxt_id < mp_ncpus
*/
bind_ithread(qs->rspq.cntxt_id);
pinned[qs->rspq.cntxt_id * adap->params.nports] = 1;
}
rspq->next_holdoff = rspq->holdoff_tmr;
@ -2088,8 +2091,6 @@ t3_intr_msix(void *data)
adapter_t *adap = qs->port->adapter;
struct sge_rspq *rspq = &qs->rspq;
if (cxgb_debug)
printf("got msi-x interrupt\n");
mtx_lock(&rspq->lock);
if (process_responses_gts(adap, rspq) == 0) {
#ifdef notyet