Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/if_ixlv.c
Show First 20 Lines • Show All 467 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct ixlv_sc *sc = device_get_softc(dev); | struct ixlv_sc *sc = device_get_softc(dev); | ||||
struct ixl_vsi *vsi = &sc->vsi; | struct ixl_vsi *vsi = &sc->vsi; | ||||
INIT_DBG_DEV(dev, "begin"); | INIT_DBG_DEV(dev, "begin"); | ||||
/* Make sure VLANS are not using driver */ | /* Make sure VLANS are not using driver */ | ||||
if (vsi->ifp->if_vlantrunk != NULL) { | if (vsi->ifp->if_vlantrunk != NULL) { | ||||
device_printf(dev, "Vlan in use, detach first\n"); | if_printf(vsi->ifp, "Vlan in use, detach first\n"); | ||||
INIT_DBG_DEV(dev, "end"); | INIT_DBG_DEV(dev, "end"); | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
/* Stop driver */ | /* Stop driver */ | ||||
ether_ifdetach(vsi->ifp); | ether_ifdetach(vsi->ifp); | ||||
if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) { | if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) { | ||||
mtx_lock(&sc->mtx); | mtx_lock(&sc->mtx); | ||||
▲ Show 20 Lines • Show All 396 Lines • ▼ Show 20 Lines | ixlv_init_locked(struct ixlv_sc *sc) | ||||
ixlv_setup_vlan_filters(sc); | ixlv_setup_vlan_filters(sc); | ||||
/* Prepare the queues for operation */ | /* Prepare the queues for operation */ | ||||
for (int i = 0; i < vsi->num_queues; i++, que++) { | for (int i = 0; i < vsi->num_queues; i++, que++) { | ||||
struct rx_ring *rxr = &que->rxr; | struct rx_ring *rxr = &que->rxr; | ||||
ixl_init_tx_ring(que); | ixl_init_tx_ring(que); | ||||
if (vsi->max_frame_size <= 2048) | if (vsi->max_frame_size <= MCLBYTES) | ||||
rxr->mbuf_sz = MCLBYTES; | rxr->mbuf_sz = MCLBYTES; | ||||
else | else | ||||
rxr->mbuf_sz = MJUMPAGESIZE; | rxr->mbuf_sz = MJUMPAGESIZE; | ||||
ixl_init_rx_ring(que); | ixl_init_rx_ring(que); | ||||
} | } | ||||
/* Configure queues */ | /* Configure queues */ | ||||
ixl_vc_enqueue(&sc->vc_mgr, &sc->config_queues_cmd, | ixl_vc_enqueue(&sc->vc_mgr, &sc->config_queues_cmd, | ||||
▲ Show 20 Lines • Show All 500 Lines • ▼ Show 20 Lines | for (int i = 0; i < vsi->num_queues; i++, vector++, que++) { | ||||
} | } | ||||
bus_describe_intr(dev, que->res, que->tag, "que %d", i); | bus_describe_intr(dev, que->res, que->tag, "que %d", i); | ||||
/* Bind the vector to a CPU */ | /* Bind the vector to a CPU */ | ||||
#ifdef RSS | #ifdef RSS | ||||
cpu_id = rss_getcpu(i % rss_getnumbuckets()); | cpu_id = rss_getcpu(i % rss_getnumbuckets()); | ||||
#endif | #endif | ||||
bus_bind_intr(dev, que->res, cpu_id); | bus_bind_intr(dev, que->res, cpu_id); | ||||
que->msix = vector; | que->msix = vector; | ||||
vsi->que_mask |= (u64)(1 << que->msix); | vsi->que_mask |= (u64)(1 << que->msix); | ||||
TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); | TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); | ||||
TASK_INIT(&que->task, 0, ixlv_handle_que, que); | TASK_INIT(&que->task, 0, ixlv_handle_que, que); | ||||
que->tq = taskqueue_create_fast("ixlv_que", M_NOWAIT, | que->tq = taskqueue_create_fast("ixlv_que", M_NOWAIT, | ||||
taskqueue_thread_enqueue, &que->tq); | taskqueue_thread_enqueue, &que->tq); | ||||
#ifdef RSS | #ifdef RSS | ||||
taskqueue_start_threads_pinned(&que->tq, 1, PI_NET, | taskqueue_start_threads_pinned(&que->tq, 1, PI_NET, | ||||
cpu_id, "%s (bucket %d)", | cpu_id, "%s (bucket %d)", | ||||
device_get_nameunit(dev), cpu_id); | device_get_nameunit(dev), cpu_id); | ||||
▲ Show 20 Lines • Show All 287 Lines • ▼ Show 20 Lines | |||||
** it enables us to use the HW Filter table since | ** it enables us to use the HW Filter table since | ||||
** we can get the vlan id. This just creates the | ** we can get the vlan id. This just creates the | ||||
** entry in the soft version of the VFTA, init will | ** entry in the soft version of the VFTA, init will | ||||
** repopulate the real table. | ** repopulate the real table. | ||||
*/ | */ | ||||
static void | static void | ||||
ixlv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) | ixlv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) | ||||
{ | { | ||||
struct ixl_vsi *vsi = ifp->if_softc; | struct ixl_vsi *vsi = arg; | ||||
struct ixlv_sc *sc = vsi->back; | struct ixlv_sc *sc = vsi->back; | ||||
struct ixlv_vlan_filter *v; | struct ixlv_vlan_filter *v; | ||||
if (ifp->if_softc != arg) /* Not our event */ | if (ifp->if_softc != arg) /* Not our event */ | ||||
return; | return; | ||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */ | if ((vtag == 0) || (vtag > 4095)) /* Invalid */ | ||||
return; | return; | ||||
/* Sanity check - make sure it doesn't already exist */ | /* Sanity check - make sure it doesn't already exist */ | ||||
SLIST_FOREACH(v, sc->vlan_filters, next) { | SLIST_FOREACH(v, sc->vlan_filters, next) { | ||||
if (v->vlan == vtag) | if (v->vlan == vtag) | ||||
Show All 15 Lines | |||||
/* | /* | ||||
** This routine is run via an vlan | ** This routine is run via an vlan | ||||
** unconfig EVENT, remove our entry | ** unconfig EVENT, remove our entry | ||||
** in the soft vfta. | ** in the soft vfta. | ||||
*/ | */ | ||||
static void | static void | ||||
ixlv_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) | ixlv_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) | ||||
{ | { | ||||
struct ixl_vsi *vsi = ifp->if_softc; | struct ixl_vsi *vsi = arg; | ||||
struct ixlv_sc *sc = vsi->back; | struct ixlv_sc *sc = vsi->back; | ||||
struct ixlv_vlan_filter *v; | struct ixlv_vlan_filter *v; | ||||
int i = 0; | int i = 0; | ||||
if (ifp->if_softc != arg) | if (ifp->if_softc != arg) | ||||
return; | return; | ||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */ | if ((vtag == 0) || (vtag > 4095)) /* Invalid */ | ||||
return; | return; | ||||
mtx_lock(&sc->mtx); | mtx_lock(&sc->mtx); | ||||
SLIST_FOREACH(v, sc->vlan_filters, next) { | SLIST_FOREACH(v, sc->vlan_filters, next) { | ||||
if (v->vlan == vtag) { | if (v->vlan == vtag) { | ||||
▲ Show 20 Lines • Show All 656 Lines • ▼ Show 20 Lines | for (int i = 0; i < vsi->num_queues; i++,que++) { | ||||
if (que->busy == IXL_QUEUE_HUNG) { | if (que->busy == IXL_QUEUE_HUNG) { | ||||
++hung; | ++hung; | ||||
/* Mark the queue as inactive */ | /* Mark the queue as inactive */ | ||||
vsi->active_queues &= ~((u64)1 << que->me); | vsi->active_queues &= ~((u64)1 << que->me); | ||||
continue; | continue; | ||||
} else { | } else { | ||||
/* Check if we've come back from hung */ | /* Check if we've come back from hung */ | ||||
if ((vsi->active_queues & ((u64)1 << que->me)) == 0) | if ((vsi->active_queues & ((u64)1 << que->me)) == 0) | ||||
vsi->active_queues |= ((u64)1 << que->me); | vsi->active_queues |= ((u64)1 << que->me); | ||||
} | } | ||||
if (que->busy >= IXL_MAX_TX_BUSY) { | if (que->busy >= IXL_MAX_TX_BUSY) { | ||||
device_printf(dev,"Warning queue %d " | device_printf(dev,"Warning queue %d " | ||||
"appears to be hung!\n", i); | "appears to be hung!\n", i); | ||||
que->busy = IXL_QUEUE_HUNG; | que->busy = IXL_QUEUE_HUNG; | ||||
++hung; | ++hung; | ||||
} | } | ||||
} | } | ||||
Show All 14 Lines | |||||
** the real check of the hardware only happens with | ** the real check of the hardware only happens with | ||||
** a link interrupt. | ** a link interrupt. | ||||
*/ | */ | ||||
void | void | ||||
ixlv_update_link_status(struct ixlv_sc *sc) | ixlv_update_link_status(struct ixlv_sc *sc) | ||||
{ | { | ||||
struct ixl_vsi *vsi = &sc->vsi; | struct ixl_vsi *vsi = &sc->vsi; | ||||
struct ifnet *ifp = vsi->ifp; | struct ifnet *ifp = vsi->ifp; | ||||
device_t dev = sc->dev; | |||||
if (vsi->link_up){ | if (vsi->link_up) { | ||||
if (vsi->link_active == FALSE) { | if (vsi->link_active == FALSE) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev,"Link is Up, %d Gbps\n", | if_printf(ifp,"Link is Up, %d Gbps\n", | ||||
(vsi->link_speed == I40E_LINK_SPEED_40GB) ? 40:10); | (vsi->link_speed == I40E_LINK_SPEED_40GB) ? 40:10); | ||||
vsi->link_active = TRUE; | vsi->link_active = TRUE; | ||||
if_link_state_change(ifp, LINK_STATE_UP); | if_link_state_change(ifp, LINK_STATE_UP); | ||||
} | } | ||||
} else { /* Link down */ | } else { /* Link down */ | ||||
if (vsi->link_active == TRUE) { | if (vsi->link_active == TRUE) { | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(dev,"Link is Down\n"); | if_printf(ifp,"Link is Down\n"); | ||||
if_link_state_change(ifp, LINK_STATE_DOWN); | if_link_state_change(ifp, LINK_STATE_DOWN); | ||||
vsi->link_active = FALSE; | vsi->link_active = FALSE; | ||||
} | } | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | |||||
** This routine adds new MAC filters to the sc's list; | ** This routine adds new MAC filters to the sc's list; | ||||
** these are later added in hardware by sending a virtual | ** these are later added in hardware by sending a virtual | ||||
** channel message. | ** channel message. | ||||
*/ | */ | ||||
static int | static int | ||||
ixlv_add_mac_filter(struct ixlv_sc *sc, u8 *macaddr, u16 flags) | ixlv_add_mac_filter(struct ixlv_sc *sc, u8 *macaddr, u16 flags) | ||||
{ | { | ||||
struct ixlv_mac_filter *f; | struct ixlv_mac_filter *f; | ||||
device_t dev = sc->dev; | |||||
/* Does one already exist? */ | /* Does one already exist? */ | ||||
f = ixlv_find_mac_filter(sc, macaddr); | f = ixlv_find_mac_filter(sc, macaddr); | ||||
if (f != NULL) { | if (f != NULL) { | ||||
IDPRINTF(sc->vsi.ifp, "exists: " MAC_FORMAT, | IDPRINTF(sc->vsi.ifp, "exists: " MAC_FORMAT, | ||||
MAC_FORMAT_ARGS(macaddr)); | MAC_FORMAT_ARGS(macaddr)); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
/* If not, get a new empty filter */ | /* If not, get a new empty filter */ | ||||
f = ixlv_get_mac_filter(sc); | f = ixlv_get_mac_filter(sc); | ||||
if (f == NULL) { | if (f == NULL) { | ||||
device_printf(dev, "%s: no filters available!!\n", | if_printf(sc->vsi.ifp, "%s: no filters available!!\n", | ||||
__func__); | __func__); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
IDPRINTF(sc->vsi.ifp, "marked: " MAC_FORMAT, | IDPRINTF(sc->vsi.ifp, "marked: " MAC_FORMAT, | ||||
MAC_FORMAT_ARGS(macaddr)); | MAC_FORMAT_ARGS(macaddr)); | ||||
bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | struct ixl_sysctl_info ctls[] = | ||||
"Broadcast Packets Transmitted"}, | "Broadcast Packets Transmitted"}, | ||||
{&es->tx_errors, "tx_errors", "TX packet errors"}, | {&es->tx_errors, "tx_errors", "TX packet errors"}, | ||||
// end | // end | ||||
{0,0,0} | {0,0,0} | ||||
}; | }; | ||||
struct ixl_sysctl_info *entry = ctls; | struct ixl_sysctl_info *entry = ctls; | ||||
while (entry->stat != 0) | while (entry->stat != 0) | ||||
{ | { | ||||
SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, entry->name, | SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, entry->name, | ||||
CTLFLAG_RD, entry->stat, | CTLFLAG_RD, entry->stat, | ||||
entry->description); | entry->description); | ||||
entry++; | entry++; | ||||
} | } | ||||
/* Queue sysctls */ | /* Queue sysctls */ | ||||
for (int q = 0; q < vsi->num_queues; q++) { | for (int q = 0; q < vsi->num_queues; q++) { | ||||
snprintf(queue_namebuf, QUEUE_NAME_LEN, "que%d", q); | snprintf(queue_namebuf, QUEUE_NAME_LEN, "que%d", q); | ||||
queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf, | queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf, | ||||
CTLFLAG_RD, NULL, "Queue Name"); | CTLFLAG_RD, NULL, "Queue Name"); | ||||
queue_list = SYSCTL_CHILDREN(queue_node); | queue_list = SYSCTL_CHILDREN(queue_node); | ||||
txr = &(queues[q].txr); | txr = &(queues[q].txr); | ||||
rxr = &(queues[q].rxr); | rxr = &(queues[q].rxr); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed", | ||||
CTLFLAG_RD, &(queues[q].mbuf_defrag_failed), | CTLFLAG_RD, &(queues[q].mbuf_defrag_failed), | ||||
"m_defrag() failed"); | "m_defrag() failed"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "dropped", | ||||
CTLFLAG_RD, &(queues[q].dropped_pkts), | CTLFLAG_RD, &(queues[q].dropped_pkts), | ||||
"Driver dropped packets"); | "Driver dropped packets"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "irqs", | ||||
CTLFLAG_RD, &(queues[q].irqs), | CTLFLAG_RD, &(queues[q].irqs), | ||||
"irqs on this queue"); | "irqs on this queue"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tso_tx", | ||||
CTLFLAG_RD, &(queues[q].tso), | CTLFLAG_RD, &(queues[q].tso), | ||||
"TSO"); | "TSO"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_dma_setup", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_dma_setup", | ||||
CTLFLAG_RD, &(queues[q].tx_dma_setup), | CTLFLAG_RD, &(queues[q].tx_dma_setup), | ||||
"Driver tx dma failure in xmit"); | "Driver tx dma failure in xmit"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "no_desc_avail", | ||||
CTLFLAG_RD, &(txr->no_desc), | CTLFLAG_RD, &(txr->no_desc), | ||||
"Queue No Descriptor Available"); | "Queue No Descriptor Available"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_packets", | ||||
CTLFLAG_RD, &(txr->total_packets), | CTLFLAG_RD, &(txr->total_packets), | ||||
"Queue Packets Transmitted"); | "Queue Packets Transmitted"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "tx_bytes", | ||||
CTLFLAG_RD, &(txr->tx_bytes), | CTLFLAG_RD, &(txr->tx_bytes), | ||||
"Queue Bytes Transmitted"); | "Queue Bytes Transmitted"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_packets", | ||||
CTLFLAG_RD, &(rxr->rx_packets), | CTLFLAG_RD, &(rxr->rx_packets), | ||||
"Queue Packets Received"); | "Queue Packets Received"); | ||||
SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", | SYSCTL_ADD_QUAD(ctx, queue_list, OID_AUTO, "rx_bytes", | ||||
CTLFLAG_RD, &(rxr->rx_bytes), | CTLFLAG_RD, &(rxr->rx_bytes), | ||||
"Queue Bytes Received"); | "Queue Bytes Received"); | ||||
/* Examine queue state */ | /* Examine queue state */ | ||||
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "qtx_head", | SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "qtx_head", | ||||
CTLTYPE_UINT | CTLFLAG_RD, &queues[q], | CTLTYPE_UINT | CTLFLAG_RD, &queues[q], | ||||
sizeof(struct ixl_queue), | sizeof(struct ixl_queue), | ||||
ixlv_sysctl_qtx_tail_handler, "IU", | ixlv_sysctl_qtx_tail_handler, "IU", | ||||
▲ Show 20 Lines • Show All 84 Lines • Show Last 20 Lines |