/*
* 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/ethernet.h>
#include <sys/processor.h>
#include "sfxge.h"
#include "sfxge_version.h"
#include "efsys.h"
#include "efx.h"
#ifdef DEBUG
#endif
/* Receive queue TRIM default polling interval (in microseconds) */
/* Broadcast address */
/*
* By default modinfo will display lines truncated to 80 characters and so just
* show 32 characters of our sfxge_ident string.
*/
static void
{
"%02X:%02X:%02X:%02X:%02X:%02X",
}
static int
{
unsigned int rxq_size;
int rxq_poll_usec;
int rc;
/* Allocate the object */
/* Get property values */
if (rxq_poll_usec <= 0)
DDI_PROP_DONTPASS, "mcdi_logging", 0);
#endif
/* Create a taskq */
goto fail2;
}
/* Check and initialize PCI configuration space */
goto fail3;
/* Map the device registers */
goto fail4;
/* Create the NIC object */
goto fail5;
/* Initialize MCDI to talk to the Microcontroller */
goto fail6;
/* Probe the NIC and build the configuration data area */
goto fail7;
case EFX_FAMILY_HUNTINGTON:
break;
case EFX_FAMILY_SIENA:
break;
default:
break;
}
goto fail8;
goto fail9;
goto fail10;
goto fail11;
goto fail12;
goto fail13;
goto fail14;
goto fail15;
goto fail16;
return (0);
/* Clear property values */
/* Free the soft state */
return (rc);
}
static int
{
int rc;
goto done;
goto fail1;
}
/* Start a new epoch (allow fresh MCDI requests to succeed) */
goto fail2;
goto fail3;
goto fail4;
goto fail5;
goto fail6;
goto fail7;
goto fail8;
goto fail9;
goto fail10;
goto fail11;
/* Notify any change of MTU */
done:
return (0);
return (rc);
}
int
{
int rc;
return (rc);
}
static void
{
return;
}
/* Stop event processing - must be after rx_stop see sfxge_rx_qpoll() */
}
void
{
}
static void
{
int rc;
/* logging on entry is in sfxge_restart_dispatch */
goto done;
/* inform the OS that the link is down - may trigger IPMP failover */
}
/* Stop processing */
"NIC error - interface is"
" being left permanently DOWN per driver config");
return;
} else
/* Start processing */
goto fail1;
done:
return;
}
int
{
if (hw_err == SFXGE_HW_OK)
sp->s_num_restarts++;
else {
}
/* A restart is currently in progress */
return (0);
}
reason);
/* If cflags == DDI_SLEEP then guaranteed to succeed */
}
static int
{
int index;
/*
* In SFC bug 19834 it was noted that a mblk passed up to STREAMS
* could be reused for transmit and sit in the sfxge_tx_packet_cache.
* This call to empty the TX deferred packet list may result in
* rx_loaned reducing.
*/
while (--index >= 0) {
}
/* Need to wait for desballoc free_func callback */
return (sfxge_rx_loaned(sp));
}
static int
{
int rc;
if (sfxge_can_destroy(sp) != 0) {
goto fail1;
}
(void) efx_nic_reset(enp);
/* Destroy the NIC object */
/* Unmap the device registers */
/* Tear down PCI configuration space */
/* Destroy the taskq */
/* Clear property values */
/* Free the soft state */
return (0);
return (rc);
}
void
{
/*
* single concurrent IOCTL
* serialized from sfxge_create, _destroy, _(re)start, _stop
*/
/*LINTED*/
case SFXGE_NVRAM_IOC:
ioclen = sizeof (sfxge_nvram_ioc_t);
break;
case SFXGE_MCDI_IOC:
ioclen = sizeof (sfxge_mcdi_ioc_t);
break;
case SFXGE_MCDI2_IOC:
ioclen = sizeof (sfxge_mcdi2_ioc_t);
break;
case SFXGE_VPD_IOC:
ioclen = sizeof (sfxge_vpd_ioc_t);
break;
case SFXGE_NIC_RESET_IOC:
break;
default:
goto fail1;
}
goto fail2;
}
/* if in multiple fragments pull it up to one linear buffer */
goto fail3;
}
case SFXGE_NVRAM_IOC: {
goto fail4;
break;
}
case SFXGE_MCDI_IOC: {
goto fail4;
taskq_wait = 1;
break;
}
case SFXGE_MCDI2_IOC: {
goto fail4;
taskq_wait = 1;
break;
}
case SFXGE_NIC_RESET_IOC: {
/* sp->s_state_lock held */
"NIC_RESET_IOC", 0);
taskq_wait = 1;
break;
}
case SFXGE_VPD_IOC: {
goto fail4;
break;
}
default:
ASSERT(0);
}
if (taskq_wait) {
/*
* Wait for any tasks that may be accessing GLD functions
* This may end up waiting for multiple nic_resets
* as it needs to be outside of s_state_lock for sfxge_restart()
*/
}
/* The entire structure is the acknowledgement */
return;
/* no data returned */
}
static int
{
int rc;
goto fail1;
return (0);
return (rc);
}
static int
{
int rc;
/* Wait for any tasks that may be accessing GLD functions */
goto fail1;
return (0);
return (rc);
}
static void
{
}
}
static int
{
int rc;
/* Get a copy of the VPD space */
goto fail1;
goto fail2;
}
goto fail3;
}
goto fail4;
KSTAT_FLAG_VIRTUAL)) == NULL) {
goto fail5;
}
return (0);
return (rc);
}
static void
{
/* NOTE: VPD support is optional, so kstats might not be registered */
sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
sizeof (kstat_named_t) * SFXGE_VPD_MAX);
}
}
static int
{
int rc;
/* Create the set */
KSTAT_FLAG_VIRTUAL)) == NULL) {
goto fail1;
}
return (0);
return (rc);
}
static void
{
return;
}
static int
{
int rc;
/* Start processing */
goto fail1;
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
static int
{
int rc;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_FAILURE);
return (sfxge_resume(sp));
default:
return (DDI_FAILURE);
}
/* Create the soft state */
goto fail1;
/* Create the configuration kstats */
goto fail2;
/* Create the VPD kstats */
goto fail3;
}
/* Register the interface */
goto fail4;
/* Announce ourselves in the system log */
return (DDI_SUCCESS);
/* Destroy the VPD kstats */
/* Destroy the configuration kstats */
/* Destroy the soft state */
(void) sfxge_destroy(sp);
return (DDI_FAILURE);
}
static int
{
/* Stop processing */
sfxge_stop(sp);
return (DDI_SUCCESS);
}
static int
{
int rc;
switch (cmd) {
case DDI_DETACH:
return (DDI_FAILURE);
break;
case DDI_SUSPEND:
return (DDI_FAILURE);
return (sfxge_suspend(sp));
default:
return (DDI_FAILURE);
}
/* Wait for any pending restarts to complete */
/*
* IOCTLs from utilites can cause GLD mc_start() (SFXGE_STARTED state)
* And mc_stop() may not occur until detach time and race. SFC bug 19855
* Holding the lock seems to be enough - the log message is not seen
*/
"STREAMS detach when STARTED");
}
goto destroy;
/* Unregister the interface */
goto fail1;
/* Destroy the VPD kstats */
/* Destroy the configuration kstats */
/*
* Destroy the soft state - this might fail until rx_loaned packets that
* have been passed up the STREAMS stack are returned
*/
goto fail2;
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
/*
* modlinkage
*/
(char *)sfxge_ident,
};
{ &sfxge_modldrv, NULL }
};
unsigned int *sfxge_cpu;
int
_init(void)
{
int rc;
/* Create tables for CPU, core, cache and chip counts */
goto fail1;
return (0);
return (rc);
}
int
_fini(void)
{
int rc;
return (rc);
/* Destroy tables */
return (0);
}
int
{
}