sfxge_ev.c revision 49ef7e0638c8b771d8a136eae78b1c0f99acc8e0
/*
* Copyright (c) 2008-2016 Solarflare Communications Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include <sys/sysmacros.h>
#include "sfxge.h"
#include "efx.h"
/* Timeout to wait for DRIVER_EV_START event at EVQ startup */
#define SFXGE_EV_QSTART_TIMEOUT_USEC (2000000)
/* Event queue DMA attributes */
static ddi_device_acc_attr_t sfxge_evq_devacc = {
DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
};
static ddi_dma_attr_t sfxge_evq_dma_attr = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* dma_attr_addr_lo */
0xffffffffffffffffull, /* dma_attr_addr_hi */
0xffffffffffffffffull, /* dma_attr_count_max */
EFX_BUF_SIZE, /* dma_attr_align */
0xffffffff, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0xffffffffffffffffull, /* dma_attr_maxxfer */
0xffffffffffffffffull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static int
{
int rc;
/* Compile-time structure layout checks */
goto fail1;
/* Allocate some buffer table entries */
goto fail2;
return (0);
/* Tear down DMA setup */
return (-1);
}
static int
{
}
static int
{
}
static void
{
/* Free the buffer table entries */
/* Tear down DMA setup */
}
static void
{
}
static void
{
}
static boolean_t
sfxge_ev_initialized(void *arg)
{
/* Init done events may be duplicated on 7xxx (see SFCbug31631) */
goto done;
done:
return (B_FALSE);
}
static void
{
do {
}
}
}
static boolean_t
{
unsigned int prefetch;
unsigned int stop;
unsigned int delta;
if (sep->se_exception)
goto done;
goto done;
/*
* Note that in sfxge_stop() EVQ stopped after RXQ, and will be reset
* So the return missing srp->sr_pending increase is safe
*/
goto done;
if (delta != 1) {
(delta == 0) ||
/*
* FIXME: This does not take into account scatter
* aborts. See Bug40811
*/
/* sfxge_evq_t->se_lock held */
goto done;
}
}
}
done:
/* returning B_TRUE makes efx_ev_qpoll() stop processing events */
}
static boolean_t
{
if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
/* sfxge_evq_t->se_lock held */
"Unknown EV", code);
}
return (B_FALSE);
}
static boolean_t
{
unsigned int index;
unsigned int label;
/* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
goto done;
/* Process right now if it is the correct event queue */
goto done;
}
/* Resend a software event on the correct queue */
goto done; /* TBD: state test not under the lock */
done:
return (B_FALSE);
}
static boolean_t
{
unsigned int index;
unsigned int label;
/* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
goto done;
/* Process right now if it is the correct event queue */
goto done;
}
/* Resend a software event on the correct queue */
goto done; /* TBD: state test not under the lock */
done:
return (B_FALSE);
}
static boolean_t
{
unsigned int stop;
unsigned int delta;
goto done;
goto done;
}
done:
/* returning B_TRUE makes efx_ev_qpoll() stop processing events */
}
static boolean_t
{
unsigned int evq;
unsigned int label;
/* Ensure TXQ exists, as events may arrive after TXQ was destroyed */
goto done;
/* Process right now if it is the correct event queue */
goto done;
}
/* Resend a software event on the correct queue */
done:
return (B_FALSE);
}
static boolean_t
{
unsigned int label;
switch (magic) {
case SFXGE_MAGIC_RX_QFLUSH_DONE: {
}
break;
}
case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
}
break;
}
case SFXGE_MAGIC_RX_QFPP_TRIM: {
}
break;
}
case SFXGE_MAGIC_TX_QFLUSH_DONE: {
}
break;
}
default:
break;
}
return (B_FALSE);
}
static boolean_t
{
switch (code) {
case EFX_SRAM_UPDATE:
break;
case EFX_SRAM_CLEAR:
break;
case EFX_SRAM_ILLEGAL_CLEAR:
break;
default:
break;
}
return (B_FALSE);
}
static boolean_t
{
return (B_FALSE);
}
static boolean_t
{
return (B_FALSE);
}
static boolean_t
{
return (B_FALSE);
}
static int
{
int rc;
if (rw != KSTAT_READ) {
goto fail1;
}
goto done;
knp += EV_NQSTATS;
done:
return (0);
return (rc);
}
static int
{
char name[MAXNAMELEN];
unsigned int id;
int rc;
/* Determine the name */
/* Create the set */
goto fail1;
}
/* Initialise the named stats */
knp++;
}
return (0);
return (rc);
}
static void
{
/* Destroy the set */
}
inline unsigned pow2_ge(unsigned int n) {
unsigned int order = 0;
ASSERT3U(n, >, 0);
return (1ul << (order));
}
static int
{
int rc;
goto fail1;
}
/* Initialize the statistics */
goto fail2;
return (0);
return (rc);
}
static int
{
int rc;
/* Set the memory to all ones */
/* Program the buffer table */
EFX_EVQ_NBUFS(evq_size))) != 0)
goto fail1;
/* Set up the event callbacks */
/* Create the event queue */
goto fail2;
/* Set the default moderation */
goto fail3;
/* Check that interrupts are enabled at the NIC */
goto fail4;
}
/* Prime the event queue for interrupts */
goto fail5;
/* Wait for the initialization event */
timeout) < 0) {
/* Timeout waiting for initialization */
goto fail6;
}
}
return (0);
/* Destroy the event queue */
/* Zero out the event handlers */
/* Clear entries from the buffer table */
return (rc);
}
int
{
int rc;
goto fail1;
}
/* Make sure the CPU information is up to date */
/* sfxge_evq_t->se_lock held */
}
/* Synchronize the DMA memory for reading */
0,
/* Poll the queue */
sep);
/* Perform any pending completion processing */
/* Re-prime the event queue for interrupts */
goto fail2;
return (0);
return (rc);
}
int
{
int rc;
goto fail1;
}
goto fail2;
return (0);
return (rc);
}
int
{
}
static void
{
/* Clear the CPU information */
/* Clear the event count */
/* Reset the exception flag */
/* Destroy the event queue */
/* Zero out the event handlers */
/* Clear entries from the buffer table */
}
static void
{
/* Tear down the statistics */
}
int
unsigned int *labelp)
{
sfxge_txq_t **stpp;
unsigned int label;
int rc;
goto fail1;
}
goto fail2;
}
}
}
goto fail3;
}
return (0);
return (rc);
}
int
unsigned int label)
{
int rc;
goto fail1;
}
goto fail2;
}
return (0);
return (rc);
}
static kmem_cache_t *
{
char name[MAXNAMELEN];
return (eqc);
}
int
{
unsigned int evq0_size;
unsigned int evqX_size;
unsigned int ev_batch;
int index;
int rc;
/*
* Must account for RXQ, TXQ(s); MCDI not event completed at present
* Note that common code does not completely fill descriptor queues
*/
if (evq0_size > EFX_EVQ_MAXNEVS) {
goto fail1;
}
/* Read driver parameters */
/*
* It is slightly peverse to have a cache for one item. But it allows
* for simple alignment control without increasing the allocation size
*/
/* Initialize the event queue(s) */
goto fail2;
}
return (0);
while (--index >= 0)
sp->s_ev_moderation = 0;
return (rc);
}
int
{
int index;
int rc;
/* Initialize the event module */
goto fail1;
/* Start the event queues */
goto fail2;
}
return (0);
/* Stop the event queue(s) */
while (--index >= 0)
/* Tear down the event module */
return (rc);
}
void
{
}
int
{
int index;
int rc;
return (ENODEV);
goto fail1;
}
return (0);
/* The only error path is if the value to set to is invalid. */
return (rc);
}
void
{
int index;
/* Stop the event queue(s) */
while (--index >= 0)
/* Tear down the event module */
}
void
{
int index;
sp->s_ev_moderation = 0;
/* Tear down the event queue(s) */
while (--index >= 0)
}