/* bnx2.c: Broadcom NX2 network driver.
*
- * Copyright (c) 2004-2009 Broadcom Corporation
+ * Copyright (c) 2004-2010 Broadcom Corporation
*
* 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
* Written by: Michael Chan (mchan@broadcom.com)
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/cache.h>
#include <linux/firmware.h>
#include <linux/log2.h>
-#include <linux/list.h>
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
-#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "2.0.3"
-#define DRV_MODULE_RELDATE "Dec 03, 2009"
-#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j3.fw"
+#define DRV_MODULE_VERSION "2.0.8"
+#define DRV_MODULE_RELDATE "Feb 15, 2010"
+#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j6.fw"
#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-5.0.0.j3.fw"
-#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j3.fw"
-#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw"
-#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j3.fw"
+#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j9.fw"
+#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw"
+#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j10.fw"
#define RUN_AT(x) (jiffies + (x))
{
if (bp->link_up) {
netif_carrier_on(bp->dev);
- printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name,
- bnx2_xceiver_str(bp));
-
- printk("%d Mbps ", bp->line_speed);
-
- if (bp->duplex == DUPLEX_FULL)
- printk("full duplex");
- else
- printk("half duplex");
+ netdev_info(bp->dev, "NIC %s Link is Up, %d Mbps %s duplex",
+ bnx2_xceiver_str(bp),
+ bp->line_speed,
+ bp->duplex == DUPLEX_FULL ? "full" : "half");
if (bp->flow_ctrl) {
if (bp->flow_ctrl & FLOW_CTRL_RX) {
- printk(", receive ");
+ pr_cont(", receive ");
if (bp->flow_ctrl & FLOW_CTRL_TX)
- printk("& transmit ");
+ pr_cont("& transmit ");
}
else {
- printk(", transmit ");
+ pr_cont(", transmit ");
}
- printk("flow control ON");
+ pr_cont("flow control ON");
}
- printk("\n");
- }
- else {
+ pr_cont("\n");
+ } else {
netif_carrier_off(bp->dev);
- printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name,
- bnx2_xceiver_str(bp));
+ netdev_err(bp->dev, "NIC %s Link is Down\n",
+ bnx2_xceiver_str(bp));
}
bnx2_report_fw_link(bp);
if (lo_water >= bp->rx_ring_size)
lo_water = 0;
- hi_water = bp->rx_ring_size / 4;
+ hi_water = min_t(int, bp->rx_ring_size / 4, lo_water + 16);
if (hi_water <= lo_water)
lo_water = 0;
/* If we timed out, inform the firmware that this is the case. */
if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
if (!silent)
- printk(KERN_ERR PFX "fw sync timeout, reset code = "
- "%x\n", msg_data);
+ pr_err("fw sync timeout, reset code = %x\n", msg_data);
msg_data &= ~BNX2_DRV_MSG_CODE;
msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
if (good_mbuf == NULL) {
- printk(KERN_ERR PFX "Failed to allocate memory in "
- "bnx2_alloc_bad_rbuf\n");
+ pr_err("Failed to allocate memory in %s\n", __func__);
return -ENOMEM;
}
memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS);
- for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist = mclist->next) {
-
+ netdev_for_each_mc_addr(mclist, dev) {
crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr);
bit = crc & 0xff;
regidx = (bit & 0xe0) >> 5;
sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
}
- if (dev->uc.count > BNX2_MAX_UNICAST_ADDRESSES) {
+ if (netdev_uc_count(dev) > BNX2_MAX_UNICAST_ADDRESSES) {
rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
BNX2_RPM_SORT_USER0_PROM_VLAN;
} else if (!(dev->flags & IFF_PROMISC)) {
/* Add all entries into to the match filter list */
i = 0;
- list_for_each_entry(ha, &dev->uc.list, list) {
+ netdev_for_each_uc_addr(ha, dev) {
bnx2_set_mac_addr(bp, ha->addr,
i + BNX2_START_UNICAST_ADDRESS_INDEX);
sort_mode |= (1 <<
rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
if (rc) {
- printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n",
- mips_fw_file);
+ pr_err("Can't load firmware file \"%s\"\n", mips_fw_file);
return rc;
}
rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
if (rc) {
- printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n",
- rv2p_fw_file);
+ pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file);
return rc;
}
mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) ||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
- printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
- mips_fw_file);
+ pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file);
return -EINVAL;
}
if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
- printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
- rv2p_fw_file);
+ pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file);
return -EINVAL;
}
if (j == entry_count) {
bp->flash_info = NULL;
- printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n");
+ pr_alert("Unknown flash/EEPROM type\n");
return -ENODEV;
}
if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
- printk(KERN_ERR PFX "Chip reset did not complete\n");
+ pr_err("Chip reset did not complete\n");
return -EBUSY;
}
}
/* Make sure byte swapping is properly configured. */
val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
if (val != 0x01020304) {
- printk(KERN_ERR PFX "Chip not in correct endian mode\n");
+ pr_err("Chip not in correct endian mode\n");
return -ENODEV;
}
BNX2_HC_CONFIG_COLLECT_STATS;
}
- if (bp->irq_nvecs > 1) {
+ if (bp->flags & BNX2_FLAG_USING_MSIX) {
REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
BNX2_HC_MSIX_BIT_VECTOR_VAL);
ring_prod = prod = rxr->rx_pg_prod;
for (i = 0; i < bp->rx_pg_ring_size; i++) {
if (bnx2_alloc_rx_page(bp, rxr, ring_prod) < 0) {
- printk(KERN_WARNING PFX "%s: init'ed rx page ring %d "
- "with %d/%d pages only\n",
- bp->dev->name, ring_num, i, bp->rx_pg_ring_size);
+ netdev_warn(bp->dev, "init'ed rx page ring %d with %d/%d pages only\n",
+ ring_num, i, bp->rx_pg_ring_size);
break;
}
prod = NEXT_RX_BD(prod);
ring_prod = prod = rxr->rx_prod;
for (i = 0; i < bp->rx_ring_size; i++) {
if (bnx2_alloc_rx_skb(bp, rxr, ring_prod) < 0) {
- printk(KERN_WARNING PFX "%s: init'ed rx ring %d with "
- "%d/%d skbs only\n",
- bp->dev->name, ring_num, i, bp->rx_ring_size);
+ netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d skbs only\n",
+ ring_num, i, bp->rx_ring_size);
break;
}
prod = NEXT_RX_BD(prod);
* If MSI test fails, go back to INTx mode
*/
if (bnx2_test_intr(bp) != 0) {
- printk(KERN_WARNING PFX "%s: No interrupt was generated"
- " using MSI, switching to INTx mode. Please"
- " report this failure to the PCI maintainer"
- " and include system chipset information.\n",
- bp->dev->name);
+ netdev_warn(bp->dev, "No interrupt was generated using MSI, switching to INTx mode. Please report this failure to the PCI maintainer and include system chipset information.\n");
bnx2_disable_int(bp);
bnx2_free_irq(bp);
}
}
if (bp->flags & BNX2_FLAG_USING_MSI)
- printk(KERN_INFO PFX "%s: using MSI\n", dev->name);
+ netdev_info(dev, "using MSI\n");
else if (bp->flags & BNX2_FLAG_USING_MSIX)
- printk(KERN_INFO PFX "%s: using MSIX\n", dev->name);
+ netdev_info(dev, "using MSIX\n");
netif_tx_start_all_queues(dev);
{
struct net_device *dev = bp->dev;
- printk(KERN_ERR PFX "%s DEBUG: intr_sem[%x]\n", dev->name,
- atomic_read(&bp->intr_sem));
- printk(KERN_ERR PFX "%s DEBUG: EMAC_TX_STATUS[%08x] "
- "RPM_MGMT_PKT_CTRL[%08x]\n", dev->name,
- REG_RD(bp, BNX2_EMAC_TX_STATUS),
- REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
- printk(KERN_ERR PFX "%s DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
- dev->name, bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P0),
- bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P1));
- printk(KERN_ERR PFX "%s DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
- dev->name, REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
+ netdev_err(dev, "DEBUG: intr_sem[%x]\n", atomic_read(&bp->intr_sem));
+ netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] RPM_MGMT_PKT_CTRL[%08x]\n",
+ REG_RD(bp, BNX2_EMAC_TX_STATUS),
+ REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
+ netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
+ bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P0),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P1));
+ netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
+ REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
if (bp->flags & BNX2_FLAG_USING_MSIX)
- printk(KERN_ERR PFX "%s DEBUG: PBA[%08x]\n", dev->name,
- REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
+ netdev_err(dev, "DEBUG: PBA[%08x]\n",
+ REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
}
static void
if (unlikely(bnx2_tx_avail(bp, txr) <
(skb_shinfo(skb)->nr_frags + 1))) {
netif_tx_stop_queue(txq);
- printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
- dev->name);
+ netdev_err(dev, "BUG! Tx ring full when queue awake!\n");
return NETDEV_TX_BUSY;
}
u32 hi;
u64 lo;
- hi = *(temp_stats + i) + *(hw_stats + i);
- lo = *(temp_stats + i + 1) + *(hw_stats + i + 1);
+ hi = temp_stats[i] + hw_stats[i];
+ lo = (u64) temp_stats[i + 1] + (u64) hw_stats[i + 1];
if (lo > 0xffffffff)
hi++;
- *(temp_stats + i) = hi;
- *(temp_stats + i + 1) = lo & 0xffffffff;
+ temp_stats[i] = hi;
+ temp_stats[i + 1] = lo & 0xffffffff;
}
for ( ; i < sizeof(struct statistics_block) / 4; i++)
- *(temp_stats + i) = *(temp_stats + i) + *(hw_stats + i);
+ temp_stats[i] += hw_stats[i];
}
#define GET_64BIT_NET_STATS64(ctr) \
if (cmd->autoneg == AUTONEG_ENABLE) {
autoneg |= AUTONEG_SPEED;
- cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED;
-
- /* allow advertising 1 speed */
- if ((cmd->advertising == ADVERTISED_10baseT_Half) ||
- (cmd->advertising == ADVERTISED_10baseT_Full) ||
- (cmd->advertising == ADVERTISED_100baseT_Half) ||
- (cmd->advertising == ADVERTISED_100baseT_Full)) {
-
- if (cmd->port == PORT_FIBRE)
- goto err_out_unlock;
-
- advertising = cmd->advertising;
-
- } else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
- if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) ||
- (cmd->port == PORT_TP))
- goto err_out_unlock;
- } else if (cmd->advertising == ADVERTISED_1000baseT_Full)
- advertising = cmd->advertising;
- else if (cmd->advertising == ADVERTISED_1000baseT_Half)
- goto err_out_unlock;
- else {
- if (cmd->port == PORT_FIBRE)
- advertising = ETHTOOL_ALL_FIBRE_SPEED;
- else
+ advertising = cmd->advertising;
+ if (cmd->port == PORT_TP) {
+ advertising &= ETHTOOL_ALL_COPPER_SPEED;
+ if (!advertising)
advertising = ETHTOOL_ALL_COPPER_SPEED;
+ } else {
+ advertising &= ETHTOOL_ALL_FIBRE_SPEED;
+ if (!advertising)
+ advertising = ETHTOOL_ALL_FIBRE_SPEED;
}
advertising |= ADVERTISED_Autoneg;
}
dev_close(bp->dev);
return rc;
}
+#ifdef BCM_CNIC
+ mutex_lock(&bp->cnic_lock);
+ /* Let cnic know about the new status block. */
+ if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD)
+ bnx2_setup_cnic_irq_info(bp);
+ mutex_unlock(&bp->cnic_lock);
+#endif
bnx2_netif_start(bp);
}
return 0;
return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size));
}
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void
poll_bnx2(struct net_device *dev)
{
/* enable device (incl. PCI PM wakeup), and bus-mastering */
rc = pci_enable_device(pdev);
if (rc) {
- dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
+ dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
goto err_out;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
dev_err(&pdev->dev,
- "Cannot find PCI device base address, aborting.\n");
+ "Cannot find PCI device base address, aborting\n");
rc = -ENODEV;
goto err_out_disable;
}
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) {
- dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
goto err_out_disable;
}
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) {
dev_err(&pdev->dev,
- "Cannot find power management capability, aborting.\n");
+ "Cannot find power management capability, aborting\n");
rc = -EIO;
goto err_out_release;
}
bp->regview = ioremap_nocache(dev->base_addr, mem_len);
if (!bp->regview) {
- dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
+ dev_err(&pdev->dev, "Cannot map register space, aborting\n");
rc = -ENOMEM;
goto err_out_release;
}
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
dev_err(&pdev->dev,
- "Cannot find PCIE capability, aborting.\n");
+ "Cannot find PCIE capability, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
if (bp->pcix_cap == 0) {
dev_err(&pdev->dev,
- "Cannot find PCIX capability, aborting.\n");
+ "Cannot find PCIX capability, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
if (rc) {
dev_err(&pdev->dev,
- "pci_set_consistent_dma_mask failed, aborting.\n");
+ "pci_set_consistent_dma_mask failed, aborting\n");
goto err_out_unmap;
}
} else if ((rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
- dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
+ dev_err(&pdev->dev, "System does not support DMA, aborting\n");
goto err_out_unmap;
}
!(bp->flags & BNX2_FLAG_PCIX)) {
dev_err(&pdev->dev,
- "5706 A1 can only be used in a PCIX bus, aborting.\n");
+ "5706 A1 can only be used in a PCIX bus, aborting\n");
goto err_out_unmap;
}
if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
BNX2_DEV_INFO_SIGNATURE_MAGIC) {
- dev_err(&pdev->dev, "Firmware not running, aborting.\n");
+ dev_err(&pdev->dev, "Firmware not running, aborting\n");
rc = -ENODEV;
goto err_out_unmap;
}
#ifdef BCM_VLAN
.ndo_vlan_rx_register = bnx2_vlan_rx_register,
#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2,
#endif
};
char str[40];
if (version_printed++ == 0)
- printk(KERN_INFO "%s", version);
+ pr_info("%s", version);
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS);
goto error;
}
- printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
- "IRQ %d, node addr %pM\n",
- dev->name,
- board_info[ent->driver_data].name,
- ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
- ((CHIP_ID(bp) & 0x0ff0) >> 4),
- bnx2_bus_string(bp, str),
- dev->base_addr,
- bp->pdev->irq, dev->dev_addr);
+ netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, node addr %pM\n",
+ board_info[ent->driver_data].name,
+ ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+ ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ bnx2_bus_string(bp, str),
+ dev->base_addr,
+ bp->pdev->irq, dev->dev_addr);
return 0;
rtnl_lock();
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev,
- "Cannot re-enable PCI device after reset.\n");
+ "Cannot re-enable PCI device after reset\n");
rtnl_unlock();
return PCI_ERS_RESULT_DISCONNECT;
}