Mercurial > illumos > illumos-gate
changeset 6705:50db7364dad5
6679395 nxge_dev_ops should be initialized with the DDI_DEFINE_STREAM_OPS macro
6608404 hot plug operation on Atlas QGC card leave pending INTx interrupts.
author | ml29623 |
---|---|
date | Fri, 23 May 2008 16:33:43 -0700 |
parents | 69d909654d1c |
children | 2d5b422fab0d |
files | usr/src/uts/common/io/nxge/nxge_main.c usr/src/uts/common/sys/nxge/nxge_virtual.h |
diffstat | 2 files changed, 150 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/nxge/nxge_main.c Fri May 23 14:27:10 2008 -0700 +++ b/usr/src/uts/common/io/nxge/nxge_main.c Fri May 23 16:33:43 2008 -0700 @@ -48,6 +48,16 @@ #endif /* + * Software workaround for a Neptune (PCI-E) + * hardware interrupt bug which the hardware + * may generate spurious interrupts after the + * device interrupt handler was removed. If this flag + * is enabled, the driver will reset the + * hardware when devices are being detached. + */ +uint32_t nxge_peu_reset_enable = 0; + +/* * Software workaround for the hardware * checksum bugs that affect packet transmission * and receive: @@ -270,6 +280,7 @@ void *); static int nxge_get_def_val(nxge_t *, mac_prop_id_t, uint_t, void *); +static void nxge_niu_peu_reset(p_nxge_t nxgep); mac_priv_prop_t nxge_priv_props[] = { {"_adv_10gfdx_cap", MAC_PROP_PERM_RW}, @@ -930,6 +941,14 @@ nxgep->nxge_timerid = 0; } + /* + * If this flag is set, it will affect the Neptune + * only. + */ + if ((nxgep->niu_type != N2_NIU) && nxge_peu_reset_enable) { + nxge_niu_peu_reset(nxgep); + } + #if defined(sun4v) if (isLDOMguest(nxgep)) { (void) nxge_hio_vr_release(nxgep); @@ -1653,7 +1672,17 @@ nxge_free_mem_pool(nxgep); - (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); + /* + * Start the timer if the reset flag is not set. + * If this reset flag is set, the link monitor + * will not be started in order to stop furthur bus + * activities coming from this interface. + * The driver will start the monitor function + * if the interface was initialized again later. + */ + if (!nxge_peu_reset_enable) { + (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); + } nxgep->drv_state &= ~STATE_HW_INITIALIZED; @@ -3613,6 +3642,10 @@ NXGE_DEBUG_MSG((nxgep, NXGE_CTL, "==> nxge_m_start")); + if (nxge_peu_reset_enable && !nxgep->nxge_link_poll_timerid) { + (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); + } + MUTEX_ENTER(nxgep->genlock); if (nxge_init(nxgep) != NXGE_OK) { NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, @@ -4447,7 +4480,7 @@ /* * No dynamic allocation of groups and * rings at this time. Shares dictate the - * configurartion. + * configuration. */ mrings->mr_gadd_ring = NULL; mrings->mr_grem_ring = NULL; @@ -5472,42 +5505,8 @@ * Module loading and removing entry points. */ -static struct cb_ops nxge_cb_ops = { - nodev, /* cb_open */ - nodev, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - nodev, /* cb_read */ - nodev, /* cb_write */ - nodev, /* cb_ioctl */ - nodev, /* cb_devmap */ - nodev, /* cb_mmap */ - nodev, /* cb_segmap */ - nochpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - NULL, - D_MP, /* cb_flag */ - CB_REV, /* rev */ - nodev, /* int (*cb_aread)() */ - nodev /* int (*cb_awrite)() */ -}; - -static struct dev_ops nxge_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - nulldev, - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - nxge_attach, /* devo_attach */ - nxge_detach, /* devo_detach */ - nodev, /* devo_reset */ - &nxge_cb_ops, /* devo_cb_ops */ - (struct bus_ops *)NULL, /* devo_bus_ops */ - ddi_power /* devo_power */ -}; - -extern struct mod_ops mod_driverops; +DDI_DEFINE_STREAM_OPS(nxge_dev_ops, nulldev, nulldev, nxge_attach, nxge_detach, + nodev, NULL, D_MP, NULL); #define NXGE_DESC_VER "Sun NIU 10Gb Ethernet" @@ -6679,3 +6678,113 @@ } return (err); } + + +/* + * The following is a software around for the Neptune hardware's + * interrupt bugs; The Neptune hardware may generate spurious interrupts when + * an interrupr handler is removed. + */ +#define NXGE_PCI_PORT_LOGIC_OFFSET 0x98 +#define NXGE_PIM_RESET (1ULL << 29) +#define NXGE_GLU_RESET (1ULL << 30) +#define NXGE_NIU_RESET (1ULL << 31) +#define NXGE_PCI_RESET_ALL (NXGE_PIM_RESET | \ + NXGE_GLU_RESET | \ + NXGE_NIU_RESET) + +#define NXGE_WAIT_QUITE_TIME 200000 +#define NXGE_WAIT_QUITE_RETRY 40 +#define NXGE_PCI_RESET_WAIT 1000000 /* one second */ + +static void +nxge_niu_peu_reset(p_nxge_t nxgep) +{ + uint32_t rvalue; + p_nxge_hw_list_t hw_p; + p_nxge_t fnxgep; + int i, j; + + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_niu_peu_reset")); + if ((hw_p = nxgep->nxge_hw_p) == NULL) { + NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: NULL hardware pointer")); + return; + } + + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: flags 0x%x link timer id %d timer id %d", + hw_p->flags, nxgep->nxge_link_poll_timerid, + nxgep->nxge_timerid)); + + MUTEX_ENTER(&hw_p->nxge_cfg_lock); + /* + * Make sure other instances from the same hardware + * stop sending PIO and in quiescent state. + */ + for (i = 0; i < NXGE_MAX_PORTS; i++) { + fnxgep = hw_p->nxge_p[i]; + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: checking entry %d " + "nxgep $%p", i, fnxgep)); +#ifdef NXGE_DEBUG + if (fnxgep) { + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: entry %d (function %d) " + "link timer id %d hw timer id %d", + i, fnxgep->function_num, + fnxgep->nxge_link_poll_timerid, + fnxgep->nxge_timerid)); + } +#endif + if (fnxgep && fnxgep != nxgep && + (fnxgep->nxge_timerid || fnxgep->nxge_link_poll_timerid)) { + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: checking $%p " + "(function %d) timer ids", + fnxgep, fnxgep->function_num)); + for (j = 0; j < NXGE_WAIT_QUITE_RETRY; j++) { + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "==> nxge_niu_peu_reset: waiting")); + NXGE_DELAY(NXGE_WAIT_QUITE_TIME); + if (!fnxgep->nxge_timerid && + !fnxgep->nxge_link_poll_timerid) { + break; + } + } + NXGE_DELAY(NXGE_WAIT_QUITE_TIME); + if (fnxgep->nxge_timerid || + fnxgep->nxge_link_poll_timerid) { + MUTEX_EXIT(&hw_p->nxge_cfg_lock); + NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, + "<== nxge_niu_peu_reset: cannot reset " + "hardware (devices are still in use)")); + return; + } + } + } + + if ((hw_p->flags & COMMON_RESET_NIU_PCI) != COMMON_RESET_NIU_PCI) { + hw_p->flags |= COMMON_RESET_NIU_PCI; + rvalue = pci_config_get32(nxgep->dev_regs->nxge_pciregh, + NXGE_PCI_PORT_LOGIC_OFFSET); + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "nxge_niu_peu_reset: read offset 0x%x (%d) " + "(data 0x%x)", + NXGE_PCI_PORT_LOGIC_OFFSET, + NXGE_PCI_PORT_LOGIC_OFFSET, + rvalue)); + + rvalue |= NXGE_PCI_RESET_ALL; + pci_config_put32(nxgep->dev_regs->nxge_pciregh, + NXGE_PCI_PORT_LOGIC_OFFSET, rvalue); + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, + "nxge_niu_peu_reset: RESETTING NIU: write NIU reset 0x%x", + rvalue)); + + NXGE_DELAY(NXGE_PCI_RESET_WAIT); + } + + MUTEX_EXIT(&hw_p->nxge_cfg_lock); + NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, "<== nxge_niu_peu_reset")); +}
--- a/usr/src/uts/common/sys/nxge/nxge_virtual.h Fri May 23 14:27:10 2008 -0700 +++ b/usr/src/uts/common/sys/nxge/nxge_virtual.h Fri May 23 16:33:43 2008 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,6 +59,8 @@ #define COMMON_INIT_DONE 0x08 #define COMMON_TCAM_BUSY 0x10 #define COMMON_VLAN_BUSY 0x20 +#define COMMON_RESET_NIU_PCI 0x40 + #define NXGE_SR_FUNC_BUSY_SHIFT 0x8 #define NXGE_SR_FUNC_BUSY_MASK 0xf00