summaryrefslogtreecommitdiff
path: root/drivers/net/tehuti.c
diff options
context:
space:
mode:
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-05-15 21:46:41 -0700
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-08-11 16:28:56 -0700
commitef7f54297df683665145859501f63c801f6c7ea8 (patch)
treeb41a8cc3d8b786984859e0ba483ddbe796314ff7 /drivers/net/tehuti.c
parentded19addf9c937d83b9bfb4d73a836732569041b (diff)
downloadlinux-ef7f54297df683665145859501f63c801f6c7ea8.tar.gz
linux-ef7f54297df683665145859501f63c801f6c7ea8.tar.bz2
linux-ef7f54297df683665145859501f63c801f6c7ea8.zip
tehuti: Move the Tehuti driver
Move the Tehuti driver into drivers/net/ethernet/tehuti/ and make the necessary Kconfig and Makefile changes. CC: Alexander Indenbaum <baum@tehutinetworks.net> CC: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/tehuti.c')
-rw-r--r--drivers/net/tehuti.c2470
1 files changed, 0 insertions, 2470 deletions
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
deleted file mode 100644
index 749bbf18dc6a..000000000000
--- a/drivers/net/tehuti.c
+++ /dev/null
@@ -1,2470 +0,0 @@
-/*
- * Tehuti Networks(R) Network Driver
- * ethtool interface implementation
- * Copyright (C) 2007 Tehuti Networks Ltd. All rights reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/*
- * RX HW/SW interaction overview
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * There are 2 types of RX communication channels between driver and NIC.
- * 1) RX Free Fifo - RXF - holds descriptors of empty buffers to accept incoming
- * traffic. This Fifo is filled by SW and is readen by HW. Each descriptor holds
- * info about buffer's location, size and ID. An ID field is used to identify a
- * buffer when it's returned with data via RXD Fifo (see below)
- * 2) RX Data Fifo - RXD - holds descriptors of full buffers. This Fifo is
- * filled by HW and is readen by SW. Each descriptor holds status and ID.
- * HW pops descriptor from RXF Fifo, stores ID, fills buffer with incoming data,
- * via dma moves it into host memory, builds new RXD descriptor with same ID,
- * pushes it into RXD Fifo and raises interrupt to indicate new RX data.
- *
- * Current NIC configuration (registers + firmware) makes NIC use 2 RXF Fifos.
- * One holds 1.5K packets and another - 26K packets. Depending on incoming
- * packet size, HW desides on a RXF Fifo to pop buffer from. When packet is
- * filled with data, HW builds new RXD descriptor for it and push it into single
- * RXD Fifo.
- *
- * RX SW Data Structures
- * ~~~~~~~~~~~~~~~~~~~~~
- * skb db - used to keep track of all skbs owned by SW and their dma addresses.
- * For RX case, ownership lasts from allocating new empty skb for RXF until
- * accepting full skb from RXD and passing it to OS. Each RXF Fifo has its own
- * skb db. Implemented as array with bitmask.
- * fifo - keeps info about fifo's size and location, relevant HW registers,
- * usage and skb db. Each RXD and RXF Fifo has its own fifo structure.
- * Implemented as simple struct.
- *
- * RX SW Execution Flow
- * ~~~~~~~~~~~~~~~~~~~~
- * Upon initialization (ifconfig up) driver creates RX fifos and initializes
- * relevant registers. At the end of init phase, driver enables interrupts.
- * NIC sees that there is no RXF buffers and raises
- * RD_INTR interrupt, isr fills skbs and Rx begins.
- * Driver has two receive operation modes:
- * NAPI - interrupt-driven mixed with polling
- * interrupt-driven only
- *
- * Interrupt-driven only flow is following. When buffer is ready, HW raises
- * interrupt and isr is called. isr collects all available packets
- * (bdx_rx_receive), refills skbs (bdx_rx_alloc_skbs) and exit.
-
- * Rx buffer allocation note
- * ~~~~~~~~~~~~~~~~~~~~~~~~~
- * Driver cares to feed such amount of RxF descriptors that respective amount of
- * RxD descriptors can not fill entire RxD fifo. The main reason is lack of
- * overflow check in Bordeaux for RxD fifo free/used size.
- * FIXME: this is NOT fully implemented, more work should be done
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "tehuti.h"
-
-static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = {
- {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x1FC9, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x1FC9, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0}
-};
-
-MODULE_DEVICE_TABLE(pci, bdx_pci_tbl);
-
-/* Definitions needed by ISR or NAPI functions */
-static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f);
-static void bdx_tx_cleanup(struct bdx_priv *priv);
-static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget);
-
-/* Definitions needed by FW loading */
-static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size);
-
-/* Definitions needed by hw_start */
-static int bdx_tx_init(struct bdx_priv *priv);
-static int bdx_rx_init(struct bdx_priv *priv);
-
-/* Definitions needed by bdx_close */
-static void bdx_rx_free(struct bdx_priv *priv);
-static void bdx_tx_free(struct bdx_priv *priv);
-
-/* Definitions needed by bdx_probe */
-static void bdx_set_ethtool_ops(struct net_device *netdev);
-
-/*************************************************************************
- * Print Info *
- *************************************************************************/
-
-static void print_hw_id(struct pci_dev *pdev)
-{
- struct pci_nic *nic = pci_get_drvdata(pdev);
- u16 pci_link_status = 0;
- u16 pci_ctrl = 0;
-
- pci_read_config_word(pdev, PCI_LINK_STATUS_REG, &pci_link_status);
- pci_read_config_word(pdev, PCI_DEV_CTRL_REG, &pci_ctrl);
-
- pr_info("%s%s\n", BDX_NIC_NAME,
- nic->port_num == 1 ? "" : ", 2-Port");
- pr_info("srom 0x%x fpga %d build %u lane# %d max_pl 0x%x mrrs 0x%x\n",
- readl(nic->regs + SROM_VER), readl(nic->regs + FPGA_VER) & 0xFFF,
- readl(nic->regs + FPGA_SEED),
- GET_LINK_STATUS_LANES(pci_link_status),
- GET_DEV_CTRL_MAXPL(pci_ctrl), GET_DEV_CTRL_MRRS(pci_ctrl));
-}
-
-static void print_fw_id(struct pci_nic *nic)
-{
- pr_info("fw 0x%x\n", readl(nic->regs + FW_VER));
-}
-
-static void print_eth_id(struct net_device *ndev)
-{
- netdev_info(ndev, "%s, Port %c\n",
- BDX_NIC_NAME, (ndev->if_port == 0) ? 'A' : 'B');
-
-}
-
-/*************************************************************************
- * Code *
- *************************************************************************/
-
-#define bdx_enable_interrupts(priv) \
- do { WRITE_REG(priv, regIMR, IR_RUN); } while (0)
-#define bdx_disable_interrupts(priv) \
- do { WRITE_REG(priv, regIMR, 0); } while (0)
-
-/* bdx_fifo_init
- * create TX/RX descriptor fifo for host-NIC communication.
- * 1K extra space is allocated at the end of the fifo to simplify
- * processing of descriptors that wraps around fifo's end
- * @priv - NIC private structure
- * @f - fifo to initialize
- * @fsz_type - fifo size type: 0-4KB, 1-8KB, 2-16KB, 3-32KB
- * @reg_XXX - offsets of registers relative to base address
- *
- * Returns 0 on success, negative value on failure
- *
- */
-static int
-bdx_fifo_init(struct bdx_priv *priv, struct fifo *f, int fsz_type,
- u16 reg_CFG0, u16 reg_CFG1, u16 reg_RPTR, u16 reg_WPTR)
-{
- u16 memsz = FIFO_SIZE * (1 << fsz_type);
-
- memset(f, 0, sizeof(struct fifo));
- /* pci_alloc_consistent gives us 4k-aligned memory */
- f->va = pci_alloc_consistent(priv->pdev,
- memsz + FIFO_EXTRA_SPACE, &f->da);
- if (!f->va) {
- pr_err("pci_alloc_consistent failed\n");
- RET(-ENOMEM);
- }
- f->reg_CFG0 = reg_CFG0;
- f->reg_CFG1 = reg_CFG1;
- f->reg_RPTR = reg_RPTR;
- f->reg_WPTR = reg_WPTR;
- f->rptr = 0;
- f->wptr = 0;
- f->memsz = memsz;
- f->size_mask = memsz - 1;
- WRITE_REG(priv, reg_CFG0, (u32) ((f->da & TX_RX_CFG0_BASE) | fsz_type));
- WRITE_REG(priv, reg_CFG1, H32_64(f->da));
-
- RET(0);
-}
-
-/* bdx_fifo_free - free all resources used by fifo
- * @priv - NIC private structure
- * @f - fifo to release
- */
-static void bdx_fifo_free(struct bdx_priv *priv, struct fifo *f)
-{
- ENTER;
- if (f->va) {
- pci_free_consistent(priv->pdev,
- f->memsz + FIFO_EXTRA_SPACE, f->va, f->da);
- f->va = NULL;
- }
- RET();
-}
-
-/*
- * bdx_link_changed - notifies OS about hw link state.
- * @bdx_priv - hw adapter structure
- */
-static void bdx_link_changed(struct bdx_priv *priv)
-{
- u32 link = READ_REG(priv, regMAC_LNK_STAT) & MAC_LINK_STAT;
-
- if (!link) {
- if (netif_carrier_ok(priv->ndev)) {
- netif_stop_queue(priv->ndev);
- netif_carrier_off(priv->ndev);
- netdev_err(priv->ndev, "Link Down\n");
- }
- } else {
- if (!netif_carrier_ok(priv->ndev)) {
- netif_wake_queue(priv->ndev);
- netif_carrier_on(priv->ndev);
- netdev_err(priv->ndev, "Link Up\n");
- }
- }
-}
-
-static void bdx_isr_extra(struct bdx_priv *priv, u32 isr)
-{
- if (isr & IR_RX_FREE_0) {
- bdx_rx_alloc_skbs(priv, &priv->rxf_fifo0);
- DBG("RX_FREE_0\n");
- }
-
- if (isr & IR_LNKCHG0)
- bdx_link_changed(priv);
-
- if (isr & IR_PCIE_LINK)
- netdev_err(priv->ndev, "PCI-E Link Fault\n");
-
- if (isr & IR_PCIE_TOUT)
- netdev_err(priv->ndev, "PCI-E Time Out\n");
-
-}
-
-/* bdx_isr - Interrupt Service Routine for Bordeaux NIC
- * @irq - interrupt number
- * @ndev - network device
- * @regs - CPU registers
- *
- * Return IRQ_NONE if it was not our interrupt, IRQ_HANDLED - otherwise
- *
- * It reads ISR register to know interrupt reasons, and proceed them one by one.
- * Reasons of interest are:
- * RX_DESC - new packet has arrived and RXD fifo holds its descriptor
- * RX_FREE - number of free Rx buffers in RXF fifo gets low
- * TX_FREE - packet was transmited and RXF fifo holds its descriptor
- */
-
-static irqreturn_t bdx_isr_napi(int irq, void *dev)
-{
- struct net_device *ndev = dev;
- struct bdx_priv *priv = netdev_priv(ndev);
- u32 isr;
-
- ENTER;
- isr = (READ_REG(priv, regISR) & IR_RUN);
- if (unlikely(!isr)) {
- bdx_enable_interrupts(priv);
- return IRQ_NONE; /* Not our interrupt */
- }
-
- if (isr & IR_EXTRA)
- bdx_isr_extra(priv, isr);
-
- if (isr & (IR_RX_DESC_0 | IR_TX_FREE_0)) {
- if (likely(napi_schedule_prep(&priv->napi))) {
- __napi_schedule(&priv->napi);
- RET(IRQ_HANDLED);
- } else {
- /* NOTE: we get here if intr has slipped into window
- * between these lines in bdx_poll:
- * bdx_enable_interrupts(priv);
- * return 0;
- * currently intrs are disabled (since we read ISR),
- * and we have failed to register next poll.
- * so we read the regs to trigger chip
- * and allow further interupts. */
- READ_REG(priv, regTXF_WPTR_0);
- READ_REG(priv, regRXD_WPTR_0);
- }
- }
-
- bdx_enable_interrupts(priv);
- RET(IRQ_HANDLED);
-}
-
-static int bdx_poll(struct napi_struct *napi, int budget)
-{
- struct bdx_priv *priv = container_of(napi, struct bdx_priv, napi);
- int work_done;
-
- ENTER;
- bdx_tx_cleanup(priv);
- work_done = bdx_rx_receive(priv, &priv->rxd_fifo0, budget);
- if ((work_done < budget) ||
- (priv->napi_stop++ >= 30)) {
- DBG("rx poll is done. backing to isr-driven\n");
-
- /* from time to time we exit to let NAPI layer release
- * device lock and allow waiting tasks (eg rmmod) to advance) */
- priv->napi_stop = 0;
-
- napi_complete(napi);
- bdx_enable_interrupts(priv);
- }
- return work_done;
-}
-
-/* bdx_fw_load - loads firmware to NIC
- * @priv - NIC private structure
- * Firmware is loaded via TXD fifo, so it must be initialized first.
- * Firware must be loaded once per NIC not per PCI device provided by NIC (NIC
- * can have few of them). So all drivers use semaphore register to choose one
- * that will actually load FW to NIC.
- */
-
-static int bdx_fw_load(struct bdx_priv *priv)
-{
- const struct firmware *fw = NULL;
- int master, i;
- int rc;
-
- ENTER;
- master = READ_REG(priv, regINIT_SEMAPHORE);
- if (!READ_REG(priv, regINIT_STATUS) && master) {
- rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev);
- if (rc)
- goto out;
- bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size);
- mdelay(100);
- }
- for (i = 0; i < 200; i++) {
- if (READ_REG(priv, regINIT_STATUS)) {
- rc = 0;
- goto out;
- }
- mdelay(2);
- }
- rc = -EIO;
-out:
- if (master)
- WRITE_REG(priv, regINIT_SEMAPHORE, 1);
- if (fw)
- release_firmware(fw);
-
- if (rc) {
- netdev_err(priv->ndev, "firmware loading failed\n");
- if (rc == -EIO)
- DBG("VPC = 0x%x VIC = 0x%x INIT_STATUS = 0x%x i=%d\n",
- READ_REG(priv, regVPC),
- READ_REG(priv, regVIC),
- READ_REG(priv, regINIT_STATUS), i);
- RET(rc);
- } else {
- DBG("%s: firmware loading success\n", priv->ndev->name);
- RET(0);
- }
-}
-
-static void bdx_restore_mac(struct net_device *ndev, struct bdx_priv *priv)
-{
- u32 val;
-
- ENTER;
- DBG("mac0=%x mac1=%x mac2=%x\n",
- READ_REG(priv, regUNC_MAC0_A),
- READ_REG(priv, regUNC_MAC1_A), READ_REG(priv, regUNC_MAC2_A));
-
- val = (ndev->dev_addr[0] << 8) | (ndev->dev_addr[1]);
- WRITE_REG(priv, regUNC_MAC2_A, val);
- val = (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]);
- WRITE_REG(priv, regUNC_MAC1_A, val);
- val = (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]);
- WRITE_REG(priv, regUNC_MAC0_A, val);
-
- DBG("mac0=%x mac1=%x mac2=%x\n",
- READ_REG(priv, regUNC_MAC0_A),
- READ_REG(priv, regUNC_MAC1_A), READ_REG(priv, regUNC_MAC2_A));
- RET();
-}
-
-/* bdx_hw_start - inits registers and starts HW's Rx and Tx engines
- * @priv - NIC private structure
- */
-static int bdx_hw_start(struct bdx_priv *priv)
-{
- int rc = -EIO;
- struct net_device *ndev = priv->ndev;
-
- ENTER;
- bdx_link_changed(priv);
-
- /* 10G overall max length (vlan, eth&ip header, ip payload, crc) */
- WRITE_REG(priv, regFRM_LENGTH, 0X3FE0);
- WRITE_REG(priv, regPAUSE_QUANT, 0x96);
- WRITE_REG(priv, regRX_FIFO_SECTION, 0x800010);
- WRITE_REG(priv, regTX_FIFO_SECTION, 0xE00010);
- WRITE_REG(priv, regRX_FULLNESS, 0);
- WRITE_REG(priv, regTX_FULLNESS, 0);
- WRITE_REG(priv, regCTRLST,
- regCTRLST_BASE | regCTRLST_RX_ENA | regCTRLST_TX_ENA);
-
- WRITE_REG(priv, regVGLB, 0);
- WRITE_REG(priv, regMAX_FRAME_A,
- priv->rxf_fifo0.m.pktsz & MAX_FRAME_AB_VAL);
-
- DBG("RDINTCM=%08x\n", priv->rdintcm); /*NOTE: test script uses this */
- WRITE_REG(priv, regRDINTCM0, priv->rdintcm);
- WRITE_REG(priv, regRDINTCM2, 0); /*cpu_to_le32(rcm.val)); */
-
- DBG("TDINTCM=%08x\n", priv->tdintcm); /*NOTE: test script uses this */
- WRITE_REG(priv, regTDINTCM0, priv->tdintcm); /* old val = 0x300064 */
-
- /* Enable timer interrupt once in 2 secs. */
- /*WRITE_REG(priv, regGTMR0, ((GTMR_SEC * 2) & GTMR_DATA)); */
- bdx_restore_mac(priv->ndev, priv);
-
- WRITE_REG(priv, regGMAC_RXF_A, GMAC_RX_FILTER_OSEN |
- GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB);
-
-#define BDX_IRQ_TYPE ((priv->nic->irq_type == IRQ_MSI) ? 0 : IRQF_SHARED)
-
- rc = request_irq(priv->pdev->irq, bdx_isr_napi, BDX_IRQ_TYPE,
- ndev->name, ndev);
- if (rc)
- goto err_irq;
- bdx_enable_interrupts(priv);
-
- RET(0);
-
-err_irq:
- RET(rc);
-}
-
-static void bdx_hw_stop(struct bdx_priv *priv)
-{
- ENTER;
- bdx_disable_interrupts(priv);
- free_irq(priv->pdev->irq, priv->ndev);
-
- netif_carrier_off(priv->ndev);
- netif_stop_queue(priv->ndev);
-
- RET();
-}
-
-static int bdx_hw_reset_direct(void __iomem *regs)
-{
- u32 val, i;
- ENTER;
-
- /* reset sequences: read, write 1, read, write 0 */
- val = readl(regs + regCLKPLL);
- writel((val | CLKPLL_SFTRST) + 0x8, regs + regCLKPLL);
- udelay(50);
- val = readl(regs + regCLKPLL);
- writel(val & ~CLKPLL_SFTRST, regs + regCLKPLL);
-
- /* check that the PLLs are locked and reset ended */
- for (i = 0; i < 70; i++, mdelay(10))
- if ((readl(regs + regCLKPLL) & CLKPLL_LKD) == CLKPLL_LKD) {
- /* do any PCI-E read transaction */
- readl(regs + regRXD_CFG0_0);
- return 0;
- }
- pr_err("HW reset failed\n");
- return 1; /* failure */
-}
-
-static int bdx_hw_reset(struct bdx_priv *priv)
-{
- u32 val, i;
- ENTER;
-
- if (priv->port == 0) {
- /* reset sequences: read, write 1, read, write 0 */
- val = READ_REG(priv, regCLKPLL);
- WRITE_REG(priv, regCLKPLL, (val | CLKPLL_SFTRST) + 0x8);
- udelay(50);
- val = READ_REG(priv, regCLKPLL);
- WRITE_REG(priv, regCLKPLL, val & ~CLKPLL_SFTRST);
- }
- /* check that the PLLs are locked and reset ended */
- for (i = 0; i < 70; i++, mdelay(10))
- if ((READ_REG(priv, regCLKPLL) & CLKPLL_LKD) == CLKPLL_LKD) {
- /* do any PCI-E read transaction */
- READ_REG(priv, regRXD_CFG0_0);
- return 0;
- }
- pr_err("HW reset failed\n");
- return 1; /* failure */
-}
-
-static int bdx_sw_reset(struct bdx_priv *priv)
-{
- int i;
-
- ENTER;
- /* 1. load MAC (obsolete) */
- /* 2. disable Rx (and Tx) */
- WRITE_REG(priv, regGMAC_RXF_A, 0);
- mdelay(100);
- /* 3. disable port */
- WRITE_REG(priv, regDIS_PORT, 1);
- /* 4. disable queue */
- WRITE_REG(priv, regDIS_QU, 1);
- /* 5. wait until hw is disabled */
- for (i = 0; i < 50; i++) {
- if (READ_REG(priv, regRST_PORT) & 1)
- break;
- mdelay(10);
- }
- if (i == 50)
- netdev_err(priv->ndev, "SW reset timeout. continuing anyway\n");
-
- /* 6. disable intrs */
- WRITE_REG(priv, regRDINTCM0, 0);
- WRITE_REG(priv, regTDINTCM0, 0);
- WRITE_REG(priv, regIMR, 0);
- READ_REG(priv, regISR);
-
- /* 7. reset queue */
- WRITE_REG(priv, regRST_QU, 1);
- /* 8. reset port */
- WRITE_REG(priv, regRST_PORT, 1);
- /* 9. zero all read and write pointers */
- for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10)
- DBG("%x = %x\n", i, READ_REG(priv, i) & TXF_WPTR_WR_PTR);
- for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10)
- WRITE_REG(priv, i, 0);
- /* 10. unseet port disable */
- WRITE_REG(priv, regDIS_PORT, 0);
- /* 11. unset queue disable */
- WRITE_REG(priv, regDIS_QU, 0);
- /* 12. unset queue reset */
- WRITE_REG(priv, regRST_QU, 0);
- /* 13. unset port reset */
- WRITE_REG(priv, regRST_PORT, 0);
- /* 14. enable Rx */
- /* skiped. will be done later */
- /* 15. save MAC (obsolete) */
- for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10)
- DBG("%x = %x\n", i, READ_REG(priv, i) & TXF_WPTR_WR_PTR);
-
- RET(0);
-}
-
-/* bdx_reset - performs right type of reset depending on hw type */
-static int bdx_reset(struct bdx_priv *priv)
-{
- ENTER;
- RET((priv->pdev->device == 0x3009)
- ? bdx_hw_reset(priv)
- : bdx_sw_reset(priv));
-}
-
-/**
- * bdx_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 int bdx_close(struct net_device *ndev)
-{
- struct bdx_priv *priv = NULL;
-
- ENTER;
- priv = netdev_priv(ndev);
-
- napi_disable(&priv->napi);
-
- bdx_reset(priv);
- bdx_hw_stop(priv);
- bdx_rx_free(priv);
- bdx_tx_free(priv);
- RET(0);
-}
-
-/**
- * bdx_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 bdx_open(struct net_device *ndev)
-{
- struct bdx_priv *priv;
- int rc;
-
- ENTER;
- priv = netdev_priv(ndev);
- bdx_reset(priv);
- if (netif_running(ndev))
- netif_stop_queue(priv->ndev);
-
- if ((rc = bdx_tx_init(priv)) ||
- (rc = bdx_rx_init(priv)) ||
- (rc = bdx_fw_load(priv)))
- goto err;
-
- bdx_rx_alloc_skbs(priv, &priv->rxf_fifo0);
-
- rc = bdx_hw_start(priv);
- if (rc)
- goto err;
-
- napi_enable(&priv->napi);
-
- print_fw_id(priv->nic);
-
- RET(0);
-
-err:
- bdx_close(ndev);
- RET(rc);
-}
-
-static int bdx_range_check(struct bdx_priv *priv, u32 offset)
-{
- return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
- -EINVAL : 0;
-}
-
-static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
- u32 data[3];
- int error;
-
- ENTER;
-
- DBG("jiffies=%ld cmd=%d\n", jiffies, cmd);
- if (cmd != SIOCDEVPRIVATE) {
- error = copy_from_user(data, ifr->ifr_data, sizeof(data));
- if (error) {
- pr_err("can't copy from user\n");
- RET(-EFAULT);
- }
- DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
- }
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
- switch (data[0]) {
-
- case BDX_OP_READ:
- error = bdx_range_check(priv, data[1]);
- if (error < 0)
- return error;
- data[2] = READ_REG(priv, data[1]);
- DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2],
- data[2]);
- error = copy_to_user(ifr->ifr_data, data, sizeof(data));
- if (error)
- RET(-EFAULT);
- break;
-
- case BDX_OP_WRITE:
- error = bdx_range_check(priv, data[1]);
- if (error < 0)
- return error;
- WRITE_REG(priv, data[1], data[2]);
- DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]);
- break;
-
- default:
- RET(-EOPNOTSUPP);
- }
- return 0;
-}
-
-static int bdx_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
-{
- ENTER;
- if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
- RET(bdx_ioctl_priv(ndev, ifr, cmd));
- else
- RET(-EOPNOTSUPP);
-}
-
-/*
- * __bdx_vlan_rx_vid - private helper for adding/killing VLAN vid
- * by passing VLAN filter table to hardware
- * @ndev network device
- * @vid VLAN vid
- * @op add or kill operation
- */
-static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
- u32 reg, bit, val;
-
- ENTER;
- DBG2("vid=%d value=%d\n", (int)vid, enable);
- if (unlikely(vid >= 4096)) {
- pr_err("invalid VID: %u (> 4096)\n", vid);
- RET();
- }
- reg = regVLAN_0 + (vid / 32) * 4;
- bit = 1 << vid % 32;
- val = READ_REG(priv, reg);
- DBG2("reg=%x, val=%x, bit=%d\n", reg, val, bit);
- if (enable)
- val |= bit;
- else
- val &= ~bit;
- DBG2("new val %x\n", val);
- WRITE_REG(priv, reg, val);
- RET();
-}
-
-/*
- * bdx_vlan_rx_add_vid - kernel hook for adding VLAN vid to hw filtering table
- * @ndev network device
- * @vid VLAN vid to add
- */
-static void bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid)
-{
- __bdx_vlan_rx_vid(ndev, vid, 1);
-}
-
-/*
- * bdx_vlan_rx_kill_vid - kernel hook for killing VLAN vid in hw filtering table
- * @ndev network device
- * @vid VLAN vid to kill
- */
-static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
-{
- __bdx_vlan_rx_vid(ndev, vid, 0);
-}
-
-/**
- * bdx_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- */
-static int bdx_change_mtu(struct net_device *ndev, int new_mtu)
-{
- ENTER;
-
- if (new_mtu == ndev->mtu)
- RET(0);
-
- /* enforce minimum frame size */
- if (new_mtu < ETH_ZLEN) {
- netdev_err(ndev, "mtu %d is less then minimal %d\n",
- new_mtu, ETH_ZLEN);
- RET(-EINVAL);
- }
-
- ndev->mtu = new_mtu;
- if (netif_running(ndev)) {
- bdx_close(ndev);
- bdx_open(ndev);
- }
- RET(0);
-}
-
-static void bdx_setmulti(struct net_device *ndev)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
-
- u32 rxf_val =
- GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB | GMAC_RX_FILTER_OSEN;
- int i;
-
- ENTER;
- /* IMF - imperfect (hash) rx multicat filter */
- /* PMF - perfect rx multicat filter */
-
- /* FIXME: RXE(OFF) */
- if (ndev->flags & IFF_PROMISC) {
- rxf_val |= GMAC_RX_FILTER_PRM;
- } else if (ndev->flags & IFF_ALLMULTI) {
- /* set IMF to accept all multicast frmaes */
- for (i = 0; i < MAC_MCST_HASH_NUM; i++)
- WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, ~0);
- } else if (!netdev_mc_empty(ndev)) {
- u8 hash;
- struct netdev_hw_addr *ha;
- u32 reg, val;
-
- /* set IMF to deny all multicast frames */
- for (i = 0; i < MAC_MCST_HASH_NUM; i++)
- WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, 0);
- /* set PMF to deny all multicast frames */
- for (i = 0; i < MAC_MCST_NUM; i++) {
- WRITE_REG(priv, regRX_MAC_MCST0 + i * 8, 0);
- WRITE_REG(priv, regRX_MAC_MCST1 + i * 8, 0);
- }
-
- /* use PMF to accept first MAC_MCST_NUM (15) addresses */
- /* TBD: sort addresses and write them in ascending order
- * into RX_MAC_MCST regs. we skip this phase now and accept ALL
- * multicast frames throu IMF */
- /* accept the rest of addresses throu IMF */
- netdev_for_each_mc_addr(ha, ndev) {
- hash = 0;
- for (i = 0; i < ETH_ALEN; i++)
- hash ^= ha->addr[i];
- reg = regRX_MCST_HASH0 + ((hash >> 5) << 2);
- val = READ_REG(priv, reg);
- val |= (1 << (hash % 32));
- WRITE_REG(priv, reg, val);
- }
-
- } else {
- DBG("only own mac %d\n", netdev_mc_count(ndev));
- rxf_val |= GMAC_RX_FILTER_AB;
- }
- WRITE_REG(priv, regGMAC_RXF_A, rxf_val);
- /* enable RX */
- /* FIXME: RXE(ON) */
- RET();
-}
-
-static int bdx_set_mac(struct net_device *ndev, void *p)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
- struct sockaddr *addr = p;
-
- ENTER;
- /*
- if (netif_running(dev))
- return -EBUSY
- */
- memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
- bdx_restore_mac(ndev, priv);
- RET(0);
-}
-
-static int bdx_read_mac(struct bdx_priv *priv)
-{
- u16 macAddress[3], i;
- ENTER;
-
- macAddress[2] = READ_REG(priv, regUNC_MAC0_A);
- macAddress[2] = READ_REG(priv, regUNC_MAC0_A);
- macAddress[1] = READ_REG(priv, regUNC_MAC1_A);
- macAddress[1] = READ_REG(priv, regUNC_MAC1_A);
- macAddress[0] = READ_REG(priv, regUNC_MAC2_A);
- macAddress[0] = READ_REG(priv, regUNC_MAC2_A);
- for (i = 0; i < 3; i++) {
- priv->ndev->dev_addr[i * 2 + 1] = macAddress[i];
- priv->ndev->dev_addr[i * 2] = macAddress[i] >> 8;
- }
- RET(0);
-}
-
-static u64 bdx_read_l2stat(struct bdx_priv *priv, int reg)
-{
- u64 val;
-
- val = READ_REG(priv, reg);
- val |= ((u64) READ_REG(priv, reg + 8)) << 32;
- return val;
-}
-
-/*Do the statistics-update work*/
-static void bdx_update_stats(struct bdx_priv *priv)
-{
- struct bdx_stats *stats = &priv->hw_stats;
- u64 *stats_vector = (u64 *) stats;
- int i;
- int addr;
-
- /*Fill HW structure */
- addr = 0x7200;
- /*First 12 statistics - 0x7200 - 0x72B0 */
- for (i = 0; i < 12; i++) {
- stats_vector[i] = bdx_read_l2stat(priv, addr);
- addr += 0x10;
- }
- BDX_ASSERT(addr != 0x72C0);
- /* 0x72C0-0x72E0 RSRV */
- addr = 0x72F0;
- for (; i < 16; i++) {
- stats_vector[i] = bdx_read_l2stat(priv, addr);
- addr += 0x10;
- }
- BDX_ASSERT(addr != 0x7330);
- /* 0x7330-0x7360 RSRV */
- addr = 0x7370;
- for (; i < 19; i++) {
- stats_vector[i] = bdx_read_l2stat(priv, addr);
- addr += 0x10;
- }
- BDX_ASSERT(addr != 0x73A0);
- /* 0x73A0-0x73B0 RSRV */
- addr = 0x73C0;
- for (; i < 23; i++) {
- stats_vector[i] = bdx_read_l2stat(priv, addr);
- addr += 0x10;
- }
- BDX_ASSERT(addr != 0x7400);
- BDX_ASSERT((sizeof(struct bdx_stats) / sizeof(u64)) != i);
-}
-
-static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len,
- u16 rxd_vlan);
-static void print_rxfd(struct rxf_desc *rxfd);
-
-/*************************************************************************
- * Rx DB *
- *************************************************************************/
-
-static void bdx_rxdb_destroy(struct rxdb *db)
-{
- vfree(db);
-}
-
-static struct rxdb *bdx_rxdb_create(int nelem)
-{
- struct rxdb *db;
- int i;
-
- db = vmalloc(sizeof(struct rxdb)
- + (nelem * sizeof(int))
- + (nelem * sizeof(struct rx_map)));
- if (likely(db != NULL)) {
- db->stack = (int *)(db + 1);
- db->elems = (void *)(db->stack + nelem);
- db->nelem = nelem;
- db->top = nelem;
- for (i = 0; i < nelem; i++)
- db->stack[i] = nelem - i - 1; /* to make first allocs
- close to db struct*/
- }
-
- return db;
-}
-
-static inline int bdx_rxdb_alloc_elem(struct rxdb *db)
-{
- BDX_ASSERT(db->top <= 0);
- return db->stack[--(db->top)];
-}
-
-static inline void *bdx_rxdb_addr_elem(struct rxdb *db, int n)
-{
- BDX_ASSERT((n < 0) || (n >= db->nelem));
- return db->elems + n;
-}
-
-static inline int bdx_rxdb_available(struct rxdb *db)
-{
- return db->top;
-}
-
-static inline void bdx_rxdb_free_elem(struct rxdb *db, int n)
-{
- BDX_ASSERT((n >= db->nelem) || (n < 0));
- db->stack[(db->top)++] = n;
-}
-
-/*************************************************************************
- * Rx Init *
- *************************************************************************/
-
-/* bdx_rx_init - initialize RX all related HW and SW resources
- * @priv - NIC private structure
- *
- * Returns 0 on success, negative value on failure
- *
- * It creates rxf and rxd fifos, update relevant HW registers, preallocate
- * skb for rx. It assumes that Rx is desabled in HW
- * funcs are grouped for better cache usage
- *
- * RxD fifo is smaller than RxF fifo by design. Upon high load, RxD will be
- * filled and packets will be dropped by nic without getting into host or
- * cousing interrupt. Anyway, in that condition, host has no chance to process
- * all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles
- */
-
-/* TBD: ensure proper packet size */
-
-static int bdx_rx_init(struct bdx_priv *priv)
-{
- ENTER;
-
- if (bdx_fifo_init(priv, &priv->rxd_fifo0.m, priv->rxd_size,
- regRXD_CFG0_0, regRXD_CFG1_0,
- regRXD_RPTR_0, regRXD_WPTR_0))
- goto err_mem;
- if (bdx_fifo_init(priv, &priv->rxf_fifo0.m, priv->rxf_size,
- regRXF_CFG0_0, regRXF_CFG1_0,
- regRXF_RPTR_0, regRXF_WPTR_0))
- goto err_mem;
- priv->rxdb = bdx_rxdb_create(priv->rxf_fifo0.m.memsz /
- sizeof(struct rxf_desc));
- if (!priv->rxdb)
- goto err_mem;
-
- priv->rxf_fifo0.m.pktsz = priv->ndev->mtu + VLAN_ETH_HLEN;
- return 0;
-
-err_mem:
- netdev_err(priv->ndev, "Rx init failed\n");
- return -ENOMEM;
-}
-
-/* bdx_rx_free_skbs - frees and unmaps all skbs allocated for the fifo
- * @priv - NIC private structure
- * @f - RXF fifo
- */
-static void bdx_rx_free_skbs(struct bdx_priv *priv, struct rxf_fifo *f)
-{
- struct rx_map *dm;
- struct rxdb *db = priv->rxdb;
- u16 i;
-
- ENTER;
- DBG("total=%d free=%d busy=%d\n", db->nelem, bdx_rxdb_available(db),
- db->nelem - bdx_rxdb_available(db));
- while (bdx_rxdb_available(db) > 0) {
- i = bdx_rxdb_alloc_elem(db);
- dm = bdx_rxdb_addr_elem(db, i);
- dm->dma = 0;
- }
- for (i = 0; i < db->nelem; i++) {
- dm = bdx_rxdb_addr_elem(db, i);
- if (dm->dma) {
- pci_unmap_single(priv->pdev,
- dm->dma, f->m.pktsz,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb(dm->skb);
- }
- }
-}
-
-/* bdx_rx_free - release all Rx resources
- * @priv - NIC private structure
- * It assumes that Rx is desabled in HW
- */
-static void bdx_rx_free(struct bdx_priv *priv)
-{
- ENTER;
- if (priv->rxdb) {
- bdx_rx_free_skbs(priv, &priv->rxf_fifo0);
- bdx_rxdb_destroy(priv->rxdb);
- priv->rxdb = NULL;
- }
- bdx_fifo_free(priv, &priv->rxf_fifo0.m);
- bdx_fifo_free(priv, &priv->rxd_fifo0.m);
-
- RET();
-}
-
-/*************************************************************************
- * Rx Engine *
- *************************************************************************/
-
-/* bdx_rx_alloc_skbs - fill rxf fifo with new skbs
- * @priv - nic's private structure
- * @f - RXF fifo that needs skbs
- * It allocates skbs, build rxf descs and push it (rxf descr) into rxf fifo.
- * skb's virtual and physical addresses are stored in skb db.
- * To calculate free space, func uses cached values of RPTR and WPTR
- * When needed, it also updates RPTR and WPTR.
- */
-
-/* TBD: do not update WPTR if no desc were written */
-
-static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f)
-{
- struct sk_buff *skb;
- struct rxf_desc *rxfd;
- struct rx_map *dm;
- int dno, delta, idx;
- struct rxdb *db = priv->rxdb;
-
- ENTER;
- dno = bdx_rxdb_available(db) - 1;
- while (dno > 0) {
- skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN);
- if (!skb) {
- pr_err("NO MEM: dev_alloc_skb failed\n");
- break;
- }
- skb->