123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953 |
- /*******************************************************************************
-
- Intel(R) 82576 Virtual Function Linux driver
- Copyright(c) 2009 Intel Corporation.
-
- Copyright(c) 2010 Eric Keller <ekeller@princeton.edu>
- Copyright(c) 2010 Red Hat Inc.
- Alex Williamson <alex.williamson@redhat.com>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms and conditions of the GNU General Public License,
- version 2, as published by the Free Software Foundation.
-
- This program is distributed in the hope it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
- The full GNU General Public License is included in this distribution in
- the file called "COPYING".
-
- Contact Information:
- e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
- Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
- *******************************************************************************/
-
- FILE_LICENCE ( GPL2_ONLY );
-
- #include "igbvf.h"
-
- /**
- * igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
- *
- * @v adapter e1000 private structure
- *
- * @ret rc Returns 0 on success, negative on failure
- **/
- int igbvf_setup_tx_resources ( struct igbvf_adapter *adapter )
- {
- DBG ( "igbvf_setup_tx_resources\n" );
-
- /* Allocate transmit descriptor ring memory.
- It must not cross a 64K boundary because of hardware errata #23
- so we use malloc_dma() requesting a 128 byte block that is
- 128 byte aligned. This should guarantee that the memory
- allocated will not cross a 64K boundary, because 128 is an
- even multiple of 65536 ( 65536 / 128 == 512 ), so all possible
- allocations of 128 bytes on a 128 byte boundary will not
- cross 64K bytes.
- */
-
- adapter->tx_base =
- malloc_dma ( adapter->tx_ring_size, adapter->tx_ring_size );
-
- if ( ! adapter->tx_base ) {
- return -ENOMEM;
- }
-
- memset ( adapter->tx_base, 0, adapter->tx_ring_size );
-
- DBG ( "adapter->tx_base = %#08lx\n", virt_to_bus ( adapter->tx_base ) );
-
- return 0;
- }
-
- /**
- * igbvf_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
- *
- * Free all transmit software resources
- **/
- void igbvf_free_tx_resources ( struct igbvf_adapter *adapter )
- {
- DBG ( "igbvf_free_tx_resources\n" );
-
- free_dma ( adapter->tx_base, adapter->tx_ring_size );
- }
-
- /**
- * igbvf_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
- *
- * Free all receive software resources
- **/
- void igbvf_free_rx_resources ( struct igbvf_adapter *adapter )
- {
- int i;
-
- DBG ( "igbvf_free_rx_resources\n" );
-
- free_dma ( adapter->rx_base, adapter->rx_ring_size );
-
- for ( i = 0; i < NUM_RX_DESC; i++ ) {
- free_iob ( adapter->rx_iobuf[i] );
- }
- }
-
- /**
- * igbvf_refill_rx_ring - allocate Rx io_buffers
- *
- * @v adapter e1000 private structure
- *
- * @ret rc Returns 0 on success, negative on failure
- **/
- static int igbvf_refill_rx_ring ( struct igbvf_adapter *adapter )
- {
- int i, rx_curr;
- int rc = 0;
- union e1000_adv_rx_desc *rx_curr_desc;
- struct e1000_hw *hw = &adapter->hw;
- struct io_buffer *iob;
-
- DBGP ("igbvf_refill_rx_ring\n");
-
- for ( i = 0; i < NUM_RX_DESC; i++ ) {
- rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
- rx_curr_desc = adapter->rx_base + rx_curr;
-
- if ( rx_curr_desc->wb.upper.status_error & E1000_RXD_STAT_DD )
- continue;
-
- if ( adapter->rx_iobuf[rx_curr] != NULL )
- continue;
-
- DBG2 ( "Refilling rx desc %d\n", rx_curr );
-
- iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
- adapter->rx_iobuf[rx_curr] = iob;
-
- rx_curr_desc->wb.upper.status_error = 0;
-
- if ( ! iob ) {
- DBG ( "alloc_iob failed\n" );
- rc = -ENOMEM;
- break;
- } else {
- rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
- rx_curr_desc->read.hdr_addr = 0;
- ew32 ( RDT(0), rx_curr );
- }
- }
- return rc;
- }
-
- /**
- * igbvf_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
- static void igbvf_irq_disable ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
-
- ew32 ( EIMC, ~0 );
- }
-
- /**
- * igbvf_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
- static void igbvf_irq_enable ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
-
- ew32 ( EIAC, IMS_ENABLE_MASK );
- ew32 ( EIAM, IMS_ENABLE_MASK );
- ew32 ( EIMS, IMS_ENABLE_MASK );
- }
-
- /**
- * igbvf_irq - enable or Disable interrupts
- *
- * @v adapter e1000 adapter
- * @v action requested interrupt action
- **/
- static void igbvf_irq ( struct net_device *netdev, int enable )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
-
- DBG ( "igbvf_irq\n" );
-
- if ( enable ) {
- igbvf_irq_enable ( adapter );
- } else {
- igbvf_irq_disable ( adapter );
- }
- }
-
- /**
- * igbvf_process_tx_packets - process transmitted packets
- *
- * @v netdev network interface device structure
- **/
- static void igbvf_process_tx_packets ( struct net_device *netdev )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- uint32_t i;
- uint32_t tx_status;
- union e1000_adv_tx_desc *tx_curr_desc;
-
- /* Check status of transmitted packets
- */
- DBGP ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head,
- adapter->tx_tail );
-
- while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
-
- tx_curr_desc = ( void * ) ( adapter->tx_base ) +
- ( i * sizeof ( *adapter->tx_base ) );
-
- tx_status = tx_curr_desc->wb.status;
- DBG ( " tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
- DBG ( " tx_status = %#08x\n", tx_status );
-
- /* if the packet at tx_head is not owned by hardware it is for us */
- if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
- break;
-
- DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
- adapter->tx_head, adapter->tx_tail, tx_status );
-
- netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
- DBG ( "Success transmitting packet, tx_status: %#08x\n",
- tx_status );
-
- /* Decrement count of used descriptors, clear this descriptor
- */
- adapter->tx_fill_ctr--;
- memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
-
- adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
- }
- }
-
- /**
- * igbvf_process_rx_packets - process received packets
- *
- * @v netdev network interface device structure
- **/
- static void igbvf_process_rx_packets ( struct net_device *netdev )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- struct e1000_hw *hw = &adapter->hw;
- uint32_t i;
- uint32_t rx_status;
- uint32_t rx_len;
- uint32_t rx_err;
- union e1000_adv_rx_desc *rx_curr_desc;
-
- DBGP ( "igbvf_process_rx_packets\n" );
-
- /* Process received packets
- */
- while ( 1 ) {
- i = adapter->rx_curr;
-
- rx_curr_desc = ( void * ) ( adapter->rx_base ) +
- ( i * sizeof ( *adapter->rx_base ) );
- rx_status = rx_curr_desc->wb.upper.status_error;
-
- DBG2 ( "Before DD Check RX_status: %#08x, rx_curr: %d\n",
- rx_status, i );
-
- if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
- break;
-
- if ( adapter->rx_iobuf[i] == NULL )
- break;
-
- DBG ( "E1000_RCTL = %#08x\n", er32 (RCTL) );
-
- rx_len = rx_curr_desc->wb.upper.length;
-
- DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n",
- i, rx_status, rx_len );
-
- rx_err = rx_status;
-
- iob_put ( adapter->rx_iobuf[i], rx_len );
-
- if ( rx_err & E1000_RXDEXT_ERR_FRAME_ERR_MASK ) {
-
- netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
- DBG ( "igbvf_process_rx_packets: Corrupted packet received!"
- " rx_err: %#08x\n", rx_err );
- } else {
- /* Add this packet to the receive queue. */
- netdev_rx ( netdev, adapter->rx_iobuf[i] );
- }
- adapter->rx_iobuf[i] = NULL;
-
- memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
-
- adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
- }
- }
-
- /**
- * igbvf_poll - Poll for received packets
- *
- * @v netdev Network device
- */
- static void igbvf_poll ( struct net_device *netdev )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- uint32_t rx_status;
- union e1000_adv_rx_desc *rx_curr_desc;
-
- DBGP ( "igbvf_poll\n" );
-
- rx_curr_desc = ( void * ) ( adapter->rx_base ) +
- ( adapter->rx_curr * sizeof ( *adapter->rx_base ) );
- rx_status = rx_curr_desc->wb.upper.status_error;
-
- if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
- return;
-
- igbvf_process_tx_packets ( netdev );
-
- igbvf_process_rx_packets ( netdev );
-
- igbvf_refill_rx_ring ( adapter );
- }
-
- /**
- * igbvf_config_collision_dist_generic - Configure collision distance
- * @hw: pointer to the HW structure
- *
- * Configures the collision distance to the default value and is used
- * during link setup. Currently no func pointer exists and all
- * implementations are handled in the generic version of this function.
- **/
- void igbvf_config_collision_dist ( struct e1000_hw *hw )
- {
- u32 tctl;
-
- DBG ("igbvf_config_collision_dist");
-
- tctl = er32 (TCTL);
-
- tctl &= ~E1000_TCTL_COLD;
- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
-
- ew32 (TCTL, tctl);
- e1e_flush();
- }
-
- /**
- * igbvf_configure_tx - Configure Transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
- **/
- static void igbvf_configure_tx ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
- u32 tctl, txdctl;
-
- DBG ( "igbvf_configure_tx\n" );
-
- /* disable transmits while setting up the descriptors */
- tctl = er32 ( TCTL );
- ew32 ( TCTL, tctl & ~E1000_TCTL_EN );
- e1e_flush();
- mdelay (10);
-
- ew32 ( TDBAH(0), 0 );
- ew32 ( TDBAL(0), virt_to_bus ( adapter->tx_base ) );
- ew32 ( TDLEN(0), adapter->tx_ring_size );
-
- DBG ( "E1000_TDBAL(0): %#08x\n", er32 ( TDBAL(0) ) );
- DBG ( "E1000_TDLEN(0): %d\n", er32 ( TDLEN(0) ) );
-
- /* Setup the HW Tx Head and Tail descriptor pointers */
- ew32 ( TDH(0), 0 );
- ew32 ( TDT(0), 0 );
-
- adapter->tx_head = 0;
- adapter->tx_tail = 0;
- adapter->tx_fill_ctr = 0;
-
- txdctl = er32(TXDCTL(0));
- txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
- ew32 ( TXDCTL(0), txdctl );
-
- txdctl = er32 ( TXDCTL(0) );
- txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
- ew32 ( TXDCTL(0), txdctl );
-
- /* Setup Transmit Descriptor Settings for eop descriptor */
- adapter->txd_cmd = E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_IFCS;
-
- /* Advanced descriptor */
- adapter->txd_cmd |= E1000_ADVTXD_DCMD_DEXT;
-
- /* (not part of cmd, but in same 32 bit word...) */
- adapter->txd_cmd |= E1000_ADVTXD_DTYP_DATA;
-
- /* enable Report Status bit */
- adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
-
- /* Program the Transmit Control Register */
- tctl &= ~E1000_TCTL_CT;
- tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
-
- igbvf_config_collision_dist ( hw );
-
- /* Enable transmits */
- tctl |= E1000_TCTL_EN;
- ew32(TCTL, tctl);
- e1e_flush();
- }
-
- /* igbvf_reset - bring the hardware into a known good state
- *
- * This function boots the hardware and enables some settings that
- * require a configuration cycle of the hardware - those cannot be
- * set/changed during runtime. After reset the device needs to be
- * properly configured for Rx, Tx etc.
- */
- void igbvf_reset ( struct igbvf_adapter *adapter )
- {
- struct e1000_mac_info *mac = &adapter->hw.mac;
- struct net_device *netdev = adapter->netdev;
- struct e1000_hw *hw = &adapter->hw;
-
- /* Allow time for pending master requests to run */
- if ( mac->ops.reset_hw(hw) )
- DBG ("PF still resetting\n");
-
- mac->ops.init_hw ( hw );
-
- if ( is_valid_ether_addr(adapter->hw.mac.addr) ) {
- memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
- }
- }
-
- extern void igbvf_init_function_pointers_vf(struct e1000_hw *hw);
-
- /**
- * igbvf_sw_init - Initialize general software structures (struct igbvf_adapter)
- * @adapter: board private structure to initialize
- *
- * igbvf_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
- **/
- static int __devinit igbvf_sw_init ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
- struct pci_device *pdev = adapter->pdev;
- int rc;
-
- /* PCI config space info */
-
- hw->vendor_id = pdev->vendor;
- hw->device_id = pdev->device;
-
- pci_read_config_byte ( pdev, PCI_REVISION, &hw->revision_id );
-
- pci_read_config_word ( pdev, PCI_COMMAND, &hw->bus.pci_cmd_word );
-
- adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE + ETH_HLEN + ETH_FCS_LEN;
- adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
-
- /* Set various function pointers */
- igbvf_init_function_pointers_vf ( &adapter->hw );
-
- rc = adapter->hw.mac.ops.init_params ( &adapter->hw );
- if (rc) {
- DBG ("hw.mac.ops.init_params(&adapter->hw) Failure\n");
- return rc;
- }
-
- rc = adapter->hw.mbx.ops.init_params ( &adapter->hw );
- if (rc) {
- DBG ("hw.mbx.ops.init_params(&adapter->hw) Failure\n");
- return rc;
- }
-
- /* Explicitly disable IRQ since the NIC can be in any state. */
- igbvf_irq_disable ( adapter );
-
- return 0;
- }
-
- /**
- * igbvf_setup_srrctl - configure the receive control registers
- * @adapter: Board private structure
- **/
- static void igbvf_setup_srrctl ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
- u32 srrctl = 0;
-
- DBG ( "igbvf_setup_srrctl\n" );
-
- srrctl &= ~(E1000_SRRCTL_DESCTYPE_MASK |
- E1000_SRRCTL_BSIZEHDR_MASK |
- E1000_SRRCTL_BSIZEPKT_MASK);
-
- /* Enable queue drop to avoid head of line blocking */
- srrctl |= E1000_SRRCTL_DROP_EN;
-
- /* Setup buffer sizes */
- srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
- srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
-
- ew32 ( SRRCTL(0), srrctl );
- }
-
- /**
- * igbvf_configure_rx - Configure 8254x Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Rx unit of the MAC after a reset.
- **/
- static void igbvf_configure_rx ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
- u32 rxdctl;
-
- DBG ( "igbvf_configure_rx\n" );
-
- /* disable receives */
- rxdctl = er32 ( RXDCTL(0) );
- ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
- msleep ( 10 );
-
- /*
- * Setup the HW Rx Head and Tail Descriptor Pointers and
- * the Base and Length of the Rx Descriptor Ring
- */
- ew32 ( RDBAL(0), virt_to_bus (adapter->rx_base) );
- ew32 ( RDBAH(0), 0 );
- ew32 ( RDLEN(0), adapter->rx_ring_size );
- adapter->rx_curr = 0;
- ew32 ( RDH(0), 0 );
- ew32 ( RDT(0), 0 );
-
- rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
- rxdctl &= 0xFFF00000;
- rxdctl |= IGBVF_RX_PTHRESH;
- rxdctl |= IGBVF_RX_HTHRESH << 8;
- rxdctl |= IGBVF_RX_WTHRESH << 16;
-
- igbvf_rlpml_set_vf ( hw, adapter->max_frame_size );
-
- /* enable receives */
- ew32 ( RXDCTL(0), rxdctl );
- ew32 ( RDT(0), NUM_RX_DESC );
- }
-
- /**
- * igbvf_setup_rx_resources - allocate Rx resources (Descriptors)
- *
- * @v adapter e1000 private structure
- **/
- int igbvf_setup_rx_resources ( struct igbvf_adapter *adapter )
- {
- int i;
- union e1000_adv_rx_desc *rx_curr_desc;
- struct io_buffer *iob;
-
- DBG ( "igbvf_setup_rx_resources\n" );
-
- /* Allocate receive descriptor ring memory.
- It must not cross a 64K boundary because of hardware errata
- */
-
- adapter->rx_base =
- malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
-
- if ( ! adapter->rx_base ) {
- return -ENOMEM;
- }
- memset ( adapter->rx_base, 0, adapter->rx_ring_size );
-
- for ( i = 0; i < NUM_RX_DESC; i++ ) {
- rx_curr_desc = adapter->rx_base + i;
- iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
- adapter->rx_iobuf[i] = iob;
- rx_curr_desc->wb.upper.status_error = 0;
- if ( ! iob ) {
- DBG ( "alloc_iob failed\n" );
- return -ENOMEM;
- } else {
- rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
- rx_curr_desc->read.hdr_addr = 0;
- }
- }
-
- return 0;
- }
-
- /**
- * igbvf_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * The open entry point is called when a network interface is made
- * active by the system (IFF_UP). At this point all resources needed
- * for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
- * and the stack is notified that the interface is ready.
- **/
- static int igbvf_open ( struct net_device *netdev )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- int err;
-
- DBG ("igbvf_open\n");
-
- /* Update MAC address */
- memcpy ( adapter->hw.mac.addr, netdev->ll_addr, ETH_ALEN );
- igbvf_reset( adapter );
-
- /* allocate transmit descriptors */
- err = igbvf_setup_tx_resources ( adapter );
- if (err) {
- DBG ( "Error setting up TX resources!\n" );
- goto err_setup_tx;
- }
-
- igbvf_configure_tx ( adapter );
-
- igbvf_setup_srrctl( adapter );
-
- err = igbvf_setup_rx_resources( adapter );
- if (err) {
- DBG ( "Error setting up RX resources!\n" );
- goto err_setup_rx;
- }
-
- igbvf_configure_rx ( adapter );
-
- return 0;
-
- err_setup_rx:
- DBG ( "err_setup_rx\n" );
- igbvf_free_tx_resources ( adapter );
- return err;
-
- err_setup_tx:
- DBG ( "err_setup_tx\n" );
- igbvf_reset ( adapter );
-
- return err;
- }
-
- /**
- * igbvf_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * Returns 0, this is not allowed to fail
- *
- * The close entry point is called when an interface is de-activated
- * by the OS. The hardware is still under the drivers control, but
- * needs to be disabled. A global MAC reset is issued to stop the
- * hardware, and all transmit and receive resources are freed.
- **/
- static void igbvf_close ( struct net_device *netdev )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- struct e1000_hw *hw = &adapter->hw;
- uint32_t rxdctl;
-
- DBG ( "igbvf_close\n" );
-
- /* Disable and acknowledge interrupts */
- igbvf_irq_disable ( adapter );
- er32(EICR);
-
- /* disable receives */
- rxdctl = er32 ( RXDCTL(0) );
- ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
- mdelay ( 10 );
-
- igbvf_reset ( adapter );
-
- igbvf_free_tx_resources( adapter );
- igbvf_free_rx_resources( adapter );
- }
-
- /**
- * igbvf_transmit - Transmit a packet
- *
- * @v netdev Network device
- * @v iobuf I/O buffer
- *
- * @ret rc Returns 0 on success, negative on failure
- */
- static int igbvf_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
- {
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
- struct e1000_hw *hw = &adapter->hw;
- uint32_t tx_curr = adapter->tx_tail;
- union e1000_adv_tx_desc *tx_curr_desc;
-
- DBGP ("igbvf_transmit\n");
-
- if ( adapter->tx_fill_ctr == NUM_TX_DESC ) {
- DBG ("TX overflow\n");
- return -ENOBUFS;
- }
-
- /* Save pointer to iobuf we have been given to transmit,
- netdev_tx_complete() will need it later
- */
- adapter->tx_iobuf[tx_curr] = iobuf;
-
- tx_curr_desc = ( void * ) ( adapter->tx_base ) +
- ( tx_curr * sizeof ( *adapter->tx_base ) );
-
- DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
- DBG ( "tx_curr_desc + 16 = %#08lx\n", virt_to_bus ( tx_curr_desc ) + 16 );
- DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
-
- /* Add the packet to TX ring
- */
- tx_curr_desc->read.buffer_addr = virt_to_bus ( iobuf->data );
- tx_curr_desc->read.cmd_type_len = adapter->txd_cmd |(iob_len ( iobuf )) ;
- // minus hdr_len ????
- tx_curr_desc->read.olinfo_status = ((iob_len ( iobuf )) << E1000_ADVTXD_PAYLEN_SHIFT);
-
- DBG ( "TX fill: %d tx_curr: %d addr: %#08lx len: %zd\n", adapter->tx_fill_ctr,
- tx_curr, virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
-
- /* Point to next free descriptor */
- adapter->tx_tail = ( adapter->tx_tail + 1 ) % NUM_TX_DESC;
- adapter->tx_fill_ctr++;
-
- /* Write new tail to NIC, making packet available for transmit
- */
- ew32 ( TDT(0), adapter->tx_tail );
- e1e_flush ();
-
- return 0;
- }
-
- /** igbvf net device operations */
- static struct net_device_operations igbvf_operations = {
- .open = igbvf_open,
- .close = igbvf_close,
- .transmit = igbvf_transmit,
- .poll = igbvf_poll,
- .irq = igbvf_irq,
- };
-
- /**
- * igbvf_get_hw_control - get control of the h/w from f/w
- * @adapter: address of board private structure
- *
- * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that
- * the driver is loaded.
- *
- **/
- void igbvf_get_hw_control ( struct igbvf_adapter *adapter )
- {
- struct e1000_hw *hw = &adapter->hw;
- u32 ctrl_ext;
-
- /* Let firmware know the driver has taken over */
- ctrl_ext = er32 ( CTRL_EXT );
- ew32 ( CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD );
- }
-
- /**
- * igbvf_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in igbvf_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * igbvf_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- **/
- int igbvf_probe ( struct pci_device *pdev )
- {
- int err;
- struct net_device *netdev;
- struct igbvf_adapter *adapter;
- unsigned long mmio_start, mmio_len;
- struct e1000_hw *hw;
-
- DBG ( "igbvf_probe\n" );
-
- err = -ENOMEM;
-
- /* Allocate net device ( also allocates memory for netdev->priv
- and makes netdev-priv point to it ) */
- netdev = alloc_etherdev ( sizeof ( struct igbvf_adapter ) );
- if ( ! netdev )
- goto err_alloc_etherdev;
-
- /* Associate igbvf-specific network operations operations with
- * generic network device layer */
- netdev_init ( netdev, &igbvf_operations );
-
- /* Associate this network device with given PCI device */
- pci_set_drvdata ( pdev, netdev );
- netdev->dev = &pdev->dev;
-
- /* Initialize driver private storage */
- adapter = netdev_priv ( netdev );
- memset ( adapter, 0, ( sizeof ( *adapter ) ) );
-
- adapter->pdev = pdev;
-
- adapter->ioaddr = pdev->ioaddr;
- adapter->hw.io_base = pdev->ioaddr;
-
- hw = &adapter->hw;
- hw->vendor_id = pdev->vendor;
- hw->device_id = pdev->device;
-
- adapter->irqno = pdev->irq;
- adapter->netdev = netdev;
- adapter->hw.back = adapter;
-
- adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
- adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
-
- adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
- adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;
-
- /* Fix up PCI device */
- adjust_pci_device ( pdev );
-
- err = -EIO;
-
- mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
- mmio_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_0 );
-
- DBG ( "mmio_start: %#08lx\n", mmio_start );
- DBG ( "mmio_len: %#08lx\n", mmio_len );
-
- adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
- DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );
-
- if ( ! adapter->hw.hw_addr ) {
- DBG ( "err_ioremap\n" );
- goto err_ioremap;
- }
-
- /* setup adapter struct */
- err = igbvf_sw_init ( adapter );
- if (err) {
- DBG ( "err_sw_init\n" );
- goto err_sw_init;
- }
-
- /* reset the controller to put the device in a known good state */
- err = hw->mac.ops.reset_hw ( hw );
- if ( err ) {
- DBG ("PF still in reset state, assigning new address\n");
- netdev->hw_addr[0] = 0x21;
- netdev->hw_addr[1] = 0x21;
- netdev->hw_addr[2] = 0x21;
- netdev->hw_addr[3] = 0x21;
- netdev->hw_addr[4] = 0x21;
- netdev->hw_addr[5] = 0x21;
- netdev->hw_addr[6] = 0x21;
- } else {
- err = hw->mac.ops.read_mac_addr(hw);
- if (err) {
- DBG ("Error reading MAC address\n");
- goto err_hw_init;
- }
- if ( ! is_valid_ether_addr(adapter->hw.mac.addr) ) {
- /* Assign random MAC address */
- eth_random_addr(adapter->hw.mac.addr);
- }
- }
-
- memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
-
- /* reset the hardware with the new settings */
- igbvf_reset ( adapter );
-
- /* let the f/w know that the h/w is now under the control of the
- * driver. */
- igbvf_get_hw_control ( adapter );
-
- /* Mark as link up; we don't yet handle link state */
- netdev_link_up ( netdev );
-
- if ( ( err = register_netdev ( netdev ) ) != 0) {
- DBG ( "err_register\n" );
- goto err_register;
- }
-
- DBG ("igbvf_probe_succeeded\n");
-
- return 0;
-
- err_register:
- err_hw_init:
- err_sw_init:
- iounmap ( adapter->hw.hw_addr );
- err_ioremap:
- netdev_put ( netdev );
- err_alloc_etherdev:
- return err;
- }
-
- /**
- * igbvf_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * igbvf_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device. The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- **/
- void igbvf_remove ( struct pci_device *pdev )
- {
- struct net_device *netdev = pci_get_drvdata ( pdev );
- struct igbvf_adapter *adapter = netdev_priv ( netdev );
-
- DBG ( "igbvf_remove\n" );
-
- if ( adapter->hw.flash_address )
- iounmap ( adapter->hw.flash_address );
- if ( adapter->hw.hw_addr )
- iounmap ( adapter->hw.hw_addr );
-
- unregister_netdev ( netdev );
- igbvf_reset ( adapter );
- netdev_nullify ( netdev );
- netdev_put ( netdev );
- }
-
- static struct pci_device_id igbvf_pci_tbl[] = {
- PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0),
- PCI_ROM(0x8086, 0x1520, "i350vf", "E1000_DEV_ID_I350_VF", 0),
- };
-
-
- struct pci_driver igbvf_driver __pci_driver = {
- .ids = igbvf_pci_tbl,
- .id_count = (sizeof(igbvf_pci_tbl) / sizeof(igbvf_pci_tbl[0])),
- .probe = igbvf_probe,
- .remove = igbvf_remove,
- };
|