nge_main.c revision d62bc4badc1c1f1549c961cfb8b420e650e1272b
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * Describes the chip's DMA engine 2N/A 0x0000000000000000ull,
/* dma_attr_addr_lo */ 2N/A 0x000000FFFFFFFFFFull,
/* dma_attr_addr_hi */ 2N/A 0x000000007FFFFFFFull,
/* dma_attr_count_max */ 2N/A 0x0000000000000010ull,
/* dma_attr_align */ 2N/A 0x00000FFF,
/* dma_attr_burstsizes */ 2N/A 0x00000001,
/* dma_attr_minxfer */ 2N/A 0x000000000000FFFFull,
/* dma_attr_maxxfer */ 2N/A 0x000000FFFFFFFFFFull,
/* dma_attr_seg */ 2N/A 1,
/* dma_attr_sgllen */ 2N/A 0x00000001,
/* dma_attr_granular */ 2N/A 0x0000000000000000ull,
/* dma_attr_addr_lo */ 2N/A 0x000000FFFFFFFFFFull,
/* dma_attr_addr_hi */ 2N/A 0x0000000000003FFFull,
/* dma_attr_count_max */ 2N/A 0x0000000000000010ull,
/* dma_attr_align */ 2N/A 0x00000FFF,
/* dma_attr_burstsizes */ 2N/A 0x00000001,
/* dma_attr_minxfer */ 2N/A 0x0000000000003FFFull,
/* dma_attr_maxxfer */ 2N/A 0x000000FFFFFFFFFFull,
/* dma_attr_seg */ 2N/A 1,
/* dma_attr_granular */ 2N/A 0x0000000000000000ull,
/* dma_attr_addr_lo */ 2N/A 0x00000000FFFFFFFFull,
/* dma_attr_addr_hi */ 2N/A 0x000000007FFFFFFFull,
/* dma_attr_count_max */ 2N/A 0x0000000000000010ull,
/* dma_attr_align */ 2N/A 0x00000FFF,
/* dma_attr_burstsizes */ 2N/A 0x00000001,
/* dma_attr_minxfer */ 2N/A 0x000000000000FFFFull,
/* dma_attr_maxxfer */ 2N/A 0x00000000FFFFFFFFull,
/* dma_attr_seg */ 2N/A 1,
/* dma_attr_sgllen */ 2N/A 0x00000001,
/* dma_attr_granular */ 2N/A 0x0000000000000000ull,
/* dma_attr_addr_lo */ 2N/A 0x00000000FFFFFFFFull,
/* dma_attr_addr_hi */ 2N/A 0x0000000000003FFFull,
/* dma_attr_count_max */ 2N/A 0x0000000000000010ull,
/* dma_attr_align */ 2N/A 0x00000FFF,
/* dma_attr_burstsizes */ 2N/A 0x00000001,
/* dma_attr_minxfer */ 2N/A 0x0000000000003FFFull,
/* dma_attr_maxxfer */ 2N/A 0x00000000FFFFFFFFull,
/* dma_attr_seg */ 2N/A 1,
/* dma_attr_granular */ 2N/A * DMA access attributes for data. 2N/A * DMA access attributes for descriptors. 2N/A * PIO access attributes for registers static char nge_ident[] =
"nVidia 1Gb Ethernet %I%";
* If the mode isn't being changed, there's nothing to do ... * Validate the requested mode and prepare a suitable message * to explain the link down/up cycle that the change will * All OK; tell the caller to reprogram * the PHY and/or MAC for the new mode ... * Utility routine to carve a slice off a chunk of allocated memory, * updating the chunk descriptor accordingly. The size of the slice * is given by the product of the <qty> and <size> parameters. * Allocate an area of memory and a DMA handle for accessing it NGE_TRACE((
"nge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)",
NGE_DEBUG((
"nge_alloc_dma_mem: fail to alloc dma memory!"));
* Free one allocated area of DMAable memory * Allocate memory & handles for TX buffers * Allocate memory & handles for receive return rings and * buffer (producer) descriptor rings * Allocate memory & handles for TX descriptor rings, * This routine frees the transmit and receive buffers and descriptors. * Make sure the chip is stopped before calling it! * Clean up initialisation done above before the memory is freed * Initialise the specified Send Ring, using the information in the * <dma_area> descriptors that it contains to set up all the other * fields. This routine should be called only once for each ring. * Other one-off initialisation of per-ring data * Allocate the array of s/w Send Buffer Descriptors * Now initialise each array element once and for all /* preallocate dma handles for tx buffer */ "nge_init_send_ring: alloc dma handle fails");
* Intialize the tx recycle pointer and tx sending pointer of tx ring * and set the type of tx's data descriptor by default. * Reinitialise control variables ... * Zero and sync all the h/w Send Buffer Descriptors * Initialize the slot number of rx's ring * Intialize the rx recycle pointer and rx sending pointer of rx ring * Reinitialise control variables ... * Zero and sync all the h/w Send Buffer Descriptors * Clean up initialisation done above before the memory is freed * Intialize the Rx's data ring and free ring * Allocate the array of s/w Recv Buffer Descriptors * Now initialise each array element once and for all * Fill the host address of data in rx' descriptor * and initialize free pointers of rx free ring * There is a scenario: When the traffic of small tcp * packet is heavy, suspending the tcp traffic will * cause the preallocated buffers for rx not to be * released in time by tcp taffic and cause rx's buffer * pointers not to be refilled in time. * At this point, if we reinitialize the driver, the bufp * pointer for rx's traffic will be NULL. * So the result of the reinitializion fails. /* Init the locks for send ring */ /* Init parameters of buffer ring */ /* Init recycle list lock */ * For receive ring, nothing need to be finished. * So only finish buffer ring and send ring here. * Validate format of ioctl * nge_get_props -- get the parameters to tune the driver * Clear the Multicast mac address table /* Clear the software statistics */ * Just stop processing, then record new MAC state /* If suspended, the adapter is already stopped, just return. */ /* Try to wait all the buffer post to upper layer be released */ /* Recycle all the TX BD */ * Start processing and record new MAC state * If suspended, don't start, as the resume processing * will recall this function with the suspended flag off. * Remember the new current address in the driver state * Sync the chip's idea of the address too ... * If we are suspended, we want to quit now, and not update * the chip. Doing so might put it in a bad state, but the * resume will get the unicast address installed. * Store specified mode and pass to chip layer to update h/w * If suspended, there is no need to do anything, even * recording the promiscuious mode is not neccessary, as * it won't be properly set on resume. Just return failing. * If suspended, we might actually be able to do some of * these ioctls, but it is harder to make sure they occur * without actually putting the hardware in an undesireable * Validate the command before bothering with the mutex ... (
"nge_m_ioctl: unknown cmd 0x%x",
cmd));
* Check for specific net_config privilege. NGE_DEBUG((
"nge_m_ioctl: rejected cmd 0x%x, err %d",
* Do we need to reprogram the PHY and/or the MAC? * Do it now, while we still have the mutex. * Note: update the PHY first, 'cos it controls the * Finally, decide how to reply * There's nothing for us to fill in, simply returning * B_TRUE, stating that we support polling is sufficient. * High-level cyclic handler * This routine schedules a (low-level) softint callback to the * Flag that no more activity may be initiated * Quiesce the PHY and MAC (leave it reset but still powered). * Clean up and free all NGE data structures * If there are state inconsistancies, this is bad. Returning * DDI_FAILURE here will eventually cause the machine to panic, * so it is best done here so that there is a possibility of "nge: ngep returned from ddi_get_driver_private was NULL");
"nge: passed devinfo not the same as saved devinfo");
* Fetch the config space. Even though we have most of it cached, * Only in one case, this conditional branch can be executed: the port * We note the failure, but return success, as the * system is still usable without this controller. * attach(9E) -- Attach a device to the system * Called once for each board successfully probed. " register intrs and init locks failed");
* Initialise link state variables * Stop, reset & reinitialise the chip. * Initialise the (internal) PHY. * Now that mutex locks are initialized, enable interrupts. /* Call ddi_intr_block_enable() for MSI interrupts */ /* Call ddi_intr_enable for MSI or FIXED interrupts */ * Register NDD-tweakable parameters * Create & initialise named kstats * Finally, we're ready to register ourselves with the mac * interface; if this succeeds, we're all ready to start() * Register a periodical handler. * nge_chip_cyclic() is invoked in kernel context. /* if the port hasn't been plumbed, just return */ * detach(9E) -- Detach a device from the system * Note: This driver doesn't currently support WOL, but * should it in the future, it is important to * make sure the PHY remains powered so that the * wakeup packet can actually be recieved. /* Try to wait all the buffer post to upper layer be released */ for (i = 0; i <
1000; i++) {
/* If there is any posted buffer, reject to detach */ /* Recycle the multicast table */ * Unregister from the GLD subsystem. This can fail, in * particular if there are DLPI style-2 streams still open - * in which case we just return failure without shutting * All activity stopped, so we can clean up & exit * ========== Module Loading Data & Entry Points ========== * Register interrupts and initialize each mutex and condition variables * Add the softint handlers: * Both of these handlers are used to avoid restrictions on the * context and/or mutexes required for some operations. In * particular, the hardware interrupt handler and its subfunctions * can detect a number of conditions that we don't want to handle * in that context or with that set of mutexes held. So, these * softints are triggered instead: * the <resched> softint is triggered if if we have previously * had to refuse to send a packet because of resource shortage * (we've run out of transmit buffers), but the send completion * interrupt handler has now detected that more buffers have * become available. Its only purpose is to call gld_sched() * to retry the pending transmits (we're not allowed to hold * driver-defined mutexes across gld_sched()). * the <factotum> is triggered if the h/w interrupt handler * sees the <link state changed> or <error> bits in the status * block. It's also triggered periodically to poll the link * state, just in case we aren't getting link status change "nge_attach: add nge_reschedule softintr failed");
"nge_attach: add nge_chip_factotum softintr failed!");
/* Get supported interrupt types */ NGE_DEBUG((
"ddi_intr_get_supported_types() returned: %x",
/* MSI Configurations for mcp55 chipset */ /* Enable the 8 vectors */ * Remapping the MSI MAP0 and MAP1. MCP55 * is default mapping all the interrupt to 0 vector. * Software needs to remapping this. * This mapping is same as CK804. "trying FIXED interrupt type\n"));
"registration failed\n");
* Register FIXED or MSI interrupts. /* Get number of interrupts */ /* Get number of available interrupts */ NGE_DEBUG((
"nitrs() returned %d, navail returned %d\n",
/* Allocate an array of interrupt handles */ /* Call ddi_intr_alloc() */ * Get priority for first msi, assume remaining are all the same /* Free already allocated intr */ for (i = 0; i <
actual; i++) {
/* Test for high level mutex */ "Hi level interrupt not supported");
/* Call ddi_intr_add_handler() */ for (i = 0; i <
actual; i++) {
/* Free already allocated intr */ for (i = 0; i <
actual; i++) {
for (i = 0; i <
actual; i++) {
* Unregister FIXED or MSI interrupts /* Disable all interrupts */ /* Call ddi_intr_block_disable() */ /* Call ddi_intr_remove_handler() */