summaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c283
1 files changed, 141 insertions, 142 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8e6d618b530..4b2b57018a0 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
-#define DRV_MODULE_VERSION "2.1.6"
-#define DRV_MODULE_RELDATE "Mar 7, 2011"
+#define DRV_MODULE_VERSION "2.1.11"
+#define DRV_MODULE_RELDATE "July 20, 2011"
#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.2.1.fw"
#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw"
#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.2.1a.fw"
@@ -385,6 +385,9 @@ static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
if (cp->drv_state & CNIC_DRV_STATE_REGD)
return -EBUSY;
+ if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN))
+ return -ENODEV;
+
bp->cnic_data = data;
rcu_assign_pointer(bp->cnic_ops, ops);
@@ -416,6 +419,9 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ if (!cp->max_iscsi_conn)
+ return NULL;
+
cp->drv_owner = THIS_MODULE;
cp->chip_id = bp->chip_id;
cp->pdev = bp->pdev;
@@ -2440,6 +2446,48 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
return 0;
}
+static void
+bnx2_dump_mcp_state(struct bnx2 *bp)
+{
+ struct net_device *dev = bp->dev;
+ u32 mcp_p0, mcp_p1;
+
+ netdev_err(dev, "<--- start MCP states dump --->\n");
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ mcp_p0 = BNX2_MCP_STATE_P0;
+ mcp_p1 = BNX2_MCP_STATE_P1;
+ } else {
+ mcp_p0 = BNX2_MCP_STATE_P0_5708;
+ mcp_p1 = BNX2_MCP_STATE_P1_5708;
+ }
+ netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
+ bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
+ netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n",
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK));
+ netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n",
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+ bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION));
+ netdev_err(dev, "DEBUG: shmem states:\n");
+ netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]",
+ bnx2_shmem_rd(bp, BNX2_DRV_MB),
+ bnx2_shmem_rd(bp, BNX2_FW_MB),
+ bnx2_shmem_rd(bp, BNX2_LINK_STATUS));
+ pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB));
+ netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]",
+ bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE),
+ bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE));
+ pr_cont(" condition[%08x]\n",
+ bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION));
+ DP_SHMEM_LINE(bp, 0x3cc);
+ DP_SHMEM_LINE(bp, 0x3dc);
+ DP_SHMEM_LINE(bp, 0x3ec);
+ netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc));
+ netdev_err(dev, "<--- end MCP states dump --->\n");
+}
+
static int
bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
{
@@ -2468,13 +2516,14 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
/* 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)
- 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;
bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
+ if (!silent) {
+ pr_err("fw sync timeout, reset code = %x\n", msg_data);
+ bnx2_dump_mcp_state(bp);
+ }
return -EBUSY;
}
@@ -3174,7 +3223,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
}
skb_checksum_none_assert(skb);
- if (bp->rx_csum &&
+ if ((bp->dev->features & NETIF_F_RXCSUM) &&
(status & (L2_FHDR_STATUS_TCP_SEGMENT |
L2_FHDR_STATUS_UDP_DATAGRAM))) {
@@ -6293,6 +6342,7 @@ static void
bnx2_reset_task(struct work_struct *work)
{
struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
+ int rc;
rtnl_lock();
if (!netif_running(bp->dev)) {
@@ -6302,7 +6352,14 @@ bnx2_reset_task(struct work_struct *work)
bnx2_netif_stop(bp, true);
- bnx2_init_nic(bp, 1);
+ rc = bnx2_init_nic(bp, 1);
+ if (rc) {
+ netdev_err(bp->dev, "failed to reset NIC, closing\n");
+ bnx2_napi_enable(bp);
+ dev_close(bp->dev);
+ rtnl_unlock();
+ return;
+ }
atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp, true);
@@ -6313,7 +6370,7 @@ static void
bnx2_dump_state(struct bnx2 *bp)
{
struct net_device *dev = bp->dev;
- u32 mcp_p0, mcp_p1, val1, val2;
+ u32 val1, val2;
pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1);
netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n",
@@ -6326,15 +6383,6 @@ bnx2_dump_state(struct bnx2 *bp)
REG_RD(bp, BNX2_EMAC_RX_STATUS));
netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- mcp_p0 = BNX2_MCP_STATE_P0;
- mcp_p1 = BNX2_MCP_STATE_P1;
- } else {
- mcp_p0 = BNX2_MCP_STATE_P0_5708;
- mcp_p1 = BNX2_MCP_STATE_P1_5708;
- }
- netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
- bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_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)
@@ -6348,6 +6396,7 @@ bnx2_tx_timeout(struct net_device *dev)
struct bnx2 *bp = netdev_priv(dev);
bnx2_dump_state(bp);
+ bnx2_dump_mcp_state(bp);
/* This allows the netif to be shutdown gracefully before resetting */
schedule_work(&bp->reset_task);
@@ -6532,8 +6581,6 @@ bnx2_close(struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
- cancel_work_sync(&bp->reset_task);
-
bnx2_disable_int_sync(bp);
bnx2_napi_disable(bp);
del_timer_sync(&bp->timer);
@@ -6696,17 +6743,16 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (bp->autoneg & AUTONEG_SPEED) {
cmd->autoneg = AUTONEG_ENABLE;
- }
- else {
+ } else {
cmd->autoneg = AUTONEG_DISABLE;
}
if (netif_carrier_ok(dev)) {
- cmd->speed = bp->line_speed;
+ ethtool_cmd_speed_set(cmd, bp->line_speed);
cmd->duplex = bp->duplex;
}
else {
- cmd->speed = -1;
+ ethtool_cmd_speed_set(cmd, -1);
cmd->duplex = -1;
}
spin_unlock_bh(&bp->phy_lock);
@@ -6758,21 +6804,21 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising |= ADVERTISED_Autoneg;
}
else {
+ u32 speed = ethtool_cmd_speed(cmd);
if (cmd->port == PORT_FIBRE) {
- if ((cmd->speed != SPEED_1000 &&
- cmd->speed != SPEED_2500) ||
+ if ((speed != SPEED_1000 &&
+ speed != SPEED_2500) ||
(cmd->duplex != DUPLEX_FULL))
goto err_out_unlock;
- if (cmd->speed == SPEED_2500 &&
+ if (speed == SPEED_2500 &&
!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
goto err_out_unlock;
- }
- else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500)
+ } else if (speed == SPEED_1000 || speed == SPEED_2500)
goto err_out_unlock;
autoneg &= ~AUTONEG_SPEED;
- req_line_speed = cmd->speed;
+ req_line_speed = speed;
req_duplex = cmd->duplex;
advertising = 0;
}
@@ -7189,38 +7235,6 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
return 0;
}
-static u32
-bnx2_get_rx_csum(struct net_device *dev)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- return bp->rx_csum;
-}
-
-static int
-bnx2_set_rx_csum(struct net_device *dev, u32 data)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- bp->rx_csum = data;
- return 0;
-}
-
-static int
-bnx2_set_tso(struct net_device *dev, u32 data)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- if (data) {
- dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- dev->features |= NETIF_F_TSO6;
- } else
- dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
- NETIF_F_TSO_ECN);
- return 0;
-}
-
static struct {
char string[ETH_GSTRING_LEN];
} bnx2_stats_str_arr[] = {
@@ -7495,82 +7509,74 @@ bnx2_get_ethtool_stats(struct net_device *dev,
}
static int
-bnx2_phys_id(struct net_device *dev, u32 data)
+bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
{
struct bnx2 *bp = netdev_priv(dev);
- int i;
- u32 save;
- bnx2_set_power_state(bp, PCI_D0);
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ bnx2_set_power_state(bp, PCI_D0);
+
+ bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
+ REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
+ return 1; /* cycle on/off once per second */
+
+ case ETHTOOL_ID_ON:
+ REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
+ BNX2_EMAC_LED_1000MB_OVERRIDE |
+ BNX2_EMAC_LED_100MB_OVERRIDE |
+ BNX2_EMAC_LED_10MB_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC);
+ break;
- if (data == 0)
- data = 2;
+ case ETHTOOL_ID_OFF:
+ REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
+ break;
- save = REG_RD(bp, BNX2_MISC_CFG);
- REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
+ case ETHTOOL_ID_INACTIVE:
+ REG_WR(bp, BNX2_EMAC_LED, 0);
+ REG_WR(bp, BNX2_MISC_CFG, bp->leds_save);
- for (i = 0; i < (data * 2); i++) {
- if ((i % 2) == 0) {
- REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
- }
- else {
- REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
- BNX2_EMAC_LED_1000MB_OVERRIDE |
- BNX2_EMAC_LED_100MB_OVERRIDE |
- BNX2_EMAC_LED_10MB_OVERRIDE |
- BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
- BNX2_EMAC_LED_TRAFFIC);
- }
- msleep_interruptible(500);
- if (signal_pending(current))
- break;
+ if (!netif_running(dev))
+ bnx2_set_power_state(bp, PCI_D3hot);
+ break;
}
- REG_WR(bp, BNX2_EMAC_LED, 0);
- REG_WR(bp, BNX2_MISC_CFG, save);
-
- if (!netif_running(dev))
- bnx2_set_power_state(bp, PCI_D3hot);
return 0;
}
-static int
-bnx2_set_tx_csum(struct net_device *dev, u32 data)
+static u32
+bnx2_fix_features(struct net_device *dev, u32 features)
{
struct bnx2 *bp = netdev_priv(dev);
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- return ethtool_op_set_tx_ipv6_csum(dev, data);
- else
- return ethtool_op_set_tx_csum(dev, data);
+ if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
+ features |= NETIF_F_HW_VLAN_RX;
+
+ return features;
}
static int
-bnx2_set_flags(struct net_device *dev, u32 data)
+bnx2_set_features(struct net_device *dev, u32 features)
{
struct bnx2 *bp = netdev_priv(dev);
- int rc;
-
- if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) &&
- !(data & ETH_FLAG_RXVLAN))
- return -EINVAL;
/* TSO with VLAN tag won't work with current firmware */
- if (!(data & ETH_FLAG_TXVLAN))
- return -EINVAL;
-
- rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN |
- ETH_FLAG_TXVLAN);
- if (rc)
- return rc;
+ if (features & NETIF_F_HW_VLAN_TX)
+ dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO);
+ else
+ dev->vlan_features &= ~NETIF_F_ALL_TSO;
- if ((!!(data & ETH_FLAG_RXVLAN) !=
+ if ((!!(features & NETIF_F_HW_VLAN_RX) !=
!!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
netif_running(dev)) {
bnx2_netif_stop(bp, false);
+ dev->features = features;
bnx2_set_rx_mode(dev);
bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
bnx2_netif_start(bp, false);
+ return 1;
}
return 0;
@@ -7595,18 +7601,11 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
.set_ringparam = bnx2_set_ringparam,
.get_pauseparam = bnx2_get_pauseparam,
.set_pauseparam = bnx2_set_pauseparam,
- .get_rx_csum = bnx2_get_rx_csum,
- .set_rx_csum = bnx2_set_rx_csum,
- .set_tx_csum = bnx2_set_tx_csum,
- .set_sg = ethtool_op_set_sg,
- .set_tso = bnx2_set_tso,
.self_test = bnx2_self_test,
.get_strings = bnx2_get_strings,
- .phys_id = bnx2_phys_id,
+ .set_phys_id = bnx2_set_phys_id,
.get_ethtool_stats = bnx2_get_ethtool_stats,
.get_sset_count = bnx2_get_sset_count,
- .set_flags = bnx2_set_flags,
- .get_flags = ethtool_op_get_flags,
};
/* Called with rtnl_lock */
@@ -7956,9 +7955,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
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");
+ if (!pci_is_pcie(pdev)) {
+ dev_err(&pdev->dev, "Not PCIE, aborting\n");
rc = -EIO;
goto err_out_unmap;
}
@@ -8099,7 +8097,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->fw_version[j++] = ' ';
for (i = 0; i < 3 && j < 28; i++) {
reg = bnx2_reg_rd_ind(bp, addr + i * 4);
- reg = swab32(reg);
+ reg = be32_to_cpu(reg);
memcpy(&bp->fw_version[j], &reg, 4);
j += 4;
}
@@ -8118,8 +8116,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->tx_ring_size = MAX_TX_DESC_CNT;
bnx2_set_rx_ring_size(bp, 255);
- bp->rx_csum = 1;
-
bp->tx_quick_cons_trip_int = 2;
bp->tx_quick_cons_trip = 20;
bp->tx_ticks_int = 18;
@@ -8227,6 +8223,12 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2_timer;
+#ifdef BCM_CNIC
+ if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN)
+ bp->cnic_eth_dev.max_iscsi_conn =
+ (bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
+ BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
+#endif
pci_save_state(pdev);
return 0;
@@ -8311,17 +8313,14 @@ static const struct net_device_ops bnx2_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = bnx2_change_mac_addr,
.ndo_change_mtu = bnx2_change_mtu,
+ .ndo_fix_features = bnx2_fix_features,
+ .ndo_set_features = bnx2_set_features,
.ndo_tx_timeout = bnx2_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2,
#endif
};
-static inline void vlan_features_add(struct net_device *dev, u32 flags)
-{
- dev->vlan_features |= flags;
-}
-
static int __devinit
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -8361,20 +8360,17 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
memcpy(dev->dev_addr, bp->mac_addr, 6);
memcpy(dev->perm_addr, bp->mac_addr, 6);
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_GRO |
- NETIF_F_RXHASH;
- vlan_features_add(dev, NETIF_F_IP_CSUM | NETIF_F_SG);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- dev->features |= NETIF_F_IPV6_CSUM;
- vlan_features_add(dev, NETIF_F_IPV6_CSUM);
- }
- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
- vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- dev->features |= NETIF_F_TSO6;
- vlan_features_add(dev, NETIF_F_TSO6);
- }
+ dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_TSO_ECN |
+ NETIF_F_RXHASH | NETIF_F_RXCSUM;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+
+ dev->vlan_features = dev->hw_features;
+ dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->features |= dev->hw_features;
+
if ((rc = register_netdev(dev))) {
dev_err(&pdev->dev, "Cannot register net device\n");
goto error;
@@ -8413,6 +8409,9 @@ bnx2_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
+ del_timer_sync(&bp->timer);
+ cancel_work_sync(&bp->reset_task);
+
if (bp->mips_firmware)
release_firmware(bp->mips_firmware);
if (bp->rv2p_firmware)