diff options
author | Steve French <sfrench@us.ibm.com> | 2008-03-01 18:29:55 +0000 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-03-01 18:29:55 +0000 |
commit | 0dbd888936a23514716b8d944775bc56f731363a (patch) | |
tree | a2c60cdc45bdcbed47680731fa8188bffe58c098 /drivers/net | |
parent | 0b442d2c28479332610c46e1a74e5638ab63a97d (diff) | |
parent | d395991c117d43bfca97101a931a41d062a93852 (diff) |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/net')
80 files changed, 3408 insertions, 1716 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f337800076c..a0f0e605d63 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -90,6 +90,11 @@ config MACVLAN This allows one to create virtual interfaces that map packets to or from specific MAC addresses to a particular interface. + Macvlan devices can be added using the "ip" command from the + iproute2 package starting with the iproute2-2.6.23 release: + + "ip link add link <real dev> [ address MAC ] [ NAME ] type macvlan" + To compile this driver as a module, choose M here: the module will be called macvlan. @@ -2363,6 +2368,7 @@ config GELIC_NET config GELIC_WIRELESS bool "PS3 Wireless support" depends on GELIC_NET + select WIRELESS_EXT help This option adds the support for the wireless feature of PS3. If you have the wireless-less model of PS3 or have no plan to diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 471c7f3e8a4..15853be4680 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.7.3" -#define DRV_MODULE_RELDATE "January 29, 2008" +#define DRV_MODULE_VERSION "1.7.4" +#define DRV_MODULE_RELDATE "February 18, 2008" #define RUN_AT(x) (jiffies + (x)) @@ -1273,14 +1273,20 @@ bnx2_set_link(struct bnx2 *bp) if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && (CHIP_NUM(bp) == CHIP_NUM_5706)) { - u32 val; + u32 val, an_dbg; if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { bnx2_5706s_force_link_dn(bp, 0); bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; } val = REG_RD(bp, BNX2_EMAC_STATUS); - if (val & BNX2_EMAC_STATUS_LINK) + + bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); + bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); + bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); + + if ((val & BNX2_EMAC_STATUS_LINK) && + !(an_dbg & MISC_SHDW_AN_DBG_NOSYNC)) bmsr |= BMSR_LSTATUS; else bmsr &= ~BMSR_LSTATUS; @@ -5356,11 +5362,15 @@ bnx2_test_intr(struct bnx2 *bp) return -ENODEV; } +/* Determining link for parallel detection. */ static int bnx2_5706_serdes_has_link(struct bnx2 *bp) { u32 mode_ctl, an_dbg, exp; + if (bp->phy_flags & BNX2_PHY_FLAG_NO_PARALLEL) + return 0; + bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_MODE_CTL); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &mode_ctl); @@ -5390,13 +5400,6 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) int check_link = 1; spin_lock(&bp->phy_lock); - if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { - bnx2_5706s_force_link_dn(bp, 0); - bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; - spin_unlock(&bp->phy_lock); - return; - } - if (bp->serdes_an_pending) { bp->serdes_an_pending--; check_link = 0; @@ -5420,7 +5423,6 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)) { u32 phy2; - check_link = 0; bnx2_write_phy(bp, 0x17, 0x0f01); bnx2_read_phy(bp, 0x15, &phy2); if (phy2 & 0x20) { @@ -5435,17 +5437,21 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) } else bp->current_interval = bp->timer_interval; - if (bp->link_up && (bp->autoneg & AUTONEG_SPEED) && check_link) { + if (check_link) { u32 val; bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); - if (val & MISC_SHDW_AN_DBG_NOSYNC) { - bnx2_5706s_force_link_dn(bp, 1); - bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN; - } + if (bp->link_up && (val & MISC_SHDW_AN_DBG_NOSYNC)) { + if (!(bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN)) { + bnx2_5706s_force_link_dn(bp, 1); + bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN; + } else + bnx2_set_link(bp); + } else if (!bp->link_up && !(val & MISC_SHDW_AN_DBG_NOSYNC)) + bnx2_set_link(bp); } spin_unlock(&bp->phy_lock); } @@ -7326,7 +7332,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_NO_WOL; bp->wol = 0; } - if (CHIP_NUM(bp) != CHIP_NUM_5706) { + if (CHIP_NUM(bp) == CHIP_NUM_5706) { + /* Don't do parallel detect on this board because of + * some board problems. The link will not go down + * if we do parallel detect. + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP && + pdev->subsystem_device == 0x310c) + bp->phy_flags |= BNX2_PHY_FLAG_NO_PARALLEL; + } else { bp->phy_addr = 2; if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 3aa0364942e..1eaf5bb3d9c 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6673,6 +6673,7 @@ struct bnx2 { #define BNX2_PHY_FLAG_DIS_EARLY_DAC 0x00000400 #define BNX2_PHY_FLAG_REMOTE_PHY_CAP 0x00000800 #define BNX2_PHY_FLAG_FORCED_DOWN 0x00001000 +#define BNX2_PHY_FLAG_NO_PARALLEL 0x00002000 u32 mii_bmcr; u32 mii_bmsr; diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index afc7f34b1dc..8af142ccf37 100644 --- a/drivers/net/bnx2x.c +++ b/drivers/net/bnx2x.c @@ -1,6 +1,6 @@ /* bnx2x.c: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 @@ -10,13 +10,13 @@ * Based on code from Michael Chan's bnx2 driver * UDP CSUM errata workaround by Arik Gendelman * Slowpath rework by Vladislav Zolotarov - * Statistics and Link managment by Yitchak Gertner + * Statistics and Link management by Yitchak Gertner * */ /* define this to make the driver freeze on error * to allow getting debug info - * (you will need to reboot afterwords) + * (you will need to reboot afterwards) */ /*#define BNX2X_STOP_ON_ERROR*/ @@ -63,22 +63,21 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "0.40.15" -#define DRV_MODULE_RELDATE "$DateTime: 2007/11/15 07:28:37 $" -#define BNX2X_BC_VER 0x040009 +#define DRV_MODULE_VERSION "1.40.22" +#define DRV_MODULE_RELDATE "2007/11/27" +#define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (5*HZ) static char version[] __devinitdata = - "Broadcom NetXtreme II 577xx 10Gigabit Ethernet Driver " + "Broadcom NetXtreme II 5771X 10Gigabit Ethernet Driver " DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Eliezer Tamir <eliezert@broadcom.com>"); MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -MODULE_INFO(cvs_version, "$Revision: #356 $"); static int use_inta; static int poll; @@ -94,8 +93,8 @@ module_param(debug, int, 0); MODULE_PARM_DESC(use_inta, "use INT#A instead of MSI-X"); MODULE_PARM_DESC(poll, "use polling (for debug)"); MODULE_PARM_DESC(onefunc, "enable only first function"); -MODULE_PARM_DESC(nomcp, "ignore managment CPU (Implies onefunc)"); -MODULE_PARM_DESC(debug, "defualt debug msglevel"); +MODULE_PARM_DESC(nomcp, "ignore management CPU (Implies onefunc)"); +MODULE_PARM_DESC(debug, "default debug msglevel"); #ifdef BNX2X_MULTI module_param(use_multi, int, 0); @@ -298,8 +297,7 @@ static void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) static int bnx2x_mc_assert(struct bnx2x *bp) { - int i, j; - int rc = 0; + int i, j, rc = 0; char last_idx; const char storm[] = {"XTCU"}; const u32 intmem_base[] = { @@ -313,8 +311,9 @@ static int bnx2x_mc_assert(struct bnx2x *bp) for (i = 0; i < 4; i++) { last_idx = REG_RD8(bp, XSTORM_ASSERT_LIST_INDEX_OFFSET + intmem_base[i]); - BNX2X_ERR("DATA %cSTORM_ASSERT_LIST_INDEX 0x%x\n", - storm[i], last_idx); + if (last_idx) + BNX2X_LOG("DATA %cSTORM_ASSERT_LIST_INDEX 0x%x\n", + storm[i], last_idx); /* print the asserts */ for (j = 0; j < STROM_ASSERT_ARRAY_SIZE; j++) { @@ -330,7 +329,7 @@ static int bnx2x_mc_assert(struct bnx2x *bp) intmem_base[i]); if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) { - BNX2X_ERR("DATA %cSTORM_ASSERT_INDEX 0x%x =" + BNX2X_LOG("DATA %cSTORM_ASSERT_INDEX 0x%x =" " 0x%08x 0x%08x 0x%08x 0x%08x\n", storm[i], j, row3, row2, row1, row0); rc++; @@ -341,6 +340,7 @@ static int bnx2x_mc_assert(struct bnx2x *bp) } return rc; } + static void bnx2x_fw_dump(struct bnx2x *bp) { u32 mark, offset; @@ -348,21 +348,22 @@ static void bnx2x_fw_dump(struct bnx2x *bp) int word; mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); - printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark); + mark = ((mark + 0x3) & ~0x3); + printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark); for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + offset + 4*word)); data[8] = 0x0; - printk(KERN_ERR PFX "%s", (char *)data); + printk(KERN_CONT "%s", (char *)data); } for (offset = 0xF108; offset <= mark - 0x08000000; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + offset + 4*word)); data[8] = 0x0; - printk(KERN_ERR PFX "%s", (char *)data); + printk(KERN_CONT "%s", (char *)data); } printk("\n" KERN_ERR PFX "end of fw dump\n"); } @@ -427,10 +428,10 @@ static void bnx2x_panic_dump(struct bnx2x *bp) } } - BNX2X_ERR("def_c_idx(%u) def_u_idx(%u) def_t_idx(%u)" - " def_x_idx(%u) def_att_idx(%u) attn_state(%u)" + BNX2X_ERR("def_c_idx(%u) def_u_idx(%u) def_x_idx(%u)" + " def_t_idx(%u) def_att_idx(%u) attn_state(%u)" " spq_prod_idx(%u)\n", - bp->def_c_idx, bp->def_u_idx, bp->def_t_idx, bp->def_x_idx, + bp->def_c_idx, bp->def_u_idx, bp->def_x_idx, bp->def_t_idx, bp->def_att_idx, bp->attn_state, bp->spq_prod_idx); @@ -441,7 +442,7 @@ static void bnx2x_panic_dump(struct bnx2x *bp) DP(BNX2X_MSG_STATS, "stats_state - DISABLE\n"); } -static void bnx2x_enable_int(struct bnx2x *bp) +static void bnx2x_int_enable(struct bnx2x *bp) { int port = bp->port; u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; @@ -454,18 +455,26 @@ static void bnx2x_enable_int(struct bnx2x *bp) HC_CONFIG_0_REG_ATTN_BIT_EN_0); } else { val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | + HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | HC_CONFIG_0_REG_INT_LINE_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); + + /* Errata A0.158 workaround */ + DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) MSI-X %d\n", + val, port, addr, msix); + + REG_WR(bp, addr, val); + val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0; } - DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) msi %d\n", + DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) MSI-X %d\n", val, port, addr, msix); REG_WR(bp, addr, val); } -static void bnx2x_disable_int(struct bnx2x *bp) +static void bnx2x_int_disable(struct bnx2x *bp) { int port = bp->port; u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; @@ -484,15 +493,15 @@ static void bnx2x_disable_int(struct bnx2x *bp) BNX2X_ERR("BUG! proper val not read from IGU!\n"); } -static void bnx2x_disable_int_sync(struct bnx2x *bp) +static void bnx2x_int_disable_sync(struct bnx2x *bp) { int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0; int i; atomic_inc(&bp->intr_sem); - /* prevent the HW from sending interrupts*/ - bnx2x_disable_int(bp); + /* prevent the HW from sending interrupts */ + bnx2x_int_disable(bp); /* make sure all ISRs are done */ if (msix) { @@ -775,6 +784,7 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, mb(); /* force bnx2x_wait_ramrod to see the change */ return; } + switch (command | bp->state) { case (RAMROD_CMD_ID_ETH_PORT_SETUP | BNX2X_STATE_OPENING_WAIT4_PORT): DP(NETIF_MSG_IFUP, "got setup ramrod\n"); @@ -787,20 +797,20 @@ static void bnx2x_sp_event(struct bnx2x_fastpath *fp, fp->state = BNX2X_FP_STATE_HALTED; break; - case (RAMROD_CMD_ID_ETH_PORT_DEL | BNX2X_STATE_CLOSING_WAIT4_DELETE): - DP(NETIF_MSG_IFDOWN, "got delete ramrod\n"); - bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; - break; - case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_CLOSING_WAIT4_HALT): - DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", cid); - bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_DELETED; + DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", + cid); + bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED; break; case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN): DP(NETIF_MSG_IFUP, "got set mac ramrod\n"); break; + case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT): + DP(NETIF_MSG_IFUP, "got (un)set mac ramrod\n"); + break; + default: BNX2X_ERR("unexpected ramrod (%d) state is %x\n", command, bp->state); @@ -1179,12 +1189,175 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits) return val; } +static int bnx2x_hw_lock(struct bnx2x *bp, u32 resource) +{ + u32 cnt; + u32 lock_status; + u32 resource_bit = (1 << resource); + u8 func = bp->port; + + /* Validating that the resource is within range */ + if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { + DP(NETIF_MSG_HW, + "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n", + resource, HW_LOCK_MAX_RESOURCE_VALUE); + return -EINVAL; + } + + /* Validating that the resource is not already taken */ + lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); + if (lock_status & resource_bit) { + DP(NETIF_MSG_HW, "lock_status 0x%x resource_bit 0x%x\n", + lock_status, resource_bit); + return -EEXIST; + } + + /* Try for 1 second every 5ms */ + for (cnt = 0; cnt < 200; cnt++) { + /* Try to acquire the lock */ + REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8 + 4, + resource_bit); + lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); + if (lock_status & resource_bit) + return 0; + + msleep(5); + } + DP(NETIF_MSG_HW, "Timeout\n"); + return -EAGAIN; +} + +static int bnx2x_hw_unlock(struct bnx2x *bp, u32 resource) +{ + u32 lock_status; + u32 resource_bit = (1 << resource); + u8 func = bp->port; + + /* Validating that the resource is within range */ + if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { + DP(NETIF_MSG_HW, + "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n", + resource, HW_LOCK_MAX_RESOURCE_VALUE); + return -EINVAL; + } + + /* Validating that the resource is currently taken */ + lock_status = REG_RD(bp, MISC_REG_DRIVER_CONTROL_1 + func*8); + if (!(lock_status & resource_bit)) { + DP(NETIF_MSG_HW, "lock_status 0x%x resource_bit 0x%x\n", + lock_status, resource_bit); + return -EFAULT; + } + + REG_WR(bp, MISC_REG_DRIVER_CONTROL_1 + func*8, resource_bit); + return 0; +} + +static int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode) +{ + /* The GPIO should be swapped if swap register is set and active */ + int gpio_port = (REG_RD(bp, NIG_REG_PORT_SWAP) && + REG_RD(bp, NIG_REG_STRAP_OVERRIDE)) ^ bp->port; + int gpio_shift = gpio_num + + (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0); + u32 gpio_mask = (1 << gpio_shift); + u32 gpio_reg; + + if (gpio_num > MISC_REGISTERS_GPIO_3) { + BNX2X_ERR("Invalid GPIO %d\n", gpio_num); + return -EINVAL; + } + + bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_GPIO); + /* read GPIO and mask except the float bits */ + gpio_reg = (REG_RD(bp, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT); + + switch (mode) { + case MISC_REGISTERS_GPIO_OUTPUT_LOW: + DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output low\n", + gpio_num, gpio_shift); + /* clear FLOAT and set CLR */ + gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); + gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS); + break; + + case MISC_REGISTERS_GPIO_OUTPUT_HIGH: + DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> output high\n", + gpio_num, gpio_shift); + /* clear FLOAT and set SET */ + gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); + gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_SET_POS); + break; + + case MISC_REGISTERS_GPIO_INPUT_HI_Z : + DP(NETIF_MSG_LINK, "Set GPIO %d (shift %d) -> input\n", + gpio_num, gpio_shift); + /* set FLOAT */ + gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); + break; + + default: + break; + } + + REG_WR(bp, MISC_REG_GPIO, gpio_reg); + bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_GPIO); + + return 0; +} + +static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) +{ + u32 spio_mask = (1 << spio_num); + u32 spio_reg; + + if ((spio_num < MISC_REGISTERS_SPIO_4) || + (spio_num > MISC_REGISTERS_SPIO_7)) { + BNX2X_ERR("Invalid SPIO %d\n", spio_num); + return -EINVAL; + } + + bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_SPIO); + /* read SPIO and mask except the float bits */ + spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT); + + switch (mode) { + case MISC_REGISTERS_SPIO_OUTPUT_LOW : + DP(NETIF_MSG_LINK, "Set SPIO %d -> output low\n", spio_num); + /* clear FLOAT and set CLR */ + spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); + spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_CLR_POS); + break; + + case MISC_REGISTERS_SPIO_OUTPUT_HIGH : + DP(NETIF_MSG_LINK, "Set SPIO %d -> output high\n", spio_num); + /* clear FLOAT and set SET */ + spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); + spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_SET_POS); + break; + + case MISC_REGISTERS_SPIO_INPUT_HI_Z: + DP(NETIF_MSG_LINK, "Set SPIO %d -> input\n", spio_num); + /* set FLOAT */ + spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); + break; + + default: + break; + } + + REG_WR(bp, MISC_REG_SPIO, spio_reg); + bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_SPIO); + + return 0; +} + static int bnx2x_mdio22_write(struct bnx2x *bp, u32 reg, u32 val) { - int rc; - u32 tmp, i; int port = bp->port; u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; + u32 tmp; + int i, rc; /* DP(NETIF_MSG_HW, "phy_addr 0x%x reg 0x%x val 0x%08x\n", bp->phy_addr, reg, val); */ @@ -1236,8 +1409,8 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val) { int port = bp->port; u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - u32 val, i; - int rc; + u32 val; + int i, rc; if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { @@ -1286,58 +1459,54 @@ static int bnx2x_mdio22_read(struct bnx2x *bp, u32 reg, u32 *ret_val) return rc; } -static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val) +static int bnx2x_mdio45_ctrl_write(struct bnx2x *bp, u32 mdio_ctrl, + u32 phy_addr, u32 reg, u32 addr, u32 val) { - int rc = 0; - u32 tmp, i; - int port = bp->port; - u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - - if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { - - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - tmp &= ~EMAC_MDIO_MODE_AUTO_POLL; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); - REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - udelay(40); - } + u32 tmp; + int i, rc = 0; - /* set clause 45 mode */ - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - tmp |= EMAC_MDIO_MODE_CLAUSE_45; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); + /* set clause 45 mode, slow down the MDIO clock to 2.5MHz + * (a value of 49==0x31) and make sure that the AUTO poll is off + */ + tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + tmp &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); + tmp |= (EMAC_MDIO_MODE_CLAUSE_45 | + (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT)); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp); + REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + udelay(40); /* address */ - tmp = ((bp->phy_addr << 21) | (reg << 16) | addr | + tmp = ((phy_addr << 21) | (reg << 16) | addr | EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY); - EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); for (i = 0; i < 50; i++) { udelay(10); - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); + tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { udelay(5); break; } } - if (tmp & EMAC_MDIO_COMM_START_BUSY) { BNX2X_ERR("write phy register failed\n"); rc = -EBUSY; + } else { /* data */ - tmp = ((bp->phy_addr << 21) | (reg << 16) | val | + tmp = ((phy_addr << 21) | (reg << 16) | val | EMAC_MDIO_COMM_COMMAND_WRITE_45 | EMAC_MDIO_COMM_START_BUSY); - EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, tmp); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); for (i = 0; i < 50; i++) { udelay(10); - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); + tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { udelay(5); break; @@ -1351,75 +1520,78 @@ static int bnx2x_mdio45_write(struct bnx2x *bp, u32 reg, u32 addr, u32 val) } } - /* unset clause 45 mode */ - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - tmp &= ~EMAC_MDIO_MODE_CLAUSE_45; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); - - if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { - - tmp = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); + /* unset clause 45 mode, set the MDIO clock to a faster value + * (0x13 => 6.25Mhz) and restore the AUTO poll if needed + */ + tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + tmp &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT); + tmp |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) tmp |= EMAC_MDIO_MODE_AUTO_POLL; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, tmp); - } + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp); return rc; } -static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr, - u32 *ret_val) +static int bnx2x_mdio45_write(struct bnx2x *bp, u32 phy_addr, u32 reg, + u32 addr, u32 val) { - int port = bp->port; - u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - u32 val, i; - int rc = 0; + u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { + return bnx2x_mdio45_ctrl_write(bp, emac_base, phy_addr, + reg, addr, val); +} - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - val &= ~EMAC_MDIO_MODE_AUTO_POLL; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); - REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - udelay(40); - } +static int bnx2x_mdio45_ctrl_read(struct bnx2x *bp, u32 mdio_ctrl, + u32 phy_addr, u32 reg, u32 addr, + u32 *ret_val) +{ + u32 val; + int i, rc = 0; - /* set clause 45 mode */ - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - val |= EMAC_MDIO_MODE_CLAUSE_45; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); + /* set clause 45 mode, slow down the MDIO clock to 2.5MHz + * (a value of 49==0x31) and make sure that the AUTO poll is off + */ + val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + val &= ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); + val |= (EMAC_MDIO_MODE_CLAUSE_45 | + (49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT)); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val); + REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + udelay(40); /* address */ - val = ((bp->phy_addr << 21) | (reg << 16) | addr | + val = ((phy_addr << 21) | (reg << 16) | addr | EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY); - EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); for (i = 0; i < 50; i++) { udelay(10); - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); + val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(val & EMAC_MDIO_COMM_START_BUSY)) { udelay(5); break; } } - if (val & EMAC_MDIO_COMM_START_BUSY) { BNX2X_ERR("read phy register failed\n"); *ret_val = 0; rc = -EBUSY; + } else { /* data */ - val = ((bp->phy_addr << 21) | (reg << 16) | + val = ((phy_addr << 21) | (reg << 16) | EMAC_MDIO_COMM_COMMAND_READ_45 | EMAC_MDIO_COMM_START_BUSY); - EMAC_WR(EMAC_REG_EMAC_MDIO_COMM, val); + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); for (i = 0; i < 50; i++) { udelay(10); - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM); + val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(val & EMAC_MDIO_COMM_START_BUSY)) { val &= EMAC_MDIO_COMM_DATA; break; @@ -1436,31 +1608,39 @@ static int bnx2x_mdio45_read(struct bnx2x *bp, u32 reg, u32 addr, *ret_val = val; } - /* unset clause 45 mode */ - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - val &= ~EMAC_MDIO_MODE_CLAUSE_45; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); - - if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { - - val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); + /* unset clause 45 mode, set the MDIO clock to a faster value + * (0x13 => 6.25Mhz) and restore the AUTO poll if needed + */ + val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); + val &= ~(EMAC_MDIO_MODE_CLAUSE_45 | EMAC_MDIO_MODE_CLOCK_CNT); + val |= (0x13 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) val |= EMAC_MDIO_MODE_AUTO_POLL; - EMAC_WR(EMAC_REG_EMAC_MDIO_MODE, val); - } + REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val); return rc; } -static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val) +static int bnx2x_mdio45_read(struct bnx2x *bp, u32 phy_addr, u32 reg, + u32 addr, u32 *ret_val) +{ + u32 emac_base = bp->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; + + return bnx2x_mdio45_ctrl_read(bp, emac_base, phy_addr, + reg, addr, ret_val); +} + +static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 phy_addr, u32 reg, + u32 addr, u32 val) { int i; u32 rd_val; might_sleep(); for (i = 0; i < 10; i++) { - bnx2x_mdio45_write(bp, reg, addr, val); + bnx2x_mdio45_write(bp, phy_addr, reg, addr, val); msleep(5); - bnx2x_mdio45_read(bp, reg, addr, &rd_val); + bnx2x_mdio45_read(bp, phy_addr, reg, addr, &rd_val); /* if the read value is not the same as the value we wrote, we should write it again */ if (rd_val == val) @@ -1471,18 +1651,81 @@ static int bnx2x_mdio45_vwrite(struct bnx2x *bp, u32 reg, u32 addr, u32 val) } /* - * link managment + * link management */ +static void bnx2x_pause_resolve(struct bnx2x *bp, u32 pause_result) +{ + switch (pause_result) { /* ASYM P ASYM P */ + case 0xb: /* 1 0 1 1 */ + bp->flow_ctrl = FLOW_CTRL_TX; + break; + + case 0xe: /* 1 1 1 0 */ + bp->flow_ctrl = FLOW_CTRL_RX; + break; + + case 0x5: /* 0 1 0 1 */ + case 0x7: /* 0 1 1 1 */ + case 0xd: /* 1 1 0 1 */ + case 0xf: /* 1 1 1 1 */ + bp->flow_ctrl = FLOW_CTRL_BOTH; + break; + + default: + break; + } +} + +static u8 bnx2x_ext_phy_resove_fc(struct bnx2x *bp) +{ + u32 ext_phy_addr; + u32 ld_pause; /* local */ + u32 lp_pause; /* link partner */ + u32 an_complete; /* AN complete */ + u32 pause_result; + u8 ret = 0; + + ext_phy_addr = ((bp->ext_phy_config & + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); + + /* read twice */ + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_STATUS, &an_complete); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_STATUS, &an_complete); + + if (an_complete & EXT_PHY_KR_AUTO_NEG_COMPLETE) { + ret = 1; + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_AUTO_NEG_ADVERT, &ld_pause); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_LP_AUTO_NEG, &lp_pause); + pause_result = (ld_pause & + EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 8; + pause_result |= (lp_pause & + EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK) >> 10; + DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n", + pause_result); + bnx2x_pause_resolve(bp, pause_result); + } + return ret; +} + static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status) { - u32 ld_pause; /* local driver */ - u32 lp_pause; /* link partner */ + u32 ld_pause; /* local driver */ + u32 lp_pause; /* link partner */ u32 pause_result; bp->flow_ctrl = 0; - /* reolve from gp_status in case of AN complete and not sgmii */ + /* resolve from gp_status in case of AN complete and not sgmii */ if ((bp->req_autoneg & AUTONEG_FLOW_CTRL) && (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) && (!(bp->phy_flags & PHY_SGMII_FLAG)) && @@ -1499,45 +1742,57 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x *bp, u32 gp_status) pause_result |= (lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); + bnx2x_pause_resolve(bp, pause_result); + } else if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) || + !(bnx2x_ext_phy_resove_fc(bp))) { + /* forced speed */ + if (bp->req_autoneg & AUTONEG_FLOW_CTRL) { + switch (bp->req_flow_ctrl) { + case FLOW_CTRL_AUTO: + if (bp->dev->mtu <= 4500) + bp->flow_ctrl = FLOW_CTRL_BOTH; + else + bp->flow_ctrl = FLOW_CTRL_TX; + break; - switch (pause_result) { /* ASYM P ASYM P */ - case 0xb: /* 1 0 1 1 */ - bp->flow_ctrl = FLOW_CTRL_TX; - break; - - case 0xe: /* 1 1 1 0 */ - bp->flow_ctrl = FLOW_CTRL_RX; - break; + case FLOW_CTRL_TX: + bp->flow_ctrl = FLOW_CTRL_TX; + break; - case 0x5: /* 0 1 0 1 */ - case 0x7: /* 0 1 1 1 */ - case 0xd: /* 1 1 0 1 */ - case 0xf: /* 1 1 1 1 */ - bp->flow_ctrl = FLOW_CTRL_BOTH; - break; + case FLOW_CTRL_RX: + if (bp->dev->mtu <= 4500) + bp->flow_ctrl = FLOW_CTRL_RX; + break; - default: - break; - } + case FLOW_CTRL_BOTH: + if (bp->dev->mtu <= 4500) + bp->flow_ctrl = FLOW_CTRL_BOTH; + else + bp->flow_ctrl = FLOW_CTRL_TX; + break; - } else { /* forced mode */ - switch (bp->req_flow_ctrl) { - case FLOW_CTRL_AUTO: - if (bp->dev->mtu <= 4500) - bp->flow_ctrl = FLOW_CTRL_BOTH; - else - bp->flow_ctrl = FLOW_CTRL_TX; - break; + case FLOW_CTRL_NONE: + default: + break; + } + } else { /* forced mode */ + switch (bp->req_flow_ctrl) { + case FLOW_CTRL_AUTO: + DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while" + " req_autoneg 0x%x\n", + bp->req_flow_ctrl, bp->req_autoneg); + break; - case FLOW_CTRL_TX: - case FLOW_CTRL_RX: - case FLOW_CTRL_BOTH: - bp->flow_ctrl = bp->req_flow_ctrl; - break; + case FLOW_CTRL_TX: + case FLOW_CTRL_RX: + case FLOW_CTRL_BOTH: + bp->flow_ctrl = bp->req_flow_ctrl; + break; - case FLOW_CTRL_NONE: - default: - break; + case FLOW_CTRL_NONE: + default: + break; + } } } DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", bp->flow_ctrl); @@ -1548,9 +1803,9 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status) bp->link_status = 0; if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { - DP(NETIF_MSG_LINK, "link up\n"); + DP(NETIF_MSG_LINK, "phy link up\n"); - bp->link_up = 1; + bp->phy_link_up = 1; bp->link_status |= LINK_STATUS_LINK_UP; if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS) @@ -1659,20 +1914,20 @@ static void bnx2x_link_settings_status(struct bnx2x *bp, u32 gp_status) bp->link_status |= LINK_STATUS_RX_FLOW_CONTROL_ENABLED; } else { /* link_down */ - DP(NETIF_MSG_LINK, "link down\n"); + DP(NETIF_MSG_LINK, "phy link down\n"); - bp->link_up = 0; + bp->phy_link_up = 0; bp->line_speed = 0; bp->duplex = DUPLEX_FULL; bp->flow_ctrl = 0; } - DP(NETIF_MSG_LINK, "gp_status 0x%x link_up %d\n" + DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %d\n" DP_LEVEL " line_speed %d duplex %d flow_ctrl 0x%x" " link_status 0x%x\n", - gp_status, bp->link_up, bp->line_speed, bp->duplex, bp->flow_ctrl, - bp->link_status); + gp_status, bp->phy_link_up, bp->line_speed, bp->duplex, + bp->flow_ctrl, bp->link_status); } static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g) @@ -1680,40 +1935,40 @@ static void bnx2x_link_int_ack(struct bnx2x *bp, int is_10g) int port = bp->port; /* first reset all status - * we asume only one line will be change at a time */ + * we assume only one line will be change at a time */ bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, - (NIG_XGXS0_LINK_STATUS | - NIG_SERDES0_LINK_STATUS | - NIG_STATUS_INTERRUPT_XGXS0_LINK10G)); - if (bp->link_up) { + (NIG_STATUS_XGXS0_LINK10G | + NIG_STATUS_XGXS0_LINK_STATUS | + NIG_STATUS_SERDES0_LINK_STATUS)); + if (bp->phy_link_up) { if (is_10g) { /* Disable the 10G link interrupt * by writing 1 to the status register */ - DP(NETIF_MSG_LINK, "10G XGXS link up\n"); + DP(NETIF_MSG_LINK, "10G XGXS phy link up\n"); bnx2x_bits_en(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, - NIG_STATUS_INTERRUPT_XGXS0_LINK10G); + NIG_STATUS_XGXS0_LINK10G); } else if (bp->phy_flags & PHY_XGXS_FLAG) { /* Disable the link interrupt * by writing 1 to the relevant lane * in the status register */ - DP(NETIF_MSG_LINK, "1G XGXS link up\n"); + DP(NETIF_MSG_LINK, "1G XGXS phy link up\n"); bnx2x_bits_en(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, ((1 << bp->ser_lane) << - NIG_XGXS0_LINK_STATUS_SIZE)); + NIG_STATUS_XGXS0_LINK_STATUS_SIZE)); } else { /* SerDes */ - DP(NETIF_MSG_LINK, "SerDes link up\n"); + DP(NETIF_MSG_LINK, "SerDes phy link up\n"); /* Disable the link interrupt * by writing 1 to the status register */ bnx2x_bits_en(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, - NIG_SERDES0_LINK_STATUS); + NIG_STATUS_SERDES0_LINK_STATUS); } } else { /* link_down */ @@ -1724,91 +1979,182 @@ static int bnx2x_ext_phy_is_link_up(struct bnx2x *bp) { u32 ext_phy_type; u32 ext_phy_addr; - u32 local_phy; - u32 val = 0; + u32 val1 = 0, val2; u32 rx_sd, pcs_status; if (bp->phy_flags & PHY_XGXS_FLAG) { - local_phy = bp->phy_addr; ext_phy_addr = ((bp->ext_phy_config & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); - bp->phy_addr = (u8)ext_phy_addr; ext_phy_type = XGXS_EXT_PHY_TYPE(bp); switch (ext_phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: DP(NETIF_MSG_LINK, "XGXS Direct\n"); - val = 1; + val1 = 1; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: DP(NETIF_MSG_LINK, "XGXS 8705\n"); - bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD, - EXT_PHY_OPT_LASI_STATUS, &val); - DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val); - - bnx2x_mdio45_read(bp, EXT_PHY_OPT_WIS_DEVAD, - EXT_PHY_OPT_LASI_STATUS, &val); - DP(NETIF_MSG_LINK, "8705 LASI status is %d\n", val); - - bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_WIS_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); + + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_WIS_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); + + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_PMD_RX_SD, &rx_sd); - val = (rx_sd & 0x1); + DP(NETIF_MSG_LINK, "8705 rx_sd 0x%x\n", rx_sd); + val1 = (rx_sd & 0x1); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: DP(NETIF_MSG_LINK, "XGXS 8706\n"); - bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, - EXT_PHY_OPT_LASI_STATUS, &val); - DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val); - - bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, - EXT_PHY_OPT_LASI_STATUS, &val); - DP(NETIF_MSG_LINK, "8706 LASI status is %d\n", val); - - bnx2x_mdio45_read(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); + + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); + + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_PMD_RX_SD, &rx_sd); - bnx2x_mdio45_read(bp, EXT_PHY_OPT_PCS_DEVAD, - EXT_PHY_OPT_PCS_STATUS, &pcs_status); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PCS_DEVAD, + EXT_PHY_OPT_PCS_STATUS, &pcs_status); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_AN_LINK_STATUS, &val2); + DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x" - " pcs_status 0x%x\n", rx_sd, pcs_status); - /* link is up if both bit 0 of pmd_rx and - * bit 0 of pcs_status are set + " pcs_status 0x%x 1Gbps link_status 0x%x 0x%x\n", + rx_sd, pcs_status, val2, (val2 & (1<<1))); + /* link is up if both bit 0 of pmd_rx_sd and + * bit 0 of pcs_status are set, or if the autoneg bit + 1 is set */ - val = (rx_sd & pcs_status); + val1 = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1))); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); + + /* clear the interrupt LASI status register */ + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PCS_DEVAD, + EXT_PHY_KR_LASI_STATUS, &val2); + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PCS_DEVAD, + EXT_PHY_KR_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, "KR LASI status 0x%x->0x%x\n", + val2, val1); + /* Check the LASI */ + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0x9003, &val2); + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0x9003, &val1); + DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n", + val2, val1); + /* Check the link status */ + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PCS_DEVAD, + EXT_PHY_KR_PCS_STATUS, &val2); + DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2); + /* Check the link status on 1.1.2 */ + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_KR_STATUS, &val2); + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_KR_STATUS, &val1); + DP(NETIF_MSG_LINK, + "KR PMA status 0x%x->0x%x\n", val2, val1); + val1 = ((val1 & 4) == 4); + /* If 1G was requested assume the link is up */ + if (!(bp->req_autoneg & AUTONEG_SPEED) && + (bp->req_line_speed == SPEED_1000)) + val1 = 1; + bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val2); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_STATUS, &val1); + DP(NETIF_MSG_LINK, + "10G-base-T LASI status 0x%x->0x%x\n", val2, val1); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_KR_STATUS, &val2); + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_KR_STATUS, &val1); + DP(NETIF_MSG_LINK, + "10G-base-T PMA status 0x%x->0x%x\n", val2, val1); + val1 = ((val1 & 4) == 4); + /* if link is up + * print the AN outcome of the SFX7101 PHY + */ + if (val1) { + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + 0x21, &val2); + DP(NETIF_MSG_LINK, + "SFX7101 AN status 0x%x->%s\n", val2, + (val2 & (1<<14)) ? "Master" : "Slave"); + } break; default: DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", bp->ext_phy_config); - val = 0; + val1 = 0; break; } - bp->phy_addr = local_phy; } else { /* SerDes */ ext_phy_type = SERDES_EXT_PHY_TYPE(bp); switch (ext_phy_type) { case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT: DP(NETIF_MSG_LINK, "SerDes Direct\n"); - val = 1; + val1 = 1; break; case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: DP(NETIF_MSG_LINK, "SerDes 5482\n"); - val = 1; + val1 = 1; break; default: DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n", bp->ext_phy_config); - val = 0; + val1 = 0; break; } } - return val; + return val1; } static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) @@ -1819,7 +2165,7 @@ static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) u32 wb_write[2]; u32 val; - DP(NETIF_MSG_LINK, "enableing BigMAC\n"); + DP(NETIF_MSG_LINK, "enabling BigMAC\n"); /* reset and unreset the BigMac */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); @@ -1933,6 +2279,35 @@ static void bnx2x_bmac_enable(struct bnx2x *bp, int is_lb) bp->stats_state = STATS_STATE_ENABLE; } +static void bnx2x_bmac_rx_disable(struct bnx2x *bp) +{ + int port = bp->port; + u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : + NIG_REG_INGRESS_BMAC0_MEM; + u32 wb_write[2]; + + /* Only if the bmac is out of reset */ + if (REG_RD(bp, MISC_REG_RESET_REG_2) & + (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)) { + /* Clear Rx Enable bit in BMAC_CONTROL register */ +#ifdef BNX2X_DMAE_RD + bnx2x_read_dmae(bp, bmac_addr + + BIGMAC_REGISTER_BMAC_CONTROL, 2); + wb_write[0] = *bnx2x_sp(bp, wb_data[0]); + wb_write[1] = *bnx2x_sp(bp, wb_data[1]); +#else + wb_write[0] = REG_RD(bp, + bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL); + wb_write[1] = REG_RD(bp, + bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL + 4); +#endif + wb_write[0] &= ~BMAC_CONTROL_RX_ENABLE; + REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, + wb_write, 2); + msleep(1); + } +} + static void bnx2x_emac_enable(struct bnx2x *bp) { int port = bp->port; @@ -1940,7 +2315,7 @@ static void bnx2x_emac_enable(struct bnx2x *bp) u32 val; int timeout; - DP(NETIF_MSG_LINK, "enableing EMAC\n"); + DP(NETIF_MSG_LINK, "enabling EMAC\n"); /* reset and unreset the emac core */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port)); @@ -2033,7 +2408,7 @@ static void bnx2x_emac_enable(struct bnx2x *bp) EMAC_TX_MODE_EXT_PAUSE_EN); } - /* KEEP_VLAN_TAG, promiscous */ + /* KEEP_VLAN_TAG, promiscuous */ val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE); val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS; EMAC_WR(EMAC_REG_EMAC_RX_MODE, val); @@ -2161,7 +2536,6 @@ static void bnx2x_pbf_update(struct bnx2x *bp) u32 count = 1000; u32 pause = 0; - /* disable port */ REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1); @@ -2232,7 +2606,7 @@ static void bnx2x_pbf_update(struct bnx2x *bp) static void bnx2x_update_mng(struct bnx2x *bp) { if (!nomcp) - SHMEM_WR(bp, drv_fw_mb[bp->port].link_status, + SHMEM_WR(bp, port_mb[bp->port].link_status, bp->link_status); } @@ -2294,19 +2668,19 @@ static void bnx2x_link_down(struct bnx2x *bp) DP(BNX2X_MSG_STATS, "stats_state - STOP\n"); } - /* indicate link down */ + /* indicate no mac active */ bp->phy_flags &= ~(PHY_BMAC_FLAG | PHY_EMAC_FLAG); - /* reset BigMac */ - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, - (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); + /* update shared memory */ + bnx2x_update_mng(bp); - /* ignore drain flag interrupt */ /* activate nig drain */ NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); - /* update shared memory */ - bnx2x_update_mng(bp); + /* reset BigMac */ + bnx2x_bmac_rx_disable(bp); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, + (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); /* indicate link down */ bnx2x_link_report(bp); @@ -2317,14 +2691,15 @@ static void bnx2x_init_mac_stats(struct bnx2x *bp); /* This function is called upon link interrupt */ static void bnx2x_link_update(struct bnx2x *bp) { - u32 gp_status; int port = bp->port; int i; + u32 gp_status; int link_10g; - DP(NETIF_MSG_LINK, "port %x, is xgxs %x, stat_mask 0x%x," + DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x," " int_mask 0x%x, saved_mask 0x%x, MI_INT %x, SERDES_LINK %x," - " 10G %x, XGXS_LINK %x\n", port, (bp->phy_flags & PHY_XGXS_FLAG), + " 10G %x, XGXS_LINK %x\n", port, + (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4), REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), bp->nig_mask, REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), @@ -2336,7 +2711,7 @@ static void bnx2x_link_update(struct bnx2x *bp) might_sleep(); MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_GP_STATUS); /* avoid fast toggling */ - for (i = 0 ; i < 10 ; i++) { + for (i = 0; i < 10; i++) { msleep(10); bnx2x_mdio22_read(bp, MDIO_GP_STATUS_TOP_AN_STATUS1, &gp_status); @@ -2351,7 +2726,8 @@ static void bnx2x_link_update(struct bnx2x *bp) bnx2x_link_int_ack(bp, link_10g); /* link is up only if both local phy and external phy are up */ - if (bp->link_up && bnx2x_ext_phy_is_link_up(bp)) { + bp->link_up = (bp->phy_link_up && bnx2x_ext_phy_is_link_up(bp)); + if (bp->link_up) { if (link_10g) { bnx2x_bmac_enable(bp, 0); bnx2x_leds_set(bp, SPEED_10000); @@ -2427,7 +2803,9 @@ static void bnx2x_reset_unicore(struct bnx2x *bp) } } - BNX2X_ERR("BUG! unicore is still in reset!\n"); + BNX2X_ERR("BUG! %s (0x%x) is still in reset!\n", + (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", + bp->phy_addr); } static void bnx2x_set_swap_lanes(struct bnx2x *bp) @@ -2475,12 +2853,12 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp) MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_10G_PARALLEL_DETECT); bnx2x_mdio22_write(bp, - MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK, + MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT); bnx2x_mdio22_read(bp, - MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, - &control2); + MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, + &control2); if (bp->autoneg & AUTONEG_PARALLEL) { control2 |= @@ -2490,8 +2868,14 @@ static void bnx2x_set_parallel_detection(struct bnx2x *bp) ~MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN; } bnx2x_mdio22_write(bp, - MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, - control2); + MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, + control2); + + /* Disable parallel detection of HiG */ + MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_XGXS_BLOCK2); + bnx2x_mdio22_write(bp, MDIO_XGXS_BLOCK2_UNICORE_MODE_10G, + MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS | + MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS); } } @@ -2625,7 +3009,7 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x *bp) MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_OVER_1G); /* set extended capabilities */ - if (bp->advertising & ADVERTISED_2500baseT_Full) + if (bp->advertising & ADVERTISED_2500baseX_Full) val |= MDIO_OVER_1G_UP1_2_5G; if (bp->advertising & ADVERTISED_10000baseT_Full) val |= MDIO_OVER_1G_UP1_10G; @@ -2641,20 +3025,91 @@ static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x *bp) /* for AN, we are always publishing full duplex */ an_adv = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; - /* set pause */ - switch (bp->pause_mode) { - case PAUSE_SYMMETRIC: - an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC; - break; - case PAUSE_ASYMMETRIC: - an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; - break; - case PAUSE_BOTH: - an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; - break; - case PAUSE_NONE: - an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; - break; + /* resolve pause mode and advertisement + * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ + if (bp->req_autoneg & AUTONEG_FLOW_CTRL) { + switch (bp->req_flow_ctrl) { + case FLOW_CTRL_AUTO: + if (bp->dev->mtu <= 4500) { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; + bp->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + } else { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; + bp->advertising |= ADVERTISED_Asym_Pause; + } + break; + + case FLOW_CTRL_TX: + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; + bp->advertising |= ADVERTISED_Asym_Pause; + break; + + case FLOW_CTRL_RX: + if (bp->dev->mtu <= 4500) { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; + bp->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + } else { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; + bp->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + } + break; + + case FLOW_CTRL_BOTH: + if (bp->dev->mtu <= 4500) { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; + bp->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + } else { + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; + bp->advertising |= ADVERTISED_Asym_Pause; + } + break; + + case FLOW_CTRL_NONE: + default: + an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; + bp->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + break; + } + } else { /* forced mode */ + switch (bp->req_flow_ctrl) { + case FLOW_CTRL_AUTO: + DP(NETIF_MSG_LINK, "req_flow_ctrl 0x%x while" + " req_autoneg 0x%x\n", + bp->req_flow_ctrl, bp->req_autoneg); + break; + + case FLOW_CTRL_TX: + an_adv |= + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; + bp->advertising |= ADVERTISED_Asym_Pause; + break; + + case FLOW_CTRL_RX: + case FLOW_CTRL_BOTH: + an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; + bp->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + break; + + case FLOW_CTRL_NONE: + default: + an_adv |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; + bp->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + break; + } } MDIO_SET_REG_BANK(bp, MDIO_REG_BANK_COMBO_IEEE0); @@ -2752,47 +3207,162 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x *bp) static void bnx2x_link_int_enable(struct bnx2x *bp) { int port = bp->port; + u32 ext_phy_type; + u32 mask; /* setting the status to report on link up for either XGXS or SerDes */ bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, - (NIG_XGXS0_LINK_STATUS | - NIG_STATUS_INTERRUPT_XGXS0_LINK10G | - NIG_SERDES0_LINK_STATUS)); + (NIG_STATUS_XGXS0_LINK10G | + NIG_STATUS_XGXS0_LINK_STATUS | + NIG_STATUS_SERDES0_LINK_STATUS)); if (bp->phy_flags & PHY_XGXS_FLAG) { - /* TBD - - * in force mode (not AN) we can enable just the relevant - * interrupt - * Even in AN we might enable only one according to the AN - * speed mask - */ - bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, - (NIG_MASK_XGXS0_LINK_STATUS | - NIG_MASK_XGXS0_LINK10G)); - DP(NETIF_MSG_LINK, "enable XGXS interrupt\n"); + mask = (NIG_MASK_XGXS0_LINK10G | + NIG_MASK_XGXS0_LINK_STATUS); + DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n"); + ext_phy_type = XGXS_EXT_PHY_TYPE(bp); + if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && + (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) && + (ext_phy_type != + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) { + mask |= NIG_MASK_MI_INT; + DP(NETIF_MSG_LINK, "enabled external phy int\n"); + } } else { /* SerDes */ - bnx2x_bits_en(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, - NIG_MASK_SERDES0_LINK_STATUS); - DP(NETIF_MSG_LINK, "enable SerDes interrupt\n"); + mask = NIG_MASK_SERDES0_LINK_STATUS; + DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n"); + ext_phy_type = SERDES_EXT_PHY_TYPE(bp); + if ((ext_phy_type != + PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && + (ext_phy_type != + PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) { + mask |= NIG_MASK_MI_INT; + DP(NETIF_MSG_LINK, "enabled external phy int\n"); + } } + bnx2x_bits_en(bp, + NIG_REG_MASK_INTERRUPT_PORT0 + port*4, + mask); + DP(NETIF_MSG_LINK, "port %x, %s, int_status 0x%x," + " int_mask 0x%x, MI_INT %x, SERDES_LINK %x," + " 10G %x, XGXS_LINK %x\n", port, + (bp->phy_flags & PHY_XGXS_FLAG)? "XGXS":"SerDes", + REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4), + REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), + REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), + REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c), + REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), + REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68) + ); +} + +static void bnx2x_bcm8072_external_rom_boot(struct bnx2x *bp) +{ + u32 ext_phy_addr = ((bp->ext_phy_config & + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); + u32 fw_ver1, fw_ver2; + + /* Need to wait 200ms after reset */ + msleep(200); + /* Boot port from external ROM + * Set ser_boot_ctl bit in the MISC_CTRL1 register + */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + EXT_PHY_KR_MISC_CTRL1, 0x0001); + + /* Reset internal microprocessor */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, + EXT_PHY_KR_ROM_RESET_INTERNAL_MP); + /* set micro reset = 0 */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, + EXT_PHY_KR_ROM_MICRO_RESET); + /* Reset internal microprocessor */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_GEN_CTRL, + EXT_PHY_KR_ROM_RESET_INTERNAL_MP); + /* wait for 100ms for code download via SPI port */ + msleep(100); + + /* Clear ser_boot_ctl bit */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + EXT_PHY_KR_MISC_CTRL1, 0x0000); + /* Wait 100ms */ + msleep(100); + + /* Print the PHY FW version */ + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0xca19, &fw_ver1); + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0xca1a, &fw_ver2); + DP(NETIF_MSG_LINK, + "8072 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2); +} + +static void bnx2x_bcm8072_force_10G(struct bnx2x *bp) +{ + u32 ext_phy_addr = ((bp->ext_phy_config & + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); + + /* Force KR or KX */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL, + 0x2040); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_CTRL2, + 0x000b); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, EXT_PHY_KR_PMD_CTRL, + 0x0000); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, EXT_PHY_KR_CTRL, + 0x0000); } static void bnx2x_ext_phy_init(struct bnx2x *bp) { - int port = bp->port; u32 ext_phy_type; u32 ext_phy_addr; - u32 local_phy; + u32 cnt; + u32 ctrl; + u32 val = 0; if (bp->phy_flags & PHY_XGXS_FLAG) { - local_phy = bp->phy_addr; ext_phy_addr = ((bp->ext_phy_config & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); ext_phy_type = XGXS_EXT_PHY_TYPE(bp); + /* Make sure that the soft reset is off (expect for the 8072: + * due to the lock, it will be done inside the specific + * handling) + */ + if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && + (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) && + (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) && + (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)) { + /* Wait for soft reset to get cleared upto 1 sec */ + for (cnt = 0; cnt < 1000; cnt++) { + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_CNTL, &ctrl); + if (!(ctrl & (1<<15))) + break; + msleep(1); + } + DP(NETIF_MSG_LINK, + "control reg 0x%x (after %d ms)\n", ctrl, cnt); + } + switch (ext_phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: DP(NETIF_MSG_LINK, "XGXS Direct\n"); @@ -2800,49 +3370,235 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: DP(NETIF_MSG_LINK, "XGXS 8705\n"); - bnx2x_bits_en(bp, - NIG_REG_MASK_INTERRUPT_PORT0 + port*4, - NIG_MASK_MI_INT); - DP(NETIF_MSG_LINK, "enabled extenal phy int\n"); - bp->phy_addr = ext_phy_type; - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_PMD_MISC_CNTL, 0x8288); - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_PHY_IDENTIFIER, 0x7fbf); - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_CMU_PLL_BYPASS, 0x0100); - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_WIS_DEVAD, + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_WIS_DEVAD, EXT_PHY_OPT_LASI_CNTL, 0x1); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: DP(NETIF_MSG_LINK, "XGXS 8706\n"); - bnx2x_bits_en(bp, - NIG_REG_MASK_INTERRUPT_PORT0 + port*4, - NIG_MASK_MI_INT); - DP(NETIF_MSG_LINK, "enabled extenal phy int\n"); - - bp->phy_addr = ext_phy_type; - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, - EXT_PHY_OPT_PMD_DIGITAL_CNT, - 0x400); - bnx2x_mdio45_vwrite(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + + if (!(bp->req_autoneg & AUTONEG_SPEED)) { + /* Force speed */ + if (bp->req_line_speed == SPEED_10000) { + DP(NETIF_MSG_LINK, + "XGXS 8706 force 10Gbps\n"); + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_PMD_DIGITAL_CNT, + 0x400); + } else { + /* Force 1Gbps */ + DP(NETIF_MSG_LINK, + "XGXS 8706 force 1Gbps\n"); + + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_CNTL, + 0x0040); + + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_CNTL2, + 0x000D); + } + + /* Enable LASI */ + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_CNTL, + 0x1); + } else { + /* AUTONEG */ + /* Allow CL37 through CL73 */ + DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n"); + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_AN_CL37_CL73, + 0x040c); + + /* Enable Full-Duplex advertisment on CL37 */ + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_AN_CL37_FD, + 0x0020); + /* Enable CL37 AN */ + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_AN_CL37_AN, + 0x1000); + /* Advertise 10G/1G support */ + if (bp->advertising & + ADVERTISED_1000baseT_Full) + val = (1<<5); + if (bp->advertising & + ADVERTISED_10000baseT_Full) + val |= (1<<7); + + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_AN_ADV, val); + /* Enable LASI */ + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_LASI_CNTL, + 0x1); + + /* Enable clause 73 AN */ + bnx2x_mdio45_write(bp, ext_phy_addr, + EXT_PHY_AUTO_NEG_DEVAD, + EXT_PHY_OPT_CNTL, + 0x1200); + } + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); + /* Wait for soft reset to get cleared upto 1 sec */ + for (cnt = 0; cnt < 1000; cnt++) { + bnx2x_mdio45_ctrl_read(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + EXT_PHY_OPT_CNTL, &ctrl); + if (!(ctrl & (1<<15))) + break; + msleep(1); + } + DP(NETIF_MSG_LINK, + "8072 control reg 0x%x (after %d ms)\n", + ctrl, cnt); + + bnx2x_bcm8072_external_rom_boot(bp); + DP(NETIF_MSG_LINK, "Finshed loading 8072 KR ROM\n"); + + /* enable LASI */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0x9000, 0x0400); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + EXT_PHY_KR_LASI_CNTL, 0x0004); + + /* If this is forced speed, set to KR or KX + * (all other are not supported) + */ + if (!(bp->req_autoneg & AUTONEG_SPEED)) { + if (bp->req_line_speed == SPEED_10000) { + bnx2x_bcm8072_force_10G(bp); + DP(NETIF_MSG_LINK, + "Forced speed 10G on 8072\n"); + /* unlock */ + bnx2x_hw_unlock(bp, + HW_LOCK_RESOURCE_8072_MDIO); + break; + } else + val = (1<<5); + } else { + + /* Advertise 10G/1G support */ + if (bp->advertising & + ADVERTISED_1000baseT_Full) + val = (1<<5); + if (bp->advertising & + ADVERTISED_10000baseT_Full) + val |= (1<<7); + } + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + 0x11, val); + /* Add support for CL37 ( passive mode ) I */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + 0x8370, 0x040c); + /* Add support for CL37 ( passive mode ) II */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + 0xffe4, 0x20); + /* Add support for CL37 ( passive mode ) III */ + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + 0xffe0, 0x1000); + /* Restart autoneg */ + msleep(500); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_CTRL, 0x1200); + DP(NETIF_MSG_LINK, "8072 Autoneg Restart: " + "1G %ssupported 10G %ssupported\n", + (val & (1<<5)) ? "" : "not ", + (val & (1<<7)) ? "" : "not "); + + /* unlock */ + bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + DP(NETIF_MSG_LINK, + "Setting the SFX7101 LASI indication\n"); + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_LASI_CNTL, 0x1); + DP(NETIF_MSG_LINK, + "Setting the SFX7101 LED to blink on traffic\n"); + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, + 0xC007, (1<<3)); + + /* read modify write pause advertizing */ + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_AUTO_NEG_ADVERT, &val); + val &= ~EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_BOTH; + /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ + if (bp->advertising & ADVERTISED_Pause) + val |= EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE; + + if (bp->advertising & ADVERTISED_Asym_Pause) { + val |= + EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_ASYMMETRIC; + } + DP(NETIF_MSG_LINK, "SFX7101 AN advertize 0x%x\n", val); + bnx2x_mdio45_vwrite(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_AUTO_NEG_ADVERT, val); + /* Restart autoneg */ + bnx2x_mdio45_read(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_CTRL, &val); + val |= 0x200; + bnx2x_mdio45_write(bp, ext_phy_addr, + EXT_PHY_KR_AUTO_NEG_DEVAD, + EXT_PHY_KR_CTRL, val); break; default: - DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", - bp->ext_phy_config); + BNX2X_ERR("BAD XGXS ext_phy_config 0x%x\n", + bp->ext_phy_config); break; } - bp->phy_addr = local_phy; } else { /* SerDes */ -/* ext_phy_addr = ((bp->ext_phy_config & +/* ext_phy_addr = ((bp->ext_phy_config & PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK) >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT); */ @@ -2854,10 +3610,6 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: DP(NETIF_MSG_LINK, "SerDes 5482\n"); - bnx2x_bits_en(bp, - NIG_REG_MASK_INTERRUPT_PORT0 + port*4, - NIG_MASK_MI_INT); - DP(NETIF_MSG_LINK, "enabled extenal phy int\n"); break; default: @@ -2871,8 +3623,22 @@ static void bnx2x_ext_phy_init(struct bnx2x *bp) static void bnx2x_ext_phy_reset(struct bnx2x *bp) { u32 ext_phy_type; - u32 ext_phy_addr; - u32 local_phy; + u32 ext_phy_addr = ((bp->ext_phy_config & + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> + PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); + u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK); + + /* The PHY reset is controled by GPIO 1 + * Give it 1ms of reset pulse + */ + if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) && + (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) { + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, + MISC_REGISTERS_GPIO_OUTPUT_LOW); + msleep(1); + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, + MISC_REGISTERS_GPIO_OUTPUT_HIGH); + } if (bp->phy_flags & PHY_XGXS_FLAG) { ext_phy_type = XGXS_EXT_PHY_TYPE(bp); @@ -2883,15 +3649,24 @@ static void bnx2x_ext_phy_reset(struct bnx2x *bp) case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: - DP(NETIF_MSG_LINK, "XGXS 8705/6\n"); - local_phy = bp->phy_addr; - ext_phy_addr = ((bp->ext_phy_config & - PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> - PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); - bp->phy_addr = (u8)ext_phy_addr; - bnx2x_mdio45_write(bp, EXT_PHY_OPT_PMA_PMD_DEVAD, + DP(NETIF_MSG_LINK, "XGXS 8705/8706\n"); + bnx2x_mdio45_write(bp, ext_phy_addr, + EXT_PHY_OPT_PMA_PMD_DEVAD, EXT_PHY_OPT_CNTL, 0xa040); - bp->phy_addr = local_phy; + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + DP(NETIF_MSG_LINK, "XGXS 8072\n"); + bnx2x_hw_lock(bp, HW_LOCK_RESOURCE_8072_MDIO); + bnx2x_mdio45_ctrl_write(bp, GRCBASE_EMAC0, + ext_phy_addr, + EXT_PHY_KR_PMA_PMD_DEVAD, + 0, 1<<15); + bnx2x_hw_unlock(bp, HW_LOCK_RESOURCE_8072_MDIO); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + DP(NETIF_MSG_LINK, "XGXS SFX7101\n"); break; default: @@ -2930,6 +3705,7 @@ static void bnx2x_link_initialize(struct bnx2x *bp) NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT)); + /* Activate the external PHY */ bnx2x_ext_phy_reset(bp); bnx2x_set_aer_mmd(bp); @@ -2994,13 +3770,13 @@ static void bnx2x_link_initialize(struct bnx2x *bp) /* AN enabled */ bnx2x_set_brcm_cl37_advertisment(bp); - /* program duplex & pause advertisment (for aneg) */ + /* program duplex & pause advertisement (for aneg) */ bnx2x_set_ieee_aneg_advertisment(bp); /* enable autoneg */ bnx2x_set_autoneg(bp); - /* enalbe and restart AN */ + /* enable and restart AN */ bnx2x_restart_autoneg(bp); } @@ -3010,11 +3786,11 @@ static void bnx2x_link_initialize(struct bnx2x *bp) bnx2x_initialize_sgmii_process(bp); } - /* enable the interrupt */ - bnx2x_link_int_enable(bp); - /* init ext phy and enable link state int */ bnx2x_ext_phy_init(bp); + + /* enable the interrupt */ + bnx2x_link_int_enable(bp); } static void bnx2x_phy_deassert(struct bnx2x *bp) @@ -3073,6 +3849,11 @@ static int bnx2x_phy_init(struct bnx2x *bp) static void bnx2x_link_reset(struct bnx2x *bp) { int port = bp->port; + u32 board = (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK); + + /* update shared memory */ + bp->link_status = 0; + bnx2x_update_mng(bp); /* disable attentions */ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, @@ -3081,21 +3862,45 @@ static void bnx2x_link_reset(struct bnx2x *bp) NIG_MASK_SERDES0_LINK_STATUS | NIG_MASK_MI_INT)); - bnx2x_ext_phy_reset(bp); + /* activate nig drain */ + NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); + + /* disable nig egress interface */ + NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0); + NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); + + /* Stop BigMac rx */ + bnx2x_bmac_rx_disable(bp); + + /* disable emac */ + NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0); + + msleep(10); + + /* The PHY reset is controled by GPIO 1 + * Hold it as output low + */ + if ((board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1002G) && + (board != SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G)) { + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, + MISC_REGISTERS_GPIO_OUTPUT_LOW); + DP(NETIF_MSG_LINK, "reset external PHY\n"); + } /* reset the SerDes/XGXS */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, (0x1ff << (port*16))); - /* reset EMAC / BMAC and disable NIG interfaces */ - NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0); - NIG_WR(NIG_REG_BMAC0_OUT_EN + port*4, 0); + /* reset BigMac */ + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, + (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); - NIG_WR(NIG_REG_NIG_EMAC0_EN + port*4, 0); + /* disable nig ingress interface */ + NIG_WR(NIG_REG_BMAC0_IN_EN + port*4, 0); NIG_WR(NIG_REG_EMAC0_IN_EN + port*4, 0); - NIG_WR(NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); - NIG_WR(NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); + /* set link down */ + bp->link_up = 0; } #ifdef BNX2X_XGXS_LB @@ -3158,7 +3963,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, int port = bp->port; DP(NETIF_MSG_TIMER, - "spe (%x:%x) command %x hw_cid %x data (%x:%x) left %x\n", + "spe (%x:%x) command %d hw_cid %x data (%x:%x) left %x\n", (u32)U64_HI(bp->spq_mapping), (u32)(U64_LO(bp->spq_mapping) + (void *)bp->spq_prod_bd - (void *)bp->spq), command, HW_CID(bp, cid), data_hi, data_lo, bp->spq_left); @@ -3176,6 +3981,7 @@ static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, bnx2x_panic(); return -EBUSY; } + /* CID needs port number to be encoded int it */ bp->spq_prod_bd->hdr.conn_and_cmd_data = cpu_to_le32(((command << SPE_HDR_CMD_ID_SHIFT) | @@ -3282,8 +4088,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) u32 igu_addr = (IGU_ADDR_ATTN_BITS_SET + IGU_PORT_BASE * port) * 8; u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : MISC_REG_AEU_MASK_ATTN_FUNC_0; - u32 nig_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 : - NIG_REG_MASK_INTERRUPT_PORT0; + u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 : + NIG_REG_MASK_INTERRUPT_PORT0; if (~bp->aeu_mask & (asserted & 0xff)) BNX2X_ERR("IGU ERROR\n"); @@ -3301,15 +4107,11 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) if (asserted & ATTN_HARD_WIRED_MASK) { if (asserted & ATTN_NIG_FOR_FUNC) { - u32 nig_status_port; - u32 nig_int_addr = port ? - NIG_REG_STATUS_INTERRUPT_PORT1 : - NIG_REG_STATUS_INTERRUPT_PORT0; - bp->nig_mask = REG_RD(bp, nig_mask_addr); - REG_WR(bp, nig_mask_addr, 0); + /* save nig interrupt mask */ + bp->nig_mask = REG_RD(bp, nig_int_mask_addr); + REG_WR(bp, nig_int_mask_addr, 0); - nig_status_port = REG_RD(bp, nig_int_addr); bnx2x_link_update(bp); /* handle unicore attn? */ @@ -3362,15 +4164,132 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) /* now set back the mask */ if (asserted & ATTN_NIG_FOR_FUNC) - REG_WR(bp, nig_mask_addr, bp->nig_mask); + REG_WR(bp, nig_int_mask_addr, bp->nig_mask); } -static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) +static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) { int port = bp->port; - int index; + int reg_offset; + u32 val; + + if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) { + + reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : + MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); + + val = REG_RD(bp, reg_offset); + val &= ~AEU_INPUTS_ATTN_BITS_SPIO5; + REG_WR(bp, reg_offset, val); + + BNX2X_ERR("SPIO5 hw attention\n"); + + switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: + /* Fan failure attention */ + + /* The PHY reset is controled by GPIO 1 */ + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, + MISC_REGISTERS_GPIO_OUTPUT_LOW); + /* Low power mode is controled by GPIO 2 */ + bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, + MISC_REGISTERS_GPIO_OUTPUT_LOW); + /* mark the failure */ + bp->ext_phy_config &= + ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK; + bp->ext_phy_config |= + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE; + SHMEM_WR(bp, + dev_info.port_hw_config[port]. + external_phy_config, + bp->ext_phy_config); + /* log the failure */ + printk(KERN_ERR PFX "Fan Failure on Network" + " Controller %s has caused the driver to" + " shutdown the card to prevent permanent" + " damage. Please contact Dell Support for" + " assistance\n", bp->dev->name); + break; + + default: + break; + } + } +} + +static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn) +{ + u32 val; + + if (attn & BNX2X_DOORQ_ASSERT) { + + val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR); + BNX2X_ERR("DB hw attention 0x%x\n", val); + /* DORQ discard attention */ + if (val & 0x2) + BNX2X_ERR("FATAL error from DORQ\n"); + } +} + +static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn) +{ + u32 val; + + if (attn & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) { + + val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR); + BNX2X_ERR("CFC hw attention 0x%x\n", val); + /* CFC error attention */ + if (val & 0x2) + BNX2X_ERR("FATAL error from CFC\n"); + } + + if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) { + + val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0); + BNX2X_ERR("PXP hw attention 0x%x\n", val); + /* RQ_USDMDP_FIFO_OVERFLOW */ + if (val & 0x18000) + BNX2X_ERR("FATAL error from PXP\n"); + } +} + +static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) +{ + if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) { + + if (attn & BNX2X_MC_ASSERT_BITS) { + + BNX2X_ERR("MC assert!\n"); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_7, 0); + bnx2x_panic(); + + } else if (attn & BNX2X_MCP_ASSERT) { + + BNX2X_ERR("MCP assert!\n"); + REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_11, 0); + bnx2x_mc_assert(bp); + + } else + BNX2X_ERR("Unknown HW assert! (attn 0x%x)\n", attn); + } + + if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) { + + REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff); + BNX2X_ERR("LATCHED attention 0x%x (masked)\n", attn); + } +} + +static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) +{ struct attn_route attn; struct attn_route group_mask; + int port = bp->port; + int index; u32 reg_addr; u32 val; @@ -3391,64 +4310,14 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) DP(NETIF_MSG_HW, "group[%d]: %llx\n", index, (unsigned long long)group_mask.sig[0]); - if (attn.sig[3] & group_mask.sig[3] & - EVEREST_GEN_ATTN_IN_USE_MASK) { - - if (attn.sig[3] & BNX2X_MC_ASSERT_BITS) { - - BNX2X_ERR("MC assert!\n"); - bnx2x_panic(); - - } else if (attn.sig[3] & BNX2X_MCP_ASSERT) { - - BNX2X_ERR("MCP assert!\n"); - REG_WR(bp, - MISC_REG_AEU_GENERAL_ATTN_11, 0); - bnx2x_mc_assert(bp); - - } else { - BNX2X_ERR("UNKOWEN HW ASSERT!\n"); - } - } - - if (attn.sig[1] & group_mask.sig[1] & - BNX2X_DOORQ_ASSERT) { - - val = REG_RD(bp, DORQ_REG_DORQ_INT_STS_CLR); - BNX2X_ERR("DB hw attention 0x%x\n", val); - /* DORQ discard attention */ - if (val & 0x2) - BNX2X_ERR("FATAL error from DORQ\n"); - } - - if (attn.sig[2] & group_mask.sig[2] & - AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) { - - val = REG_RD(bp, CFC_REG_CFC_INT_STS_CLR); - BNX2X_ERR("CFC hw attention 0x%x\n", val); - /* CFC error attention */ - if (val & 0x2) - BNX2X_ERR("FATAL error from CFC\n"); - } - - if (attn.sig[2] & group_mask.sig[2] & - AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) { - - val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0); - BNX2X_ERR("PXP hw attention 0x%x\n", val); - /* RQ_USDMDP_FIFO_OVERFLOW */ - if (val & 0x18000) - BNX2X_ERR("FATAL error from PXP\n"); - } - - if (attn.sig[3] & group_mask.sig[3] & - EVEREST_LATCHED_ATTN_IN_USE_MASK) { - - REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, - 0x7ff); - DP(NETIF_MSG_HW, "got latched bits 0x%x\n", - attn.sig[3]); - } + bnx2x_attn_int_deasserted3(bp, + attn.sig[3] & group_mask.sig[3]); + bnx2x_attn_int_deasserted1(bp, + attn.sig[1] & group_mask.sig[1]); + bnx2x_attn_int_deasserted2(bp, + attn.sig[2] & group_mask.sig[2]); + bnx2x_attn_int_deasserted0(bp, + attn.sig[0] & group_mask.sig[0]); if ((attn.sig[0] & group_mask.sig[0] & HW_INTERRUT_ASSERT_SET_0) || @@ -3456,7 +4325,15 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) HW_INTERRUT_ASSERT_SET_1) || (attn.sig[2] & group_mask.sig[2] & HW_INTERRUT_ASSERT_SET_2)) - BNX2X_ERR("FATAL HW block attention\n"); + BNX2X_ERR("FATAL HW block attention" + " set0 0x%x set1 0x%x" + " set2 0x%x\n", + (attn.sig[0] & group_mask.sig[0] & + HW_INTERRUT_ASSERT_SET_0), + (attn.sig[1] & group_mask.sig[1] & + HW_INTERRUT_ASSERT_SET_1), + (attn.sig[2] & group_mask.sig[2] & + HW_INTERRUT_ASSERT_SET_2)); if ((attn.sig[0] & group_mask.sig[0] & HW_PRTY_ASSERT_SET_0) || @@ -3464,7 +4341,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) HW_PRTY_ASSERT_SET_1) || (attn.sig[2] & group_mask.sig[2] & HW_PRTY_ASSERT_SET_2)) - BNX2X_ERR("FATAL HW block parity atention\n"); + BNX2X_ERR("FATAL HW block parity attention\n"); } } @@ -3529,7 +4406,7 @@ static void bnx2x_sp_task(struct work_struct *work) /* Return here if interrupt is disabled */ if (unlikely(atomic_read(&bp->intr_sem) != 0)) { - DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); + DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n"); return; } @@ -3539,12 +4416,11 @@ static void bnx2x_sp_task(struct work_struct *work) DP(NETIF_MSG_INTR, "got a slowpath interrupt (updated %x)\n", status); - if (status & 0x1) { - /* HW attentions */ + /* HW attentions */ + if (status & 0x1) bnx2x_attn_int(bp); - } - /* CStorm events: query_stats, cfc delete ramrods */ + /* CStorm events: query_stats, port delete ramrod */ if (status & 0x2) bp->stat_pending = 0; @@ -3558,6 +4434,7 @@ static void bnx2x_sp_task(struct work_struct *work) IGU_INT_NOP, 1); bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx), IGU_INT_ENABLE, 1); + } static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) @@ -3567,11 +4444,11 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) /* Return here if interrupt is disabled */ if (unlikely(atomic_read(&bp->intr_sem) != 0)) { - DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n"); + DP(BNX2X_MSG_SP, "called but intr_sem not 0, returning\n"); return IRQ_HANDLED; } - bnx2x_ack_sb(bp, 16, XSTORM_ID, 0, IGU_INT_DISABLE, 0); + bnx2x_ack_sb(bp, DEF_SB_ID, XSTORM_ID, 0, IGU_INT_DISABLE, 0); #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -3906,7 +4783,7 @@ static void bnx2x_stop_stats(struct bnx2x *bp) while (bp->stats_state != STATS_STATE_DISABLE) { if (!timeout) { - BNX2X_ERR("timeout wating for stats stop\n"); + BNX2X_ERR("timeout waiting for stats stop\n"); break; } timeout--; @@ -4173,39 +5050,37 @@ static void bnx2x_update_net_stats(struct bnx2x *bp) nstats->rx_bytes = bnx2x_hilo(&estats->total_bytes_received_hi); - nstats->tx_bytes = - bnx2x_hilo(&estats->total_bytes_transmitted_hi); + nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi); - nstats->rx_dropped = estats->checksum_discard + - estats->mac_discard; + nstats->rx_dropped = estats->checksum_discard + estats->mac_discard; nstats->tx_dropped = 0; nstats->multicast = bnx2x_hilo(&estats->total_multicast_packets_transmitted_hi); - nstats->collisions = - estats->single_collision_transmit_frames + - estats->multiple_collision_transmit_frames + - estats->late_collision_frames + - estats->excessive_collision_frames; + nstats->collisions = estats->single_collision_transmit_frames + + estats->multiple_collision_transmit_frames + + estats->late_collision_frames + + estats->excessive_collision_frames; nstats->rx_length_errors = estats->runt_packets_received + estats->jabber_packets_received; - nstats->rx_over_errors = estats->no_buff_discard; + nstats->rx_over_errors = estats->brb_discard + + estats->brb_truncate_discard; nstats->rx_crc_errors = estats->crc_receive_errors; nstats->rx_frame_errors = estats->alignment_errors; - nstats->rx_fifo_errors = estats->brb_discard + - estats->brb_truncate_discard; + nstats->rx_fifo_errors = estats->no_buff_discard; nstats->rx_missed_errors = estats->xxoverflow_discard; nstats->rx_errors = nstats->rx_length_errors + nstats->rx_over_errors + nstats->rx_crc_errors + nstats->rx_frame_errors + - nstats->rx_fifo_errors; + nstats->rx_fifo_errors + + nstats->rx_missed_errors; nstats->tx_aborted_errors = estats->late_collision_frames + - estats->excessive_collision_frames; + estats->excessive_collision_frames; nstats->tx_carrier_errors = estats->false_carrier_detections; nstats->tx_fifo_errors = 0; nstats->tx_heartbeat_errors = 0; @@ -4334,7 +5209,7 @@ static void bnx2x_timer(unsigned long data) return; if (atomic_read(&bp->intr_sem) != 0) - goto bnx2x_restart_timer; + goto timer_restart; if (poll) { struct bnx2x_fastpath *fp = &bp->fp[0]; @@ -4344,7 +5219,7 @@ static void bnx2x_timer(unsigned long data) rc = bnx2x_rx_int(fp, 1000); } - if (!nomcp && (bp->bc_ver >= 0x040003)) { + if (!nomcp) { int port = bp->port; u32 drv_pulse; u32 mcp_pulse; @@ -4353,9 +5228,9 @@ static void bnx2x_timer(unsigned long data) bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK; /* TBD - add SYSTEM_TIME */ drv_pulse = bp->fw_drv_pulse_wr_seq; - SHMEM_WR(bp, drv_fw_mb[port].drv_pulse_mb, drv_pulse); + SHMEM_WR(bp, func_mb[port].drv_pulse_mb, drv_pulse); - mcp_pulse = (SHMEM_RD(bp, drv_fw_mb[port].mcp_pulse_mb) & + mcp_pulse = (SHMEM_RD(bp, func_mb[port].mcp_pulse_mb) & MCP_PULSE_SEQ_MASK); /* The delta between driver pulse and mcp response * should be 1 (before mcp response) or 0 (after mcp response) @@ -4369,11 +5244,11 @@ static void bnx2x_timer(unsigned long data) } if (bp->stats_state == STATS_STATE_DISABLE) - goto bnx2x_restart_timer; + goto timer_restart; bnx2x_update_stats(bp); -bnx2x_restart_timer: +timer_restart: mod_timer(&bp->timer, jiffies + bp->current_interval); } @@ -4438,6 +5313,9 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, atten_status_block); def_sb->atten_status_block.status_block_id = id; + bp->def_att_idx = 0; + bp->attn_state = 0; + reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); @@ -4472,6 +5350,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, u_def_status_block); def_sb->u_def_status_block.status_block_id = id; + bp->def_u_idx = 0; + REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section)); REG_WR(bp, BAR_USTRORM_INTMEM + @@ -4489,6 +5369,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, c_def_status_block); def_sb->c_def_status_block.status_block_id = id; + bp->def_c_idx = 0; + REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section)); REG_WR(bp, BAR_CSTRORM_INTMEM + @@ -4506,6 +5388,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, t_def_status_block); def_sb->t_def_status_block.status_block_id = id; + bp->def_t_idx = 0; + REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section)); REG_WR(bp, BAR_TSTRORM_INTMEM + @@ -4523,6 +5407,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, x_def_status_block); def_sb->x_def_status_block.status_block_id = id; + bp->def_x_idx = 0; + REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(port), U64_LO(section)); REG_WR(bp, BAR_XSTRORM_INTMEM + @@ -4535,6 +5421,8 @@ static void bnx2x_init_def_sb(struct bnx2x *bp, REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_DEF_SB_HC_DISABLE_OFFSET(port, index), 0x1); + bp->stat_pending = 0; + bnx2x_ack_sb(bp, id, CSTORM_ID, 0, IGU_INT_ENABLE, 0); } @@ -4626,7 +5514,7 @@ static void bnx2x_init_rx_rings(struct bnx2x *bp) fp->rx_bd_prod = fp->rx_comp_prod = ring_prod; fp->rx_pkt = fp->rx_calls = 0; - /* Warning! this will genrate an interrupt (to the TSTORM) */ + /* Warning! this will generate an interrupt (to the TSTORM) */ /* must only be done when chip is initialized */ REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_RCQ_PROD_OFFSET(port, j), ring_prod); @@ -4678,7 +5566,6 @@ static void bnx2x_init_sp_ring(struct bnx2x *bp) bp->spq_left = MAX_SPQ_PENDING; bp->spq_prod_idx = 0; - bp->dsb_sp_prod_idx = 0; bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX; bp->spq_prod_bd = bp->spq; bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT; @@ -4755,6 +5642,42 @@ static void bnx2x_init_ind_table(struct bnx2x *bp) REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); } +static void bnx2x_set_client_config(struct bnx2x *bp) +{ +#ifdef BCM_VLAN + int mode = bp->rx_mode; +#endif + int i, port = bp->port; + struct tstorm_eth_client_config tstorm_client = {0}; + + tstorm_client.mtu = bp->dev->mtu; + tstorm_client.statistics_counter_id = 0; + tstorm_client.config_flags = + TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; +#ifdef BCM_VLAN + if (mode && bp->vlgrp) { + tstorm_client.config_flags |= + TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE; + DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); + } +#endif + if (mode != BNX2X_RX_MODE_PROMISC) + tstorm_client.drop_flags = + TSTORM_ETH_CLIENT_CONFIG_DROP_MAC_ERR; + + for_each_queue(bp, i) { + REG_WR(bp, BAR_TSTRORM_INTMEM + + TSTORM_CLIENT_CONFIG_OFFSET(port, i), + ((u32 *)&tstorm_client)[0]); + REG_WR(bp, BAR_TSTRORM_INTMEM + + TSTORM_CLIENT_CONFIG_OFFSET(port, i) + 4, + ((u32 *)&tstorm_client)[1]); + } + +/* DP(NETIF_MSG_IFUP, "tstorm_client: 0x%08x 0x%08x\n", + ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]); */ +} + static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) { int mode = bp->rx_mode; @@ -4794,41 +5717,9 @@ static void bnx2x_set_storm_rx_mode(struct bnx2x *bp) /* DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i, ((u32 *)&tstorm_mac_filter)[i]); */ } -} -static void bnx2x_set_client_config(struct bnx2x *bp, int client_id) -{ -#ifdef BCM_VLAN - int mode = bp->rx_mode; -#endif - int port = bp->port; - struct tstorm_eth_client_config tstorm_client = {0}; - - tstorm_client.mtu = bp->dev->mtu; - tstorm_client.statistics_counter_id = 0; - tstorm_client.config_flags = - TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; -#ifdef BCM_VLAN - if (mode && bp->vlgrp) { - tstorm_client.config_flags |= - TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE; - DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); - } -#endif - tstorm_client.drop_flags = (TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR | - TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR | - TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR | - TSTORM_ETH_CLIENT_CONFIG_DROP_MAC_ERR); - - REG_WR(bp, BAR_TSTRORM_INTMEM + - TSTORM_CLIENT_CONFIG_OFFSET(port, client_id), - ((u32 *)&tstorm_client)[0]); - REG_WR(bp, BAR_TSTRORM_INTMEM + - TSTORM_CLIENT_CONFIG_OFFSET(port, client_id) + 4, - ((u32 *)&tstorm_client)[1]); - -/* DP(NETIF_MSG_IFUP, "tstorm_client: 0x%08x 0x%08x\n", - ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]); */ + if (mode != BNX2X_RX_MODE_NONE) + bnx2x_set_client_config(bp); } static void bnx2x_init_internal(struct bnx2x *bp) @@ -4836,7 +5727,6 @@ static void bnx2x_init_internal(struct bnx2x *bp) int port = bp->port; struct tstorm_eth_function_common_config tstorm_config = {0}; struct stats_indication_flags stats_flags = {0}; - int i; if (is_multi(bp)) { tstorm_config.config_flags = MULTI_FLAGS; @@ -4850,13 +5740,9 @@ static void bnx2x_init_internal(struct bnx2x *bp) /* DP(NETIF_MSG_IFUP, "tstorm_config: 0x%08x\n", (*(u32 *)&tstorm_config)); */ - bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx untill link is up */ + bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */ bnx2x_set_storm_rx_mode(bp); - for_each_queue(bp, i) - bnx2x_set_client_config(bp, i); - - stats_flags.collect_eth = cpu_to_le32(1); REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(port), @@ -4902,7 +5788,7 @@ static void bnx2x_nic_init(struct bnx2x *bp) bnx2x_init_internal(bp); bnx2x_init_stats(bp); bnx2x_init_ind_table(bp); - bnx2x_enable_int(bp); + bnx2x_int_enable(bp); } @@ -5265,8 +6151,10 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) if (mode & 0x1) { /* init common */ DP(BNX2X_MSG_MCP, "starting common init func %d mode %x\n", func, mode); - REG_WR(bp, MISC_REG_RESET_REG_1, 0xffffffff); - REG_WR(bp, MISC_REG_RESET_REG_2, 0xfffc); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, + 0xffffffff); + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, + 0xfffc); bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100); @@ -5359,7 +6247,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) REG_RD(bp, USEM_REG_PASSIVE_BUFFER + 8); #endif bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END); - /* softrest pulse */ + /* soft reset pulse */ REG_WR(bp, QM_REG_SOFT_RESET, 1); REG_WR(bp, QM_REG_SOFT_RESET, 0); @@ -5413,7 +6301,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) REG_WR(bp, SRC_REG_SOFT_RST, 1); for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) { REG_WR(bp, i, 0xc0cac01a); - /* TODO: repleace with something meaningfull */ + /* TODO: replace with something meaningful */ } /* SRCH COMMON comes here */ REG_WR(bp, SRC_REG_SOFT_RST, 0); @@ -5486,6 +6374,28 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) enable_blocks_attention(bp); /* enable_blocks_parity(bp); */ + switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: + /* Fan failure is indicated by SPIO 5 */ + bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5, + MISC_REGISTERS_SPIO_INPUT_HI_Z); + + /* set to active low mode */ + val = REG_RD(bp, MISC_REG_SPIO_INT); + val |= ((1 << MISC_REGISTERS_SPIO_5) << + MISC_REGISTERS_SPIO_INT_OLD_SET_POS); + REG_WR(bp, MISC_REG_SPIO_INT, val); + + /* enable interrupt to signal the IGU */ + val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN); + val |= (1 << MISC_REGISTERS_SPIO_5); + REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val); + break; + + default: + break; + } + } /* end of common init */ /* per port init */ @@ -5645,9 +6555,21 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) /* Port MCP comes here */ /* Port DMAE comes here */ + switch (bp->board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: + /* add SPIO 5 to group 0 */ + val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); + val |= AEU_INPUTS_ATTN_BITS_SPIO5; + REG_WR(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, val); + break; + + default: + break; + } + bnx2x_link_reset(bp); - /* Reset pciex errors for debug */ + /* Reset PCIE errors for debug */ REG_WR(bp, 0x2114, 0xffffffff); REG_WR(bp, 0x2120, 0xffffffff); REG_WR(bp, 0x2814, 0xffffffff); @@ -5669,9 +6591,9 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) port = bp->port; bp->fw_drv_pulse_wr_seq = - (SHMEM_RD(bp, drv_fw_mb[port].drv_pulse_mb) & + (SHMEM_RD(bp, func_mb[port].drv_pulse_mb) & DRV_PULSE_SEQ_MASK); - bp->fw_mb = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_param); + bp->fw_mb = SHMEM_RD(bp, func_mb[port].fw_mb_param); DP(BNX2X_MSG_MCP, "drv_pulse 0x%x fw_mb 0x%x\n", bp->fw_drv_pulse_wr_seq, bp->fw_mb); } else { @@ -5681,16 +6603,15 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) return 0; } - -/* send the MCP a request, block untill there is a reply */ +/* send the MCP a request, block until there is a reply */ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) { - u32 rc = 0; - u32 seq = ++bp->fw_seq; int port = bp->port; + u32 seq = ++bp->fw_seq; + u32 rc = 0; - SHMEM_WR(bp, drv_fw_mb[port].drv_mb_header, command|seq); - DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", command|seq); + SHMEM_WR(bp, func_mb[port].drv_mb_header, (command | seq)); + DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq)); /* let the FW do it's magic ... */ msleep(100); /* TBD */ @@ -5698,19 +6619,20 @@ static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command) if (CHIP_REV_IS_SLOW(bp)) msleep(900); - rc = SHMEM_RD(bp, drv_fw_mb[port].fw_mb_header); - + rc = SHMEM_RD(bp, func_mb[port].fw_mb_header); DP(BNX2X_MSG_MCP, "read (%x) seq is (%x) from FW MB\n", rc, seq); /* is this a reply to our command? */ if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) { rc &= FW_MSG_CODE_MASK; + } else { /* FW BUG! */ BNX2X_ERR("FW failed to respond!\n"); bnx2x_fw_dump(bp); rc = 0; } + return rc; } @@ -5869,7 +6791,7 @@ static int bnx2x_alloc_mem(struct bnx2x *bp) for (i = 0; i < 16*1024; i += 64) * (u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64; - /* now sixup the last line in the block to point to the next block */ + /* now fixup the last line in the block to point to the next block */ *(u64 *)((char *)bp->t2 + 1024*16-8) = bp->t2_mapping; /* Timer block array (MAX_CONN*8) phys uncached for now 1024 conns */ @@ -5950,22 +6872,19 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp) int i; free_irq(bp->msix_table[0].vector, bp->dev); - DP(NETIF_MSG_IFDOWN, "rleased sp irq (%d)\n", + DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", bp->msix_table[0].vector); for_each_queue(bp, i) { - DP(NETIF_MSG_IFDOWN, "about to rlease fp #%d->%d irq " + DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq " "state(%x)\n", i, bp->msix_table[i + 1].vector, bnx2x_fp(bp, i, state)); - if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED) { - - free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]); - bnx2x_fp(bp, i, state) = BNX2X_FP_STATE_CLOSED; - - } else - DP(NETIF_MSG_IFDOWN, "irq not freed\n"); + if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED) + BNX2X_ERR("IRQ of fp #%d being freed while " + "state != closed\n", i); + free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]); } } @@ -5995,7 +6914,7 @@ static int bnx2x_enable_msix(struct bnx2x *bp) if (pci_enable_msix(bp->pdev, &bp->msix_table[0], bp->num_queues + 1)){ - BNX2X_ERR("failed to enable msix\n"); + BNX2X_LOG("failed to enable MSI-X\n"); return -1; } @@ -6010,11 +6929,8 @@ static int bnx2x_enable_msix(struct bnx2x *bp) static int bnx2x_req_msix_irqs(struct bnx2x *bp) { - int i, rc; - DP(NETIF_MSG_IFUP, "about to request sp irq\n"); - rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0, bp->dev->name, bp->dev); @@ -6029,7 +6945,8 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) bp->dev->name, &bp->fp[i]); if (rc) { - BNX2X_ERR("request fp #%d irq failed\n", i); + BNX2X_ERR("request fp #%d irq failed " + "rc %d\n", i, rc); bnx2x_free_msix_irqs(bp); return -EBUSY; } @@ -6109,8 +7026,8 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, /* can take a while if any port is running */ int timeout = 500; - /* DP("waiting for state to become %d on IDX [%d]\n", - state, sb_idx); */ + DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n", + poll ? "polling" : "waiting", state, idx); might_sleep(); @@ -6128,7 +7045,7 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, mb(); /* state is changed by bnx2x_sp_event()*/ - if (*state_p != state) + if (*state_p == state) return 0; timeout--; @@ -6136,17 +7053,17 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx, } - /* timeout! */ - BNX2X_ERR("timeout waiting for ramrod %d on %d\n", state, idx); - return -EBUSY; + BNX2X_ERR("timeout %s for state %x on IDX [%d]\n", + poll ? "polling" : "waiting", state, idx); + return -EBUSY; } static int bnx2x_setup_leading(struct bnx2x *bp) { - /* reset IGU staae */ + /* reset IGU state */ bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, 0, IGU_INT_ENABLE, 0); /* SETUP ramrod */ @@ -6162,12 +7079,13 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index) /* reset IGU state */ bnx2x_ack_sb(bp, index, CSTORM_ID, 0, IGU_INT_ENABLE, 0); + /* SETUP ramrod */ bp->fp[index].state = BNX2X_FP_STATE_OPENING; bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0, index, 0); /* Wait for completion */ return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index, - &(bp->fp[index].state), 1); + &(bp->fp[index].state), 0); } @@ -6177,8 +7095,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev); static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) { - int rc; - int i = 0; + u32 load_code; + int i; bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; @@ -6188,26 +7106,28 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) initialized, otherwise - not. */ if (!nomcp) { - rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); - if (rc == FW_MSG_CODE_DRV_LOAD_REFUSED) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); + if (!load_code) { + BNX2X_ERR("MCP response failure, unloading\n"); + return -EBUSY; + } + if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { + BNX2X_ERR("MCP refused load request, unloading\n"); return -EBUSY; /* other port in diagnostic mode */ } } else { - rc = FW_MSG_CODE_DRV_LOAD_COMMON; + load_code = FW_MSG_CODE_DRV_LOAD_COMMON; } - DP(NETIF_MSG_IFUP, "set number of queues to %d\n", bp->num_queues); - /* if we can't use msix we only need one fp, * so try to enable msix with the requested number of fp's * and fallback to inta with one fp */ if (req_irq) { - if (use_inta) { bp->num_queues = 1; } else { - if (use_multi > 1 && use_multi <= 16) + if ((use_multi > 1) && (use_multi <= 16)) /* user requested number */ bp->num_queues = use_multi; else if (use_multi == 1) @@ -6216,15 +7136,17 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) bp->num_queues = 1; if (bnx2x_enable_msix(bp)) { - /* faild to enable msix */ + /* failed to enable msix */ bp->num_queues = 1; if (use_multi) - BNX2X_ERR("Muti requested but failed" + BNX2X_ERR("Multi requested but failed" " to enable MSI-X\n"); } } } + DP(NETIF_MSG_IFUP, "set number of queues to %d\n", bp->num_queues); + if (bnx2x_alloc_mem(bp)) return -ENOMEM; @@ -6232,13 +7154,13 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) if (bp->flags & USING_MSIX_FLAG) { if (bnx2x_req_msix_irqs(bp)) { pci_disable_msix(bp->pdev); - goto out_error; + goto load_error; } } else { if (bnx2x_req_irq(bp)) { BNX2X_ERR("IRQ request failed, aborting\n"); - goto out_error; + goto load_error; } } } @@ -6249,31 +7171,25 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) /* Initialize HW */ - if (bnx2x_function_init(bp, (rc == FW_MSG_CODE_DRV_LOAD_COMMON))) { + if (bnx2x_function_init(bp, + (load_code == FW_MSG_CODE_DRV_LOAD_COMMON))) { BNX2X_ERR("HW init failed, aborting\n"); - goto out_error; + goto load_error; } atomic_set(&bp->intr_sem, 0); - /* Reenable SP tasklet */ - /*if (bp->sp_task_en) { */ - /* tasklet_enable(&bp->sp_task);*/ - /*} else { */ - /* bp->sp_task_en = 1; */ - /*} */ /* Setup NIC internals and enable interrupts */ bnx2x_nic_init(bp); /* Send LOAD_DONE command to MCP */ if (!nomcp) { - rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); - DP(NETIF_MSG_IFUP, "rc = 0x%x\n", rc); - if (!rc) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); + if (!load_code) { BNX2X_ERR("MCP response failure, unloading\n"); - goto int_disable; + goto load_int_disable; } } @@ -6285,11 +7201,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) napi_enable(&bnx2x_fp(bp, i, napi)); if (bnx2x_setup_leading(bp)) - goto stop_netif; + goto load_stop_netif; for_each_nondefault_queue(bp, i) if (bnx2x_setup_multi(bp, i)) - goto stop_netif; + goto load_stop_netif; bnx2x_set_mac_addr(bp); @@ -6313,42 +7229,24 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) return 0; -stop_netif: +load_stop_netif: for_each_queue(bp, i) napi_disable(&bnx2x_fp(bp, i, napi)); -int_disable: - bnx2x_disable_int_sync(bp); +load_int_disable: + bnx2x_int_disable_sync(bp); bnx2x_free_skbs(bp); bnx2x_free_irq(bp); -out_error: +load_error: bnx2x_free_mem(bp); /* TBD we really need to reset the chip if we want to recover from this */ - return rc; + return -EBUSY; } -static void bnx2x_netif_stop(struct bnx2x *bp) -{ - int i; - - bp->rx_mode = BNX2X_RX_MODE_NONE; - bnx2x_set_storm_rx_mode(bp); - - bnx2x_disable_int_sync(bp); - bnx2x_link_reset(bp); - - for_each_queue(bp, i) - napi_disable(&bnx2x_fp(bp, i, napi)); - - if (netif_running(bp->dev)) { - netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ - } -} static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) { @@ -6401,20 +7299,20 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index) int rc; - /* halt the connnection */ + /* halt the connection */ bp->fp[index].state = BNX2X_FP_STATE_HALTING; bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0); rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index, &(bp->fp[index].state), 1); - if (rc) /* timout */ + if (rc) /* timeout */ return rc; /* delete cfc entry */ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CFC_DEL, index, 0, 0, 1); - return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_DELETED, index, + return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index, &(bp->fp[index].state), 1); } @@ -6422,8 +7320,8 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index) static void bnx2x_stop_leading(struct bnx2x *bp) { - - /* if the other port is hadling traffic, + u16 dsb_sp_prod_idx; + /* if the other port is handling traffic, this can take a lot of time */ int timeout = 500; @@ -6437,52 +7335,71 @@ static void bnx2x_stop_leading(struct bnx2x *bp) &(bp->fp[0].state), 1)) return; - bp->dsb_sp_prod_idx = *bp->dsb_sp_prod; + dsb_sp_prod_idx = *bp->dsb_sp_prod; - /* Send CFC_DELETE ramrod */ + /* Send PORT_DELETE ramrod */ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1); - /* - Wait for completion. + /* Wait for completion to arrive on default status block we are going to reset the chip anyway so there is not much to do if this times out */ - while (bp->dsb_sp_prod_idx == *bp->dsb_sp_prod && timeout) { - timeout--; - msleep(1); + while ((dsb_sp_prod_idx == *bp->dsb_sp_prod) && timeout) { + timeout--; + msleep(1); } - + if (!timeout) { + DP(NETIF_MSG_IFDOWN, "timeout polling for completion " + "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n", + *bp->dsb_sp_prod, dsb_sp_prod_idx); + } + bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD; + bp->fp[0].state = BNX2X_FP_STATE_CLOSED; } -static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq) + +static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq) { u32 reset_code = 0; - int rc; - int i; + int i, timeout; bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; - /* Calling flush_scheduled_work() may deadlock because - * linkwatch_event() may be on the workqueue and it will try to get - * the rtnl_lock which we are holding. - */ + del_timer_sync(&bp->timer); - while (bp->in_reset_task) - msleep(1); + bp->rx_mode = BNX2X_RX_MODE_NONE; + bnx2x_set_storm_rx_mode(bp); - /* Delete the timer: do it before disabling interrupts, as it - may be stil STAT_QUERY ramrod pending after stopping the timer */ - del_timer_sync(&bp->timer); + if (netif_running(bp->dev)) { + netif_tx_disable(bp->dev); + bp->dev->trans_start = jiffies; /* prevent tx timeout */ + } + + /* Wait until all fast path tasks complete */ + for_each_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + + timeout = 1000; + while (bnx2x_has_work(fp) && (timeout--)) + msleep(1); + if (!timeout) + BNX2X_ERR("timeout waiting for queue[%d]\n", i); + } /* Wait until stat ramrod returns and all SP tasks complete */ - while (bp->stat_pending && (bp->spq_left != MAX_SPQ_PENDING)) + timeout = 1000; + while ((bp->stat_pending || (bp->spq_left != MAX_SPQ_PENDING)) && + (timeout--)) msleep(1); - /* Stop fast path, disable MAC, disable interrupts, disable napi */ - bnx2x_netif_stop(bp); + for_each_queue(bp, i) + napi_disable(&bnx2x_fp(bp, i, napi)); + /* Disable interrupts after Tx and Rx are disabled on stack level */ + bnx2x_int_disable_sync(bp); if (bp->flags & NO_WOL_FLAG) reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; + else if (bp->wol) { u32 emac_base = bp->port ? GRCBASE_EMAC0 : GRCBASE_EMAC1; u8 *mac_addr = bp->dev->dev_addr; @@ -6499,28 +7416,37 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq) EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val); reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; + } else reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; + /* Close multi and leading connections */ for_each_nondefault_queue(bp, i) if (bnx2x_stop_multi(bp, i)) - goto error; - + goto unload_error; bnx2x_stop_leading(bp); + if ((bp->state != BNX2X_STATE_CLOSING_WAIT4_UNLOAD) || + (bp->fp[0].state != BNX2X_FP_STATE_CLOSED)) { + DP(NETIF_MSG_IFDOWN, "failed to close leading properly!" + "state 0x%x fp[0].state 0x%x", + bp->state, bp->fp[0].state); + } + +unload_error: + bnx2x_link_reset(bp); -error: if (!nomcp) - rc = bnx2x_fw_command(bp, reset_code); + reset_code = bnx2x_fw_command(bp, reset_code); else - rc = FW_MSG_CODE_DRV_UNLOAD_COMMON; + reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON; /* Release IRQs */ - if (fre_irq) + if (free_irq) bnx2x_free_irq(bp); /* Reset the chip */ - bnx2x_reset_chip(bp, rc); + bnx2x_reset_chip(bp, reset_code); /* Report UNLOAD_DONE to MCP */ if (!nomcp) @@ -6531,8 +7457,7 @@ error: bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; - /* Set link down */ - bp->link_up = 0; + netif_carrier_off(bp->dev); return 0; @@ -6568,7 +7493,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | - SUPPORTED_2500baseT_Full | + SUPPORTED_2500baseX_Full | SUPPORTED_TP | SUPPORTED_FIBRE | SUPPORTED_Autoneg | SUPPORTED_Pause | @@ -6581,10 +7506,10 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) bp->phy_flags |= PHY_SGMII_FLAG; - bp->supported |= (/* SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full |*/ + bp->supported |= (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_TP | SUPPORTED_FIBRE | SUPPORTED_Autoneg | @@ -6620,7 +7545,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | - SUPPORTED_2500baseT_Full | + SUPPORTED_2500baseX_Full | SUPPORTED_10000baseT_Full | SUPPORTED_TP | SUPPORTED_FIBRE | SUPPORTED_Autoneg | @@ -6629,12 +7554,46 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: + BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n", + ext_phy_type); + + bp->supported |= (SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); + break; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: - BNX2X_DEV_INFO("ext_phy_type 0x%x (8705/6)\n", + BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n", + ext_phy_type); + + bp->supported |= (SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_FIBRE | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n", ext_phy_type); bp->supported |= (SUPPORTED_10000baseT_Full | + SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | + SUPPORTED_Autoneg | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n", + ext_phy_type); + + bp->supported |= (SUPPORTED_10000baseT_Full | + SUPPORTED_TP | + SUPPORTED_Autoneg | SUPPORTED_Pause | SUPPORTED_Asym_Pause); break; @@ -6691,7 +7650,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) SUPPORTED_1000baseT_Full); if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) - bp->supported &= ~SUPPORTED_2500baseT_Full; + bp->supported &= ~SUPPORTED_2500baseX_Full; if (!(bp->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) bp->supported &= ~SUPPORTED_10000baseT_Full; @@ -6711,13 +7670,8 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) bp->req_line_speed = 0; bp->advertising = bp->supported; } else { - u32 ext_phy_type; - - ext_phy_type = XGXS_EXT_PHY_TYPE(bp); - if ((ext_phy_type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || - (ext_phy_type == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) { + if (XGXS_EXT_PHY_TYPE(bp) == + PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) { /* force 10G, no AN */ bp->req_line_speed = SPEED_10000; bp->advertising = @@ -6734,8 +7688,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_10M_FULL: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) { + if (bp->supported & SUPPORTED_10baseT_Full) { bp->req_line_speed = SPEED_10; bp->advertising = (ADVERTISED_10baseT_Full | ADVERTISED_TP); @@ -6749,8 +7702,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_10M_HALF: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) { + if (bp->supported & SUPPORTED_10baseT_Half) { bp->req_line_speed = SPEED_10; bp->req_duplex = DUPLEX_HALF; bp->advertising = (ADVERTISED_10baseT_Half | @@ -6765,8 +7717,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_100M_FULL: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) { + if (bp->supported & SUPPORTED_100baseT_Full) { bp->req_line_speed = SPEED_100; bp->advertising = (ADVERTISED_100baseT_Full | ADVERTISED_TP); @@ -6780,8 +7731,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_100M_HALF: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) { + if (bp->supported & SUPPORTED_100baseT_Half) { bp->req_line_speed = SPEED_100; bp->req_duplex = DUPLEX_HALF; bp->advertising = (ADVERTISED_100baseT_Half | @@ -6796,8 +7746,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_1G: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) { + if (bp->supported & SUPPORTED_1000baseT_Full) { bp->req_line_speed = SPEED_1000; bp->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_TP); @@ -6811,10 +7760,9 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) break; case PORT_FEATURE_LINK_SPEED_2_5G: - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) { + if (bp->supported & SUPPORTED_2500baseX_Full) { bp->req_line_speed = SPEED_2500; - bp->advertising = (ADVERTISED_2500baseT_Full | + bp->advertising = (ADVERTISED_2500baseX_Full | ADVERTISED_TP); } else { BNX2X_ERR("NVRAM config error. " @@ -6828,15 +7776,7 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) case PORT_FEATURE_LINK_SPEED_10G_CX4: case PORT_FEATURE_LINK_SPEED_10G_KX4: case PORT_FEATURE_LINK_SPEED_10G_KR: - if (!(bp->phy_flags & PHY_XGXS_FLAG)) { - BNX2X_ERR("NVRAM config error. " - "Invalid link_config 0x%x" - " phy_flags 0x%x\n", - bp->link_config, bp->phy_flags); - return; - } - if (bp->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { + if (bp->supported & SUPPORTED_10000baseT_Full) { bp->req_line_speed = SPEED_10000; bp->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); @@ -6863,43 +7803,13 @@ static void bnx2x_link_settings_requested(struct bnx2x *bp) bp->req_flow_ctrl = (bp->link_config & PORT_FEATURE_FLOW_CONTROL_MASK); - /* Please refer to Table 28B-3 of the 802.3ab-1999 spec */ - switch (bp->req_flow_ctrl) { - case FLOW_CTRL_AUTO: + if ((bp->req_flow_ctrl == FLOW_CTRL_AUTO) && + (bp->supported & SUPPORTED_Autoneg)) bp->req_autoneg |= AUTONEG_FLOW_CTRL; - if (bp->dev->mtu <= 4500) { - bp->pause_mode = PAUSE_BOTH; - bp->advertising |= (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - } else { - bp->pause_mode = PAUSE_ASYMMETRIC; - bp->advertising |= ADVERTISED_Asym_Pause; - } - break; - - case FLOW_CTRL_TX: - bp->pause_mode = PAUSE_ASYMMETRIC; - bp->advertising |= ADVERTISED_Asym_Pause; - break; - - case FLOW_CTRL_RX: - case FLOW_CTRL_BOTH: - bp->pause_mode = PAUSE_BOTH; - bp->advertising |= (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - break; - case FLOW_CTRL_NONE: - default: - bp->pause_mode = PAUSE_NONE; - bp->advertising &= ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - break; - } - BNX2X_DEV_INFO("req_autoneg 0x%x req_flow_ctrl 0x%x\n" - KERN_INFO " pause_mode %d advertising 0x%x\n", - bp->req_autoneg, bp->req_flow_ctrl, - bp->pause_mode, bp->advertising); + BNX2X_DEV_INFO("req_autoneg 0x%x req_flow_ctrl 0x%x" + " advertising 0x%x\n", + bp->req_autoneg, bp->req_flow_ctrl, bp->advertising); } static void bnx2x_get_hwinfo(struct bnx2x *bp) @@ -6933,15 +7843,15 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) val = SHMEM_RD(bp, validity_map[port]); if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) - BNX2X_ERR("MCP validity signature bad\n"); + BNX2X_ERR("BAD MCP validity signature\n"); - bp->fw_seq = (SHMEM_RD(bp, drv_fw_mb[port].drv_mb_header) & + bp->fw_seq = (SHMEM_RD(bp, func_mb[port].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); bp->hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config); - + bp->board = SHMEM_RD(bp, dev_info.shared_hw_config.board); bp->serdes_config = - SHMEM_RD(bp, dev_info.port_hw_config[bp->port].serdes_config); + SHMEM_RD(bp, dev_info.port_hw_config[port].serdes_config); bp->lane_config = SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); bp->ext_phy_config = @@ -6954,13 +7864,13 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) bp->link_config = SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); - BNX2X_DEV_INFO("hw_config (%08x) serdes_config (%08x)\n" + BNX2X_DEV_INFO("hw_config (%08x) board (%08x) serdes_config (%08x)\n" KERN_INFO " lane_config (%08x) ext_phy_config (%08x)\n" KERN_INFO " speed_cap_mask (%08x) link_config (%08x)" " fw_seq (%08x)\n", - bp->hw_config, bp->serdes_config, bp->lane_config, - bp->ext_phy_config, bp->speed_cap_mask, - bp->link_config, bp->fw_seq); + bp->hw_config, bp->board, bp->serdes_config, + bp->lane_config, bp->ext_phy_config, + bp->speed_cap_mask, bp->link_config, bp->fw_seq); switch_cfg = (bp->link_config & PORT_FEATURE_CONNECTED_SWITCH_MASK); bnx2x_link_settings_supported(bp, switch_cfg); @@ -7014,14 +7924,8 @@ static void bnx2x_get_hwinfo(struct bnx2x *bp) return; set_mac: /* only supposed to happen on emulation/FPGA */ - BNX2X_ERR("warning constant MAC workaround active\n"); - bp->dev->dev_addr[0] = 0; - bp->dev->dev_addr[1] = 0x50; - bp->dev->dev_addr[2] = 0xc2; - bp->dev->dev_addr[3] = 0x2c; - bp->dev->dev_addr[4] = 0x71; - bp->dev->dev_addr[5] = port ? 0x0d : 0x0e; - + BNX2X_ERR("warning rendom MAC workaround active\n"); + random_ether_addr(bp->dev->dev_addr); memcpy(bp->dev->perm_addr, bp->dev->dev_addr, 6); } @@ -7048,19 +7952,34 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } if (bp->phy_flags & PHY_XGXS_FLAG) { - cmd->port = PORT_FIBRE; - } else { + u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp); + + switch (ext_phy_type) { + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + cmd->port = PORT_FIBRE; + break; + + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: + cmd->port = PORT_TP; + break; + + default: + DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", + bp->ext_phy_config); + } + } else cmd->port = PORT_TP; - } cmd->phy_address = bp->phy_addr; cmd->transceiver = XCVR_INTERNAL; - if (bp->req_autoneg & AUTONEG_SPEED) { + if (bp->req_autoneg & AUTONEG_SPEED) cmd->autoneg = AUTONEG_ENABLE; - } else { + else cmd->autoneg = AUTONEG_DISABLE; - } cmd->maxtxpkt = 0; cmd->maxrxpkt = 0; @@ -7091,8 +8010,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) switch (cmd->port) { case PORT_TP: - if (!(bp->supported & SUPPORTED_TP)) + if (!(bp->supported & SUPPORTED_TP)) { + DP(NETIF_MSG_LINK, "TP not supported\n"); return -EINVAL; + } if (bp->phy_flags & PHY_XGXS_FLAG) { bnx2x_link_reset(bp); @@ -7102,8 +8023,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) break; case PORT_FIBRE: - if (!(bp->supported & SUPPORTED_FIBRE)) + if (!(bp->supported & SUPPORTED_FIBRE)) { + DP(NETIF_MSG_LINK, "FIBRE not supported\n"); return -EINVAL; + } if (!(bp->phy_flags & PHY_XGXS_FLAG)) { bnx2x_link_reset(bp); @@ -7113,12 +8036,15 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) break; default: + DP(NETIF_MSG_LINK, "Unknown port type\n"); return -EINVAL; } if (cmd->autoneg == AUTONEG_ENABLE) { - if (!(bp->supported & SUPPORTED_Autoneg)) + if (!(bp->supported & SUPPORTED_Autoneg)) { + DP(NETIF_MSG_LINK, "Aotoneg not supported\n"); return -EINVAL; + } /* advertise the requested speed and duplex if supported */ cmd->advertising &= bp->supported; @@ -7133,14 +8059,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) switch (cmd->speed) { case SPEED_10: if (cmd->duplex == DUPLEX_FULL) { - if (!(bp->supported & SUPPORTED_10baseT_Full)) + if (!(bp->supported & + SUPPORTED_10baseT_Full)) { + DP(NETIF_MSG_LINK, + "10M full not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_10baseT_Full | ADVERTISED_TP); } else { - if (!(bp->supported & SUPPORTED_10baseT_Half)) + if (!(bp->supported & + SUPPORTED_10baseT_Half)) { + DP(NETIF_MSG_LINK, + "10M half not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_10baseT_Half | ADVERTISED_TP); @@ -7150,15 +8084,21 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) case SPEED_100: if (cmd->duplex == DUPLEX_FULL) { if (!(bp->supported & - SUPPORTED_100baseT_Full)) + SUPPORTED_100baseT_Full)) { + DP(NETIF_MSG_LINK, + "100M full not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_100baseT_Full | ADVERTISED_TP); } else { if (!(bp->supported & - SUPPORTED_100baseT_Half)) + SUPPORTED_100baseT_Half)) { + DP(NETIF_MSG_LINK, + "100M half not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_100baseT_Half | ADVERTISED_TP); @@ -7166,39 +8106,54 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) break; case SPEED_1000: - if (cmd->duplex != DUPLEX_FULL) + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, "1G half not supported\n"); return -EINVAL; + } - if (!(bp->supported & SUPPORTED_1000baseT_Full)) + if (!(bp->supported & SUPPORTED_1000baseT_Full)) { + DP(NETIF_MSG_LINK, "1G full not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_TP); break; case SPEED_2500: - if (cmd->duplex != DUPLEX_FULL) + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, + "2.5G half not supported\n"); return -EINVAL; + } - if (!(bp->supported & SUPPORTED_2500baseT_Full)) + if (!(bp->supported & SUPPORTED_2500baseX_Full)) { + DP(NETIF_MSG_LINK, + "2.5G full not supported\n"); return -EINVAL; + } - advertising = (ADVERTISED_2500baseT_Full | + advertising = (ADVERTISED_2500baseX_Full | ADVERTISED_TP); break; case SPEED_10000: - if (cmd->duplex != DUPLEX_FULL) + if (cmd->duplex != DUPLEX_FULL) { + DP(NETIF_MSG_LINK, "10G half not supported\n"); return -EINVAL; + } - if (!(bp->supported & SUPPORTED_10000baseT_Full)) + if (!(bp->supported & SUPPORTED_10000baseT_Full)) { + DP(NETIF_MSG_LINK, "10G full not supported\n"); return -EINVAL; + } advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); break; default: + DP(NETIF_MSG_LINK, "Unsupported speed\n"); return -EINVAL; } @@ -7398,8 +8353,7 @@ static void bnx2x_disable_nvram_access(struct bnx2x *bp) static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, u32 *ret_val, u32 cmd_flags) { - int rc; - int count, i; + int count, i, rc; u32 val; /* build the command word */ @@ -7452,13 +8406,13 @@ static int bnx2x_nvram_read(struct bnx2x *bp, u32 offset, u8 *ret_buf, if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { DP(NETIF_MSG_NVM, - "Invalid paramter: offset 0x%x buf_size 0x%x\n", + "Invalid parameter: offset 0x%x buf_size 0x%x\n", offset, buf_size); return -EINVAL; } if (offset + buf_size > bp->flash_size) { - DP(NETIF_MSG_NVM, "Invalid paramter: offset (0x%x) +" + DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +" " buf_size (0x%x) > flash_size (0x%x)\n", offset, buf_size, bp->flash_size); return -EINVAL; @@ -7519,8 +8473,7 @@ static int bnx2x_get_eeprom(struct net_device *dev, static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, u32 cmd_flags) { - int rc; - int count, i; + int count, i, rc; /* build the command word */ cmd_flags |= MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; @@ -7557,7 +8510,7 @@ static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val, return rc; } -#define BYTE_OFFSET(offset) (8 * (offset & 0x03)) +#define BYTE_OFFSET(offset) (8 * (offset & 0x03)) static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, int buf_size) @@ -7568,7 +8521,7 @@ static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, u32 val; if (offset + buf_size > bp->flash_size) { - DP(NETIF_MSG_NVM, "Invalid paramter: offset (0x%x) +" + DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +" " buf_size (0x%x) > flash_size (0x%x)\n", offset, buf_size, bp->flash_size); return -EINVAL; @@ -7621,13 +8574,13 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf, if ((offset & 0x03) || (buf_size & 0x03) || (buf_size == 0)) { DP(NETIF_MSG_NVM, - "Invalid paramter: offset 0x%x buf_size 0x%x\n", + "Invalid parameter: offset 0x%x buf_size 0x%x\n", offset, buf_size); return -EINVAL; } if (offset + buf_size > bp->flash_size) { - DP(NETIF_MSG_NVM, "Invalid paramter: offset (0x%x) +" + DP(NETIF_MSG_NVM, "Invalid parameter: offset (0x%x) +" " buf_size (0x%x) > flash_size (0x%x)\n", offset, buf_size, bp->flash_size); return -EINVAL; @@ -7788,52 +8741,29 @@ static int bnx2x_set_pauseparam(struct net_device *dev, DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); - bp->req_flow_ctrl = FLOW_CTRL_AUTO; if (epause->autoneg) { - bp->req_autoneg |= AUTONEG_FLOW_CTRL; - if (bp->dev->mtu <= 4500) { - bp->pause_mode = PAUSE_BOTH; - bp->advertising |= (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - } else { - bp->pause_mode = PAUSE_ASYMMETRIC; - bp->advertising |= ADVERTISED_Asym_Pause; + if (!(bp->supported & SUPPORTED_Autoneg)) { + DP(NETIF_MSG_LINK, "Aotoneg not supported\n"); + return -EINVAL; } - } else { + bp->req_autoneg |= AUTONEG_FLOW_CTRL; + } else bp->req_autoneg &= ~AUTONEG_FLOW_CTRL; - if (epause->rx_pause) - bp->req_flow_ctrl |= FLOW_CTRL_RX; - if (epause->tx_pause) - bp->req_flow_ctrl |= FLOW_CTRL_TX; - - switch (bp->req_flow_ctrl) { - case FLOW_CTRL_AUTO: - bp->req_flow_ctrl = FLOW_CTRL_NONE; - bp->pause_mode = PAUSE_NONE; - bp->advertising &= ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - break; + bp->req_flow_ctrl = FLOW_CTRL_AUTO; - case FLOW_CTRL_TX: - bp->pause_mode = PAUSE_ASYMMETRIC; - bp->advertising |= ADVERTISED_Asym_Pause; - break; + if (epause->rx_pause) + bp->req_flow_ctrl |= FLOW_CTRL_RX; + if (epause->tx_pause) + bp->req_flow_ctrl |= FLOW_CTRL_TX; - case FLOW_CTRL_RX: - case FLOW_CTRL_BOTH: - bp->pause_mode = PAUSE_BOTH; - bp->advertising |= (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - break; - } - } + if (!(bp->req_autoneg & AUTONEG_FLOW_CTRL) && + (bp->req_flow_ctrl == FLOW_CTRL_AUTO)) + bp->req_flow_ctrl = FLOW_CTRL_NONE; - DP(NETIF_MSG_LINK, "req_autoneg 0x%x req_flow_ctrl 0x%x\n" - DP_LEVEL " pause_mode %d advertising 0x%x\n", - bp->req_autoneg, bp->req_flow_ctrl, bp->pause_mode, - bp->advertising); + DP(NETIF_MSG_LINK, "req_autoneg 0x%x req_flow_ctrl 0x%x\n", + bp->req_autoneg, bp->req_flow_ctrl); bnx2x_stop_stats(bp); bnx2x_link_initialize(bp); @@ -7906,81 +8836,87 @@ static void bnx2x_self_test(struct net_device *dev, static struct { char string[ETH_GSTRING_LEN]; } bnx2x_stats_str_arr[BNX2X_NUM_STATS] = { - { "rx_bytes"}, /* 0 */ - { "rx_error_bytes"}, /* 1 */ - { "tx_bytes"}, /* 2 */ - { "tx_error_bytes"}, /* 3 */ - { "rx_ucast_packets"}, /* 4 */ - { "rx_mcast_packets"}, /* 5 */ - { "rx_bcast_packets"}, /* 6 */ - { "tx_ucast_packets"}, /* 7 */ - { "tx_mcast_packets"}, /* 8 */ - { "tx_bcast_packets"}, /* 9 */ - { "tx_mac_errors"}, /* 10 */ - { "tx_carrier_errors"}, /* 11 */ - { "rx_crc_errors"}, /* 12 */ - { "rx_align_errors"}, /* 13 */ - { "tx_single_collisions"}, /* 14 */ - { "tx_multi_collisions"}, /* 15 */ - { "tx_deferred"}, /* 16 */ - { "tx_excess_collisions"}, /* 17 */ - { "tx_late_collisions"}, /* 18 */ - { "tx_total_collisions"}, /* 19 */ - { "rx_fragments"}, /* 20 */ - { "rx_jabbers"}, /* 21 */ - { "rx_undersize_packets"}, /* 22 */ - { "rx_oversize_packets"}, /* 23 */ - { "rx_xon_frames"}, /* 24 */ - { "rx_xoff_frames"}, /* 25 */ - { "tx_xon_frames"}, /* 26 */ - { "tx_xoff_frames"}, /* 27 */ - { "rx_mac_ctrl_frames"}, /* 28 */ - { "rx_filtered_packets"}, /* 29 */ - { "rx_discards"}, /* 30 */ + { "rx_bytes"}, + { "rx_error_bytes"}, + { "tx_bytes"}, + { "tx_error_bytes"}, + { "rx_ucast_packets"}, + { "rx_mcast_packets"}, + { "rx_bcast_packets"}, + { "tx_ucast_packets"}, + { "tx_mcast_packets"}, + { "tx_bcast_packets"}, + { "tx_mac_errors"}, /* 10 */ + { "tx_carrier_errors"}, + { "rx_crc_errors"}, + { "rx_align_errors"}, + { "tx_single_collisions"}, + { "tx_multi_collisions"}, + { "tx_deferred"}, + { "tx_excess_collisions"}, + { "tx_late_collisions"}, + { "tx_total_collisions"}, + { "rx_fragments"}, /* 20 */ + { "rx_jabbers"}, + { "rx_undersize_packets"}, + { "rx_oversize_packets"}, + { "rx_xon_frames"}, + { "rx_xoff_frames"}, + { "tx_xon_frames"}, + { "tx_xoff_frames"}, + { "rx_mac_ctrl_frames"}, + { "rx_filtered_packets"}, + { "rx_discards"}, /* 30 */ + { "brb_discard"}, + { "brb_truncate"}, + { "xxoverflow"} }; #define STATS_OFFSET32(offset_name) \ (offsetof(struct bnx2x_eth_stats, offset_name) / 4) static unsigned long bnx2x_stats_offset_arr[BNX2X_NUM_STATS] = { - STATS_OFFSET32(total_bytes_received_hi), /* 0 */ - STATS_OFFSET32(stat_IfHCInBadOctets_hi), /* 1 */ - STATS_OFFSET32(total_bytes_transmitted_hi), /* 2 */ - STATS_OFFSET32(stat_IfHCOutBadOctets_hi), /* 3 */ - STATS_OFFSET32(total_unicast_packets_received_hi), /* 4 */ - STATS_OFFSET32(total_multicast_packets_received_hi), /* 5 */ - STATS_OFFSET32(total_broadcast_packets_received_hi), /* 6 */ - STATS_OFFSET32(total_unicast_packets_transmitted_hi), /* 7 */ - STATS_OFFSET32(total_multicast_packets_transmitted_hi), /* 8 */ - STATS_OFFSET32(total_broadcast_packets_transmitted_hi), /* 9 */ - STATS_OFFSET32(stat_Dot3statsInternalMacTransmitErrors), /* 10 */ - STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), /* 11 */ - STATS_OFFSET32(crc_receive_errors), /* 12 */ - STATS_OFFSET32(alignment_errors), /* 13 */ - STATS_OFFSET32(single_collision_transmit_frames), /* 14 */ - STATS_OFFSET32(multiple_collision_transmit_frames), /* 15 */ - STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), /* 16 */ - STATS_OFFSET32(excessive_collision_frames), /* 17 */ - STATS_OFFSET32(late_collision_frames), /* 18 */ - STATS_OFFSET32(number_of_bugs_found_in_stats_spec), /* 19 */ - STATS_OFFSET32(runt_packets_received), /* 20 */ - STATS_OFFSET32(jabber_packets_received), /* 21 */ - STATS_OFFSET32(error_runt_packets_received), /* 22 */ - STATS_OFFSET32(error_jabber_packets_received), /* 23 */ - STATS_OFFSET32(pause_xon_frames_received), /* 24 */ - STATS_OFFSET32(pause_xoff_frames_received), /* 25 */ - STATS_OFFSET32(pause_xon_frames_transmitted), /* 26 */ - STATS_OFFSET32(pause_xoff_frames_transmitted), /* 27 */ - STATS_OFFSET32(control_frames_received), /* 28 */ - STATS_OFFSET32(mac_filter_discard), /* 29 */ - STATS_OFFSET32(no_buff_discard), /* 30 */ + STATS_OFFSET32(total_bytes_received_hi), + STATS_OFFSET32(stat_IfHCInBadOctets_hi), + STATS_OFFSET32(total_bytes_transmitted_hi), + STATS_OFFSET32(stat_IfHCOutBadOctets_hi), + STATS_OFFSET32(total_unicast_packets_received_hi), + STATS_OFFSET32(total_multicast_packets_received_hi), + STATS_OFFSET32(total_broadcast_packets_received_hi), + STATS_OFFSET32(total_unicast_packets_transmitted_hi), + STATS_OFFSET32(total_multicast_packets_transmitted_hi), + STATS_OFFSET32(total_broadcast_packets_transmitted_hi), + STATS_OFFSET32(stat_Dot3statsInternalMacTransmitErrors), /* 10 */ + STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), + STATS_OFFSET32(crc_receive_errors), + STATS_OFFSET32(alignment_errors), + STATS_OFFSET32(single_collision_transmit_frames), + STATS_OFFSET32(multiple_collision_transmit_frames), + STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), + STATS_OFFSET32(excessive_collision_frames), + STATS_OFFSET32(late_collision_frames), + STATS_OFFSET32(number_of_bugs_found_in_stats_spec), + STATS_OFFSET32(runt_packets_received), /* 20 */ + STATS_OFFSET32(jabber_packets_received), + STATS_OFFSET32(error_runt_packets_received), + STATS_OFFSET32(error_jabber_packets_received), + STATS_OFFSET32(pause_xon_frames_received), + STATS_OFFSET32(pause_xoff_frames_received), + STATS_OFFSET32(pause_xon_frames_transmitted), + STATS_OFFSET32(pause_xoff_frames_transmitted), + STATS_OFFSET32(control_frames_received), + STATS_OFFSET32(mac_filter_discard), + STATS_OFFSET32(no_buff_discard), /* 30 */ + STATS_OFFSET32(brb_discard), + STATS_OFFSET32(brb_truncate_discard), + STATS_OFFSET32(xxoverflow_discard) }; static u8 bnx2x_stats_len_arr[BNX2X_NUM_STATS] = { 8, 0, 8, 0, 8, 8, 8, 8, 8, 8, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, + 4, 4, 4, 4 }; static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) @@ -8138,9 +9074,7 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) * net_device service functions */ -/* Called with rtnl_lock from vlan functions and also netif_tx_lock - * from set_multicast. - */ +/* called with netif_tx_lock from set_multicast */ static void bnx2x_set_rx_mode(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); @@ -8314,7 +9248,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) ETH_TX_BD_ETH_ADDR_TYPE_SHIFT); tx_bd->general_data |= 1; /* header nbd */ - /* remeber the first bd of the packet */ + /* remember the first bd of the packet */ tx_buf->first_bd = bd_prod; DP(NETIF_MSG_TX_QUEUED, @@ -8334,7 +9268,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) /* for now NS flag is not used in Linux */ pbd->global_data = (len | - ((skb->protocol == ETH_P_8021Q) << + ((skb->protocol == ntohs(ETH_P_8021Q)) << ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT)); pbd->ip_hlen = ip_hdrlen(skb) / 2; pbd->total_hlen = cpu_to_le16(len + pbd->ip_hlen); @@ -8343,7 +9277,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_TCP_CSUM; - pbd->tcp_flags = htonl(tcp_flag_word(skb)) & 0xFFFF; + pbd->tcp_flags = pbd_tcp_flags(skb); pbd->total_hlen += cpu_to_le16(tcp_hdrlen(skb) / 2); pbd->tcp_pseudo_csum = swab16(th->check); @@ -8387,7 +9321,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_shinfo(skb)->gso_size && (skb->len > (bp->dev->mtu + ETH_HLEN))) { - int hlen = 2 * le32_to_cpu(pbd->total_hlen); + int hlen = 2 * le16_to_cpu(pbd->total_hlen); DP(NETIF_MSG_TX_QUEUED, "TSO packet len %d hlen %d total len %d tso size %d\n", @@ -8427,7 +9361,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_bd->vlan = cpu_to_le16(pkt_prod); /* this marks the bd * as one that has no individual mapping - * the FW ignors this flag in a bd not maked start + * the FW ignores this flag in a bd not marked start */ tx_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_SW_LSO; DP(NETIF_MSG_TX_QUEUED, @@ -8504,9 +9438,11 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %u bd %d\n", nbd, bd_prod); - fp->hw_tx_prods->bds_prod += cpu_to_le16(nbd); + fp->hw_tx_prods->bds_prod = + cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd); mb(); /* FW restriction: must not reorder writing nbd and packets */ - fp->hw_tx_prods->packets_prod += cpu_to_le32(1); + fp->hw_tx_prods->packets_prod = + cpu_to_le32(le32_to_cpu(fp->hw_tx_prods->packets_prod) + 1); DOORBELL(bp, fp_index, 0); mmiowb(); @@ -8525,11 +9461,6 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static struct net_device_stats *bnx2x_get_stats(struct net_device *dev) -{ - return &dev->stats; -} - /* Called with rtnl_lock */ static int bnx2x_open(struct net_device *dev) { @@ -8543,16 +9474,13 @@ static int bnx2x_open(struct net_device *dev) /* Called with rtnl_lock */ static int bnx2x_close(struct net_device *dev) { - int rc; struct bnx2x *bp = netdev_priv(dev); /* Unload the driver, release IRQs */ - rc = bnx2x_nic_unload(bp, 1); - if (rc) { - BNX2X_ERR("bnx2x_nic_unload failed: %d\n", rc); - return rc; - } - bnx2x_set_power_state(bp, PCI_D3hot); + bnx2x_nic_unload(bp, 1); + + if (!CHIP_REV_IS_SLOW(bp)) + bnx2x_set_power_state(bp, PCI_D3hot); return 0; } @@ -8584,7 +9512,7 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = bp->phy_addr; - /* fallthru */ + /* fallthrough */ case SIOCGMIIREG: { u32 mii_regval; @@ -8633,7 +9561,7 @@ static int bnx2x_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; /* This does not race with packet allocation - * because the actuall alloc size is + * because the actual alloc size is * only updated as part of load */ dev->mtu = new_mtu; @@ -8666,7 +9594,7 @@ static void bnx2x_vlan_rx_register(struct net_device *dev, bp->vlgrp = vlgrp; if (netif_running(dev)) - bnx2x_set_rx_mode(dev); + bnx2x_set_client_config(bp); } #endif @@ -8695,14 +9623,18 @@ static void bnx2x_reset_task(struct work_struct *work) if (!netif_running(bp->dev)) return; - bp->in_reset_task = 1; + rtnl_lock(); - bnx2x_netif_stop(bp); + if (bp->state != BNX2X_STATE_OPEN) { + DP(NETIF_MSG_TX_ERR, "state is %x, returning\n", bp->state); + goto reset_task_exit; + } bnx2x_nic_unload(bp, 0); bnx2x_nic_load(bp, 0); - bp->in_reset_task = 0; +reset_task_exit: + rtnl_unlock(); } static int __devinit bnx2x_init_board(struct pci_dev *pdev, @@ -8783,8 +9715,6 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev, spin_lock_init(&bp->phy_lock); - bp->in_reset_task = 0; - INIT_WORK(&bp->reset_task, bnx2x_reset_task); INIT_WORK(&bp->sp_task, bnx2x_sp_task); @@ -8813,7 +9743,7 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev, bnx2x_get_hwinfo(bp); if (CHIP_REV(bp) == CHIP_REV_FPGA) { - printk(KERN_ERR PFX "FPGA detacted. MCP disabled," + printk(KERN_ERR PFX "FPGA detected. MCP disabled," " will only init first device\n"); onefunc = 1; nomcp = 1; @@ -8882,14 +9812,32 @@ err_out: return rc; } +static int __devinit bnx2x_get_pcie_width(struct bnx2x *bp) +{ + u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL); + + val = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT; + return val; +} + +/* return value of 1=2.5GHz 2=5GHz */ +static int __devinit bnx2x_get_pcie_speed(struct bnx2x *bp) +{ + u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL); + + val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; + return val; +} + static int __devinit bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int version_printed; struct net_device *dev = NULL; struct bnx2x *bp; - int rc, i; + int rc; int port = PCI_FUNC(pdev->devfn); + DECLARE_MAC_BUF(mac); if (version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -8906,6 +9854,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, if (port && onefunc) { printk(KERN_ERR PFX "second function disabled. exiting\n"); + free_netdev(dev); return 0; } @@ -8918,7 +9867,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, dev->hard_start_xmit = bnx2x_start_xmit; dev->watchdog_timeo = TX_TIMEOUT; - dev->get_stats = bnx2x_get_stats; dev->ethtool_ops = &bnx2x_ethtool_ops; dev->open = bnx2x_open; dev->stop = bnx2x_close; @@ -8944,7 +9892,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, rc = register_netdev(dev); if (rc) { - printk(KERN_ERR PFX "Cannot register net device\n"); + dev_err(&pdev->dev, "Cannot register net device\n"); if (bp->regview) iounmap(bp->regview); if (bp->doorbells) @@ -8959,32 +9907,30 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); bp->name = board_info[ent->driver_data].name; - printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz " - "found at mem %lx, IRQ %d, ", - dev->name, bp->name, + printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," + " IRQ %d, ", dev->name, bp->name, ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', ((CHIP_ID(bp) & 0x0ff0) >> 4), - ((bp->flags & PCIX_FLAG) ? "-X" : ""), - ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"), - bp->bus_speed_mhz, - dev->base_addr, - bp->pdev->irq); - - printk("node addr "); - for (i = 0; i < 6; i++) - printk("%2.2x", dev->dev_addr[i]); - printk("\n"); - + bnx2x_get_pcie_width(bp), + (bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz", + dev->base_addr, bp->pdev->irq); + printk(KERN_CONT "node addr %s\n", print_mac(mac, dev->dev_addr)); return 0; } static void __devexit bnx2x_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp = netdev_priv(dev); + struct bnx2x *bp; + + if (!dev) { + /* we get here if init_one() fails */ + printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); + return; + } + + bp = netdev_priv(dev); - flush_scheduled_work(); - /*tasklet_kill(&bp->sp_task);*/ unregister_netdev(dev); if (bp->regview) @@ -9002,34 +9948,43 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp = netdev_priv(dev); - int rc; + struct bnx2x *bp; + + if (!dev) + return 0; if (!netif_running(dev)) return 0; - rc = bnx2x_nic_unload(bp, 0); - if (!rc) - return rc; + bp = netdev_priv(dev); + + bnx2x_nic_unload(bp, 0); netif_device_detach(dev); - pci_save_state(pdev); + pci_save_state(pdev); bnx2x_set_power_state(bp, pci_choose_state(pdev, state)); + return 0; } static int bnx2x_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp = netdev_priv(dev); + struct bnx2x *bp; int rc; + if (!dev) { + printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); + return -ENODEV; + } + if (!netif_running(dev)) return 0; - pci_restore_state(pdev); + bp = netdev_priv(dev); + pci_restore_state(pdev); bnx2x_set_power_state(bp, PCI_D0); netif_device_attach(dev); diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 4f7ae6f7745..4f0c0d31e7c 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 @@ -24,6 +24,8 @@ #define BNX2X_MSG_STATS 0x20000 /* was: NETIF_MSG_TIMER */ #define NETIF_MSG_NVM 0x40000 /* was: NETIF_MSG_HW */ #define NETIF_MSG_DMAE 0x80000 /* was: NETIF_MSG_HW */ +#define BNX2X_MSG_SP 0x100000 /* was: NETIF_MSG_INTR */ +#define BNX2X_MSG_FP 0x200000 /* was: NETIF_MSG_INTR */ #define DP_LEVEL KERN_NOTICE /* was: KERN_DEBUG */ @@ -40,6 +42,12 @@ __LINE__, bp->dev?(bp->dev->name):"?", ##__args); \ } while (0) +/* for logging (never masked) */ +#define BNX2X_LOG(__fmt, __args...) do { \ + printk(KERN_NOTICE "[%s:%d(%s)]" __fmt, __FUNCTION__, \ + __LINE__, bp->dev?(bp->dev->name):"?", ##__args); \ + } while (0) + /* before we have a dev->name use dev_info() */ #define BNX2X_DEV_INFO(__fmt, __args...) do { \ if (bp->msglevel & NETIF_MSG_PROBE) \ @@ -423,8 +431,6 @@ struct bnx2x_fastpath { #define BNX2X_FP_STATE_OPEN 0xa0000 #define BNX2X_FP_STATE_HALTING 0xb0000 #define BNX2X_FP_STATE_HALTED 0xc0000 -#define BNX2X_FP_STATE_DELETED 0xd0000 -#define BNX2X_FP_STATE_CLOSE_IRQ 0xe0000 int index; @@ -505,7 +511,6 @@ struct bnx2x { struct eth_spe *spq; dma_addr_t spq_mapping; u16 spq_prod_idx; - u16 dsb_sp_prod_idx; struct eth_spe *spq_prod_bd; struct eth_spe *spq_last_bd; u16 *dsb_sp_prod; @@ -517,7 +522,7 @@ struct bnx2x { */ u8 stat_pending; - /* End of fileds used in the performance code paths */ + /* End of fields used in the performance code paths */ int panic; int msglevel; @@ -540,8 +545,6 @@ struct bnx2x { spinlock_t phy_lock; struct work_struct reset_task; - u16 in_reset_task; - struct work_struct sp_task; struct timer_list timer; @@ -555,7 +558,6 @@ struct bnx2x { #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) -#define CHIP_NUM_5710 0x57100000 #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) #define CHIP_REV_Ax 0x00000000 @@ -574,7 +576,8 @@ struct bnx2x { u32 fw_mb; u32 hw_config; - u32 serdes_config; + u32 board; + u32 serdes_config; u32 lane_config; u32 ext_phy_config; #define XGXS_EXT_PHY_TYPE(bp) (bp->ext_phy_config & \ @@ -595,11 +598,11 @@ struct bnx2x { u8 tx_lane_swap; u8 link_up; + u8 phy_link_up; u32 supported; /* link settings - missing defines */ #define SUPPORTED_2500baseT_Full (1 << 15) -#define SUPPORTED_CX4 (1 << 16) u32 phy_flags; /*#define PHY_SERDES_FLAG 0x1*/ @@ -644,16 +647,9 @@ struct bnx2x { #define FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH #define FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE - u32 pause_mode; -#define PAUSE_NONE 0 -#define PAUSE_SYMMETRIC 1 -#define PAUSE_ASYMMETRIC 2 -#define PAUSE_BOTH 3 - u32 advertising; /* link settings - missing defines */ #define ADVERTISED_2500baseT_Full (1 << 15) -#define ADVERTISED_CX4 (1 << 16) u32 link_status; u32 line_speed; @@ -667,6 +663,8 @@ struct bnx2x { #define NVRAM_TIMEOUT_COUNT 30000 #define NVRAM_PAGE_SIZE 256 + u8 wol; + int rx_ring_size; u16 tx_quick_cons_trip_int; @@ -718,9 +716,6 @@ struct bnx2x { #endif char *name; - u16 bus_speed_mhz; - u8 wol; - u8 pad; /* used to synchronize stats collecting */ int stats_state; @@ -856,8 +851,8 @@ struct bnx2x { #define MAX_SPQ_PENDING 8 -#define BNX2X_NUM_STATS 31 -#define BNX2X_NUM_TESTS 2 +#define BNX2X_NUM_STATS 34 +#define BNX2X_NUM_TESTS 1 #define DPM_TRIGER_TYPE 0x40 @@ -867,6 +862,15 @@ struct bnx2x { DPM_TRIGER_TYPE); \ } while (0) +/* PCIE link and speed */ +#define PCICFG_LINK_WIDTH 0x1f00000 +#define PCICFG_LINK_WIDTH_SHIFT 20 +#define PCICFG_LINK_SPEED 0xf0000 +#define PCICFG_LINK_SPEED_SHIFT 16 + +#define BMAC_CONTROL_RX_ENABLE 2 + +#define pbd_tcp_flags(skb) (ntohl(tcp_flag_word(tcp_hdr(skb)))>>16 & 0xff) /* stuff added to make the code fit 80Col */ @@ -939,13 +943,13 @@ struct bnx2x { #define LINK_16GTFD LINK_STATUS_SPEED_AND_DUPLEX_16GTFD #define LINK_16GXFD LINK_STATUS_SPEED_AND_DUPLEX_16GXFD -#define NIG_STATUS_INTERRUPT_XGXS0_LINK10G \ +#define NIG_STATUS_XGXS0_LINK10G \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G -#define NIG_XGXS0_LINK_STATUS \ +#define NIG_STATUS_XGXS0_LINK_STATUS \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS -#define NIG_XGXS0_LINK_STATUS_SIZE \ +#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE -#define NIG_SERDES0_LINK_STATUS \ +#define NIG_STATUS_SERDES0_LINK_STATUS \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS #define NIG_MASK_MI_INT \ NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x_fw_defs.h index 62a6eb81025..3b968904ca6 100644 --- a/drivers/net/bnx2x_fw_defs.h +++ b/drivers/net/bnx2x_fw_defs.h @@ -1,6 +1,6 @@ /* bnx2x_fw_defs.h: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index 6fd959c34d1..b21075ccb52 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h @@ -1,6 +1,6 @@ /* bnx2x_hsi.h: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 @@ -8,169 +8,9 @@ */ -#define FUNC_0 0 -#define FUNC_1 1 -#define FUNC_MAX 2 - - -/* This value (in milliseconds) determines the frequency of the driver - * issuing the PULSE message code. The firmware monitors this periodic - * pulse to determine when to switch to an OS-absent mode. */ -#define DRV_PULSE_PERIOD_MS 250 - -/* This value (in milliseconds) determines how long the driver should - * wait for an acknowledgement from the firmware before timing out. Once - * the firmware has timed out, the driver will assume there is no firmware - * running and there won't be any firmware-driver synchronization during a - * driver reset. */ -#define FW_ACK_TIME_OUT_MS 5000 - -#define FW_ACK_POLL_TIME_MS 1 - -#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS) - -/* LED Blink rate that will achieve ~15.9Hz */ -#define LED_BLINK_RATE_VAL 480 - -/**************************************************************************** - * Driver <-> FW Mailbox * - ****************************************************************************/ -struct drv_fw_mb { - u32 drv_mb_header; -#define DRV_MSG_CODE_MASK 0xffff0000 -#define DRV_MSG_CODE_LOAD_REQ 0x10000000 -#define DRV_MSG_CODE_LOAD_DONE 0x11000000 -#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000 -#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000 -#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000 -#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 -#define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000 -#define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000 -#define DRV_MSG_CODE_VALIDATE_KEY 0x70000000 -#define DRV_MSG_CODE_GET_CURR_KEY 0x80000000 -#define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000 -#define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000 -#define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000 - -#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff - - u32 drv_mb_param; - - u32 fw_mb_header; -#define FW_MSG_CODE_MASK 0xffff0000 -#define FW_MSG_CODE_DRV_LOAD_COMMON 0x11000000 -#define FW_MSG_CODE_DRV_LOAD_PORT 0x12000000 -#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x13000000 -#define FW_MSG_CODE_DRV_LOAD_DONE 0x14000000 -#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x21000000 -#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x22000000 -#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x23000000 -#define FW_MSG_CODE_DIAG_ENTER_DONE 0x50000000 -#define FW_MSG_CODE_DIAG_REFUSE 0x51000000 -#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70000000 -#define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x71000000 -#define FW_MSG_CODE_GET_KEY_DONE 0x80000000 -#define FW_MSG_CODE_NO_KEY 0x8f000000 -#define FW_MSG_CODE_LIC_INFO_NOT_READY 0x8f800000 -#define FW_MSG_CODE_L2B_PRAM_LOADED 0x90000000 -#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x91000000 -#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x92000000 -#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x93000000 -#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x94000000 - -#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff - - u32 fw_mb_param; - - u32 link_status; - /* Driver should update this field on any link change event */ - -#define LINK_STATUS_LINK_FLAG_MASK 0x00000001 -#define LINK_STATUS_LINK_UP 0x00000001 -#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E -#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD (11<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD (11<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD (12<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD (12<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD (13<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD (13<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD (14<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD (14<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD (15<<1) -#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD (15<<1) - -#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020 -#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020 - -#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040 -#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080 -#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080 - -#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200 -#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400 -#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800 -#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000 -#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000 -#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000 -#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000 - -#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000 -#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000 - -#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000 -#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000 - -#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000 -#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18) -#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18) -#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18) -#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18) - -#define LINK_STATUS_SERDES_LINK 0x00100000 - -#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000 -#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000 -#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000 -#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 0x01000000 -#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE 0x02000000 -#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 0x04000000 -#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 0x08000000 -#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 0x10000000 - - u32 drv_pulse_mb; -#define DRV_PULSE_SEQ_MASK 0x00007fff -#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000 - /* The system time is in the format of - * (year-2001)*12*32 + month*32 + day. */ -#define DRV_PULSE_ALWAYS_ALIVE 0x00008000 - /* Indicate to the firmware not to go into the - * OS-absent when it is not getting driver pulse. - * This is used for debugging as well for PXE(MBA). */ - - u32 mcp_pulse_mb; -#define MCP_PULSE_SEQ_MASK 0x00007fff -#define MCP_PULSE_ALWAYS_ALIVE 0x00008000 - /* Indicates to the driver not to assert due to lack - * of MCP response */ -#define MCP_EVENT_MASK 0xffff0000 -#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000 - -}; - +#define PORT_0 0 +#define PORT_1 1 +#define PORT_MAX 2 /**************************************************************************** * Shared HW configuration * @@ -249,7 +89,7 @@ struct shared_hw_cfg { /* NVRAM Offset */ #define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000 #define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000 -#define SHARED_HW_CFG_HIDE_FUNC1 0x00002000 +#define SHARED_HW_CFG_HIDE_PORT1 0x00002000 u32 power_dissipated; /* 0x11c */ #define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000 @@ -290,6 +130,8 @@ struct shared_hw_cfg { /* NVRAM Offset */ #define SHARED_HW_CFG_BOARD_TYPE_BCM957710T1015G 0x00000006 #define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1020G 0x00000007 #define SHARED_HW_CFG_BOARD_TYPE_BCM957710T1003G 0x00000008 +#define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G 0x00000009 +#define SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G 0x0000000a #define SHARED_HW_CFG_BOARD_VER_MASK 0xffff0000 #define SHARED_HW_CFG_BOARD_VER_SHIFT 16 @@ -304,13 +146,12 @@ struct shared_hw_cfg { /* NVRAM Offset */ }; + /**************************************************************************** * Port HW configuration * ****************************************************************************/ -struct port_hw_cfg { /* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */ +struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ - /* Fields below are port specific (in anticipation of dual port - devices */ u32 pci_id; #define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xffff0000 #define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000ffff @@ -420,6 +261,8 @@ struct port_hw_cfg { /* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8276 0x00000600 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700 +#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800 +#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00 #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000ff @@ -462,11 +305,13 @@ struct port_hw_cfg { /* function 0: 0x12c-0x2bb, function 1: 0x2bc-0x44b */ }; + /**************************************************************************** * Shared Feature configuration * ****************************************************************************/ struct shared_feat_cfg { /* NVRAM Offset */ - u32 bmc_common; /* 0x450 */ + + u32 config; /* 0x450 */ #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001 }; @@ -475,7 +320,8 @@ struct shared_feat_cfg { /* NVRAM Offset */ /**************************************************************************** * Port Feature configuration * ****************************************************************************/ -struct port_feat_cfg { /* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */ +struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */ + u32 config; #define PORT_FEATURE_BAR1_SIZE_MASK 0x0000000f #define PORT_FEATURE_BAR1_SIZE_SHIFT 0 @@ -609,8 +455,7 @@ struct port_feat_cfg { /* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */ #define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe #define PORT_FEATURE_SMBUS_ADDR_SHIFT 1 - u32 iscsib_boot_cfg; -#define PORT_FEATURE_ISCSIB_SKIP_TARGET_BOOT 0x00000001 + u32 reserved1; u32 link_config; /* Used as HW defaults for the driver */ #define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000 @@ -657,20 +502,201 @@ struct port_feat_cfg { /* function 0: 0x454-0x4c7, function 1: 0x4c8-0x53b */ }; +/***************************************************************************** + * Device Information * + *****************************************************************************/ +struct dev_info { /* size */ + + u32 bc_rev; /* 8 bits each: major, minor, build */ /* 4 */ + + struct shared_hw_cfg shared_hw_config; /* 40 */ + + struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */ + + struct shared_feat_cfg shared_feature_config; /* 4 */ + + struct port_feat_cfg port_feature_config[PORT_MAX]; /* 116*2=232 */ + +}; + + +#define FUNC_0 0 +#define FUNC_1 1 +#define E1_FUNC_MAX 2 +#define FUNC_MAX E1_FUNC_MAX + + +/* This value (in milliseconds) determines the frequency of the driver + * issuing the PULSE message code. The firmware monitors this periodic + * pulse to determine when to switch to an OS-absent mode. */ +#define DRV_PULSE_PERIOD_MS 250 + +/* This value (in milliseconds) determines how long the driver should + * wait for an acknowledgement from the firmware before timing out. Once + * the firmware has timed out, the driver will assume there is no firmware + * running and there won't be any firmware-driver synchronization during a + * driver reset. */ +#define FW_ACK_TIME_OUT_MS 5000 + +#define FW_ACK_POLL_TIME_MS 1 + +#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS) + +/* LED Blink rate that will achieve ~15.9Hz */ +#define LED_BLINK_RATE_VAL 480 + /**************************************************************************** - * Device Information * + * Driver <-> FW Mailbox * ****************************************************************************/ -struct dev_info { /* size */ +struct drv_port_mb { + + u32 link_status; + /* Driver should update this field on any link change event */ + +#define LINK_STATUS_LINK_FLAG_MASK 0x00000001 +#define LINK_STATUS_LINK_UP 0x00000001 +#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E +#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD (11<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD (11<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD (12<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD (12<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD (13<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD (13<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD (14<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD (14<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD (15<<1) +#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD (15<<1) + +#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020 +#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020 + +#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040 +#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080 +#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080 + +#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200 +#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400 +#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800 +#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000 +#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000 +#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000 +#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000 + +#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000 +#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000 + +#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000 +#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000 + +#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000 +#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18) +#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18) +#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18) +#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18) + +#define LINK_STATUS_SERDES_LINK 0x00100000 + +#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000 +#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000 +#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000 +#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 0x01000000 +#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE 0x02000000 +#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 0x04000000 +#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 0x08000000 +#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 0x10000000 - u32 bc_rev; /* 8 bits each: major, minor, build */ /* 4 */ + u32 reserved[3]; - struct shared_hw_cfg shared_hw_config; /* 40 */ +}; + + +struct drv_func_mb { + + u32 drv_mb_header; +#define DRV_MSG_CODE_MASK 0xffff0000 +#define DRV_MSG_CODE_LOAD_REQ 0x10000000 +#define DRV_MSG_CODE_LOAD_DONE 0x11000000 +#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000 +#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000 +#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000 +#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 +#define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000 +#define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000 +#define DRV_MSG_CODE_VALIDATE_KEY 0x70000000 +#define DRV_MSG_CODE_GET_CURR_KEY 0x80000000 +#define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000 +#define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000 +#define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000 + +#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff + + u32 drv_mb_param; + + u32 fw_mb_header; +#define FW_MSG_CODE_MASK 0xffff0000 +#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000 +#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000 +#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000 +#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000 +#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000 +#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000 +#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000 +#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000 +#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 +#define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000 +#define FW_MSG_CODE_DIAG_REFUSE 0x50200000 +#define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000 +#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000 +#define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000 +#define FW_MSG_CODE_GET_KEY_DONE 0x80100000 +#define FW_MSG_CODE_NO_KEY 0x80f00000 +#define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000 +#define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000 +#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000 +#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000 +#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000 +#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000 + +#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff + + u32 fw_mb_param; + + u32 drv_pulse_mb; +#define DRV_PULSE_SEQ_MASK 0x00007fff +#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000 + /* The system time is in the format of + * (year-2001)*12*32 + month*32 + day. */ +#define DRV_PULSE_ALWAYS_ALIVE 0x00008000 + /* Indicate to the firmware not to go into the + * OS-absent when it is not getting driver pulse. + * This is used for debugging as well for PXE(MBA). */ - struct port_hw_cfg port_hw_config[FUNC_MAX]; /* 400*2=800 */ + u32 mcp_pulse_mb; +#define MCP_PULSE_SEQ_MASK 0x00007fff +#define MCP_PULSE_ALWAYS_ALIVE 0x00008000 + /* Indicates to the driver not to assert due to lack + * of MCP response */ +#define MCP_EVENT_MASK 0xffff0000 +#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000 - struct shared_feat_cfg shared_feature_config; /* 4 */ + u32 iscsi_boot_signature; + u32 iscsi_boot_block_offset; - struct port_feat_cfg port_feature_config[FUNC_MAX];/* 116*2=232 */ + u32 reserved[3]; }; @@ -678,9 +704,8 @@ struct dev_info { /* size */ /**************************************************************************** * Management firmware state * ****************************************************************************/ -/* Allocate 320 bytes for management firmware: still not known exactly - * how much IMD needs. */ -#define MGMTFW_STATE_WORD_SIZE 80 +/* Allocate 440 bytes for management firmware */ +#define MGMTFW_STATE_WORD_SIZE 110 struct mgmtfw_state { u32 opaque[MGMTFW_STATE_WORD_SIZE]; @@ -691,31 +716,40 @@ struct mgmtfw_state { * Shared Memory Region * ****************************************************************************/ struct shmem_region { /* SharedMem Offset (size) */ - u32 validity_map[FUNC_MAX]; /* 0x0 (4 * 2 = 0x8) */ -#define SHR_MEM_VALIDITY_PCI_CFG 0x00000001 -#define SHR_MEM_VALIDITY_MB 0x00000002 -#define SHR_MEM_VALIDITY_DEV_INFO 0x00000004 + + u32 validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */ +#define SHR_MEM_FORMAT_REV_ID ('A'<<24) +#define SHR_MEM_FORMAT_REV_MASK 0xff000000 + /* validity bits */ +#define SHR_MEM_VALIDITY_PCI_CFG 0x00100000 +#define SHR_MEM_VALIDITY_MB 0x00200000 +#define SHR_MEM_VALIDITY_DEV_INFO 0x00400000 +#define SHR_MEM_VALIDITY_RESERVED 0x00000007 /* One licensing bit should be set */ #define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038 #define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008 #define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010 #define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020 + /* Active MFW */ +#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000 +#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040 +#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080 +#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0 +#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0 +#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0 - struct drv_fw_mb drv_fw_mb[FUNC_MAX]; /* 0x8 (28 * 2 = 0x38) */ - - struct dev_info dev_info; /* 0x40 (0x438) */ + struct dev_info dev_info; /* 0x8 (0x438) */ -#ifdef _LICENSE_H - license_key_t drv_lic_key[FUNC_MAX]; /* 0x478 (52 * 2 = 0x68) */ -#else /* Linux! */ - u8 reserved[52*FUNC_MAX]; -#endif + u8 reserved[52*PORT_MAX]; /* FW information (for internal FW use) */ - u32 fw_info_fio_offset; /* 0x4e0 (0x4) */ - struct mgmtfw_state mgmtfw_state; /* 0x4e4 (0x140) */ + u32 fw_info_fio_offset; /* 0x4a8 (0x4) */ + struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */ + + struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */ + struct drv_func_mb func_mb[FUNC_MAX]; /* 0x684 (44*2=0x58) */ -}; /* 0x624 */ +}; /* 0x6dc */ #define BCM_5710_FW_MAJOR_VERSION 4 diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index 04f93bff2ef..dcaecc53bdb 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -1,6 +1,6 @@ /* bnx2x_init.h: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 @@ -409,7 +409,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp) pci_read_config_word(bp->pdev, bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val); - DP(NETIF_MSG_HW, "read 0x%x from devctl\n", val); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", (u16)val); w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5); r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12); @@ -472,10 +472,14 @@ static void bnx2x_init_pxp(struct bnx2x *bp) REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); - REG_WR(bp, PXP2_REG_RQ_WR_MBS0 + 8, w_order); + REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); - REG_WR(bp, PXP2_REG_RQ_RD_MBS0 + 8, r_order); + REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); + if (r_order == MAX_RD_ORD) + REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); + + REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); REG_WR(bp, PXP2_REG_WR_DMAE_TH, (128 << w_order)/16); } diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index 86055297ab0..5a1aa0b5504 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007 Broadcom Corporation + * Copyright (c) 2007-2008 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 @@ -24,6 +24,8 @@ #define BRB1_REG_BRB1_INT_STS 0x6011c /* [RW 4] Parity mask register #0 read/write */ #define BRB1_REG_BRB1_PRTY_MASK 0x60138 +/* [R 4] Parity register #0 read */ +#define BRB1_REG_BRB1_PRTY_STS 0x6012c /* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */ @@ -281,6 +283,8 @@ #define CDU_REG_CDU_INT_STS 0x101030 /* [RW 5] Parity mask register #0 read/write */ #define CDU_REG_CDU_PRTY_MASK 0x10104c +/* [R 5] Parity register #0 read */ +#define CDU_REG_CDU_PRTY_STS 0x101040 /* [RC 32] logging of error data in case of a CDU load error: {expected_cid[15:0]; xpected_type[2:0]; xpected_region[2:0]; ctive_error; ype_error; ctual_active; ctual_compressed_context}; */ @@ -308,6 +312,8 @@ #define CFC_REG_CFC_INT_STS_CLR 0x104100 /* [RW 4] Parity mask register #0 read/write */ #define CFC_REG_CFC_PRTY_MASK 0x104118 +/* [R 4] Parity register #0 read */ +#define CFC_REG_CFC_PRTY_STS 0x10410c /* [RW 21] CID cam access (21:1 - Data; alid - 0) */ #define CFC_REG_CID_CAM 0x104800 #define CFC_REG_CONTROL0 0x104028 @@ -354,6 +360,8 @@ #define CSDM_REG_CSDM_INT_MASK_1 0xc22ac /* [RW 11] Parity mask register #0 read/write */ #define CSDM_REG_CSDM_PRTY_MASK 0xc22bc +/* [R 11] Parity register #0 read */ +#define CSDM_REG_CSDM_PRTY_STS 0xc22b0 #define CSDM_REG_ENABLE_IN1 0xc2238 #define CSDM_REG_ENABLE_IN2 0xc223c #define CSDM_REG_ENABLE_OUT1 0xc2240 @@ -438,6 +446,9 @@ /* [RW 32] Parity mask register #0 read/write */ #define CSEM_REG_CSEM_PRTY_MASK_0 0x200130 #define CSEM_REG_CSEM_PRTY_MASK_1 0x200140 +/* [R 32] Parity register #0 read */ +#define CSEM_REG_CSEM_PRTY_STS_0 0x200124 +#define CSEM_REG_CSEM_PRTY_STS_1 0x200134 #define CSEM_REG_ENABLE_IN 0x2000a4 #define CSEM_REG_ENABLE_OUT 0x2000a8 /* [RW 32] This address space contains all registers and memories that are @@ -526,6 +537,8 @@ #define CSEM_REG_TS_9_AS 0x20005c /* [RW 1] Parity mask register #0 read/write */ #define DBG_REG_DBG_PRTY_MASK 0xc0a8 +/* [R 1] Parity register #0 read */ +#define DBG_REG_DBG_PRTY_STS 0xc09c /* [RW 2] debug only: These bits indicate the credit for PCI request type 4 interface; MUST be configured AFTER pci_ext_buffer_strt_addr_lsb/msb are configured */ @@ -543,6 +556,8 @@ #define DMAE_REG_DMAE_INT_MASK 0x102054 /* [RW 4] Parity mask register #0 read/write */ #define DMAE_REG_DMAE_PRTY_MASK 0x102064 +/* [R 4] Parity register #0 read */ +#define DMAE_REG_DMAE_PRTY_STS 0x102058 /* [RW 1] Command 0 go. */ #define DMAE_REG_GO_C0 0x102080 /* [RW 1] Command 1 go. */ @@ -623,6 +638,8 @@ #define DORQ_REG_DORQ_INT_STS_CLR 0x170178 /* [RW 2] Parity mask register #0 read/write */ #define DORQ_REG_DORQ_PRTY_MASK 0x170190 +/* [R 2] Parity register #0 read */ +#define DORQ_REG_DORQ_PRTY_STS 0x170184 /* [RW 8] The address to write the DPM CID to STORM. */ #define DORQ_REG_DPM_CID_ADDR 0x170044 /* [RW 5] The DPM mode CID extraction offset. */ @@ -692,6 +709,8 @@ #define HC_REG_CONFIG_1 0x108004 /* [RW 3] Parity mask register #0 read/write */ #define HC_REG_HC_PRTY_MASK 0x1080a0 +/* [R 3] Parity register #0 read */ +#define HC_REG_HC_PRTY_STS 0x108094 /* [RW 17] status block interrupt mask; one in each bit means unmask; zerow in each bit means mask; bit 0 - default SB; bit 1 - SB_0; bit 2 - SB_1... bit 16- SB_15; addr 0 - port 0; addr 1 - port 1 */ @@ -1127,6 +1146,7 @@ #define MISC_REG_AEU_GENERAL_ATTN_17 0xa044 #define MISC_REG_AEU_GENERAL_ATTN_18 0xa048 #define MISC_REG_AEU_GENERAL_ATTN_19 0xa04c +#define MISC_REG_AEU_GENERAL_ATTN_10 0xa028 #define MISC_REG_AEU_GENERAL_ATTN_11 0xa02c #define MISC_REG_AEU_GENERAL_ATTN_2 0xa008 #define MISC_REG_AEU_GENERAL_ATTN_20 0xa050 @@ -1135,6 +1155,9 @@ #define MISC_REG_AEU_GENERAL_ATTN_4 0xa010 #define MISC_REG_AEU_GENERAL_ATTN_5 0xa014 #define MISC_REG_AEU_GENERAL_ATTN_6 0xa018 +#define MISC_REG_AEU_GENERAL_ATTN_7 0xa01c +#define MISC_REG_AEU_GENERAL_ATTN_8 0xa020 +#define MISC_REG_AEU_GENERAL_ATTN_9 0xa024 /* [RW 32] first 32b for inverting the input for function 0; for each bit: 0= do not invert; 1= invert; mapped as follows: [0] NIG attention for function0; [1] NIG attention for function1; [2] GPIO1 mcp; [3] GPIO2 mcp; @@ -1183,6 +1206,40 @@ starts at 0x0 for the A0 tape-out and increments by one for each all-layer tape-out. */ #define MISC_REG_CHIP_REV 0xa40c +/* [RW 32] The following driver registers(1..6) represent 6 drivers and 32 + clients. Each client can be controlled by one driver only. One in each + bit represent that this driver control the appropriate client (Ex: bit 5 + is set means this driver control client number 5). addr1 = set; addr0 = + clear; read from both addresses will give the same result = status. write + to address 1 will set a request to control all the clients that their + appropriate bit (in the write command) is set. if the client is free (the + appropriate bit in all the other drivers is clear) one will be written to + that driver register; if the client isn't free the bit will remain zero. + if the appropriate bit is set (the driver request to gain control on a + client it already controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW + interrupt will be asserted). write to address 0 will set a request to + free all the clients that their appropriate bit (in the write command) is + set. if the appropriate bit is clear (the driver request to free a client + it doesn't controls the ~MISC_REGISTERS_INT_STS.GENERIC_SW interrupt will + be asserted). */ +#define MISC_REG_DRIVER_CONTROL_1 0xa510 +/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of + these bits is written as a '1'; the corresponding SPIO bit will turn off + it's drivers and become an input. This is the reset state of all GPIO + pins. The read value of these bits will be a '1' if that last command + (#SET; #CLR; or #FLOAT) for this bit was a #FLOAT. (reset value 0xff). + [23-20] CLR port 1; 19-16] CLR port 0; When any of these bits is written + as a '1'; the corresponding GPIO bit will drive low. The read value of + these bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for + this bit was a #CLR. (reset value 0). [15-12] SET port 1; 11-8] port 0; + SET When any of these bits is written as a '1'; the corresponding GPIO + bit will drive high (if it has that capability). The read value of these + bits will be a '1' if that last command (#SET; #CLR; or #FLOAT) for this + bit was a #SET. (reset value 0). [7-4] VALUE port 1; [3-0] VALUE port 0; + RO; These bits indicate the read value of each of the eight GPIO pins. + This is the result value of the pin; not the drive value. Writing these + bits will have not effect. */ +#define MISC_REG_GPIO 0xa490 /* [RW 1] Setting this bit enables a timer in the GRC block to timeout any access that does not finish within ~misc_registers_grc_timout_val.grc_timeout_val cycles. When this bit is @@ -1223,6 +1280,8 @@ #define MISC_REG_MISC_INT_MASK 0xa388 /* [RW 1] Parity mask register #0 read/write */ #define MISC_REG_MISC_PRTY_MASK 0xa398 +/* [R 1] Parity register #0 read */ +#define MISC_REG_MISC_PRTY_STS 0xa38c /* [RW 32] 32 LSB of storm PLL first register; reset val = 0x 071d2911. inside order of the bits is: [0] P1 divider[0] (reset value 1); [1] P1 divider[1] (reset value 0); [2] P1 divider[2] (reset value 0); [3] P1 @@ -1264,6 +1323,55 @@ /* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is shared with the driver resides */ #define MISC_REG_SHARED_MEM_ADDR 0xa2b4 +/* [RW 32] SPIO. [31-24] FLOAT When any of these bits is written as a '1'; + the corresponding SPIO bit will turn off it's drivers and become an + input. This is the reset state of all SPIO pins. The read value of these + bits will be a '1' if that last command (#SET; #CL; or #FLOAT) for this + bit was a #FLOAT. (reset value 0xff). [23-16] CLR When any of these bits + is written as a '1'; the corresponding SPIO bit will drive low. The read + value of these bits will be a '1' if that last command (#SET; #CLR; or +#FLOAT) for this bit was a #CLR. (reset value 0). [15-8] SET When any of + these bits is written as a '1'; the corresponding SPIO bit will drive + high (if it has that capability). The read value of these bits will be a + '1' if that last command (#SET; #CLR; or #FLOAT) for this bit was a #SET. + (reset value 0). [7-0] VALUE RO; These bits indicate the read value of + each of the eight SPIO pins. This is the result value of the pin; not the + drive value. Writing these bits will have not effect. Each 8 bits field + is divided as follows: [0] VAUX Enable; when pulsed low; enables supply + from VAUX. (This is an output pin only; the FLOAT field is not applicable + for this pin); [1] VAUX Disable; when pulsed low; disables supply form + VAUX. (This is an output pin only; FLOAT field is not applicable for this + pin); [2] SEL_VAUX_B - Control to power switching logic. Drive low to + select VAUX supply. (This is an output pin only; it is not controlled by + the SET and CLR fields; it is controlled by the Main Power SM; the FLOAT + field is not applicable for this pin; only the VALUE fields is relevant - + it reflects the output value); [3] reserved; [4] spio_4; [5] spio_5; [6] + Bit 0 of UMP device ID select; read by UMP firmware; [7] Bit 1 of UMP + device ID select; read by UMP firmware. */ +#define MISC_REG_SPIO 0xa4fc +/* [RW 8] These bits enable the SPIO_INTs to signals event to the IGU/MC. + according to the following map: [3:0] reserved; [4] spio_4 [5] spio_5; + [7:0] reserved */ +#define MISC_REG_SPIO_EVENT_EN 0xa2b8 +/* [RW 32] SPIO INT. [31-24] OLD_CLR Writing a '1' to these bit clears the + corresponding bit in the #OLD_VALUE register. This will acknowledge an + interrupt on the falling edge of corresponding SPIO input (reset value + 0). [23-16] OLD_SET Writing a '1' to these bit sets the corresponding bit + in the #OLD_VALUE register. This will acknowledge an interrupt on the + rising edge of corresponding SPIO input (reset value 0). [15-8] OLD_VALUE + RO; These bits indicate the old value of the SPIO input value. When the + ~INT_STATE bit is set; this bit indicates the OLD value of the pin such + that if ~INT_STATE is set and this bit is '0'; then the interrupt is due + to a low to high edge. If ~INT_STATE is set and this bit is '1'; then the + interrupt is due to a high to low edge (reset value 0). [7-0] INT_STATE + RO; These bits indicate the current SPIO interrupt state for each SPIO + pin. This bit is cleared when the appropriate #OLD_SET or #OLD_CLR + command bit is written. This bit is set when the SPIO input does not + match the current value in #OLD_VALUE (reset value 0). */ +#define MISC_REG_SPIO_INT 0xa500 +/* [RW 1] Set by the MCP to remember if one or more of the drivers is/are + loaded; 0-prepare; -unprepare */ +#define MISC_REG_UNPREPARED 0xa424 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT (0x1<<0) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS (0x1<<9) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G (0x1<<15) @@ -1392,6 +1500,9 @@ #define NIG_REG_NIG_INGRESS_EMAC0_NO_CRC 0x10044 /* [RW 1] Input enable for RX PBF LP IF */ #define NIG_REG_PBF_LB_IN_EN 0x100b4 +/* [RW 1] Value of this register will be transmitted to port swap when + ~nig_registers_strap_override.strap_override =1 */ +#define NIG_REG_PORT_SWAP 0x10394 /* [RW 1] output enable for RX parser descriptor IF */ #define NIG_REG_PRS_EOP_OUT_EN 0x10104 /* [RW 1] Input enable for RX parser request IF */ @@ -1410,6 +1521,10 @@ #define NIG_REG_STAT2_BRB_OCTET 0x107e0 #define NIG_REG_STATUS_INTERRUPT_PORT0 0x10328 #define NIG_REG_STATUS_INTERRUPT_PORT1 0x1032c +/* [RW 1] port swap mux selection. If this register equal to 0 then port + swap is equal to SPIO pin that inputs from ifmux_serdes_swap. If 1 then + ort swap is equal to ~nig_registers_port_swap.port_swap */ +#define NIG_REG_STRAP_OVERRIDE 0x10398 /* [RW 1] output enable for RX_XCM0 IF */ #define NIG_REG_XCM0_OUT_EN 0x100f0 /* [RW 1] output enable for RX_XCM1 IF */ @@ -1499,6 +1614,8 @@ #define PB_REG_PB_INT_STS 0x1c /* [RW 4] Parity mask register #0 read/write */ #define PB_REG_PB_PRTY_MASK 0x38 +/* [R 4] Parity register #0 read */ +#define PB_REG_PB_PRTY_STS 0x2c #define PRS_REG_A_PRSU_20 0x40134 /* [R 8] debug only: CFC load request current credit. Transaction based. */ #define PRS_REG_CFC_LD_CURRENT_CREDIT 0x40164 @@ -1590,6 +1707,8 @@ #define PRS_REG_PRS_INT_STS 0x40188 /* [RW 8] Parity mask register #0 read/write */ #define PRS_REG_PRS_PRTY_MASK 0x401a4 +/* [R 8] Parity register #0 read */ +#define PRS_REG_PRS_PRTY_STS 0x40198 /* [RW 8] Context region for pure acknowledge packets. Used in CFC load request message */ #define PRS_REG_PURE_REGIONS 0x40024 @@ -1718,6 +1837,9 @@ /* [RW 32] Parity mask register #0 read/write */ #define PXP2_REG_PXP2_PRTY_MASK_0 0x120588 #define PXP2_REG_PXP2_PRTY_MASK_1 0x120598 +/* [R 32] Parity register #0 read */ +#define PXP2_REG_PXP2_PRTY_STS_0 0x12057c +#define PXP2_REG_PXP2_PRTY_STS_1 0x12058c /* [R 1] Debug only: The 'almost full' indication from each fifo (gives indication about backpressure) */ #define PXP2_REG_RD_ALMOST_FULL_0 0x120424 @@ -1911,6 +2033,8 @@ #define PXP2_REG_RQ_HC_ENDIAN_M 0x1201a8 /* [WB 53] Onchip address table */ #define PXP2_REG_RQ_ONCHIP_AT 0x122000 +/* [RW 13] Pending read limiter threshold; in Dwords */ +#define PXP2_REG_RQ_PDR_LIMIT 0x12033c /* [RW 2] Endian mode for qm */ #define PXP2_REG_RQ_QM_ENDIAN_M 0x120194 /* [RW 3] page size in L2P table for QM module; -4k; -8k; -16k; -32k; -64k; @@ -1921,6 +2045,9 @@ /* [RW 3] Max burst size filed for read requests port 0; 000 - 128B; 001:256B; 010: 512B; 11:1K:100:2K; 01:4K */ #define PXP2_REG_RQ_RD_MBS0 0x120160 +/* [RW 3] Max burst size filed for read requests port 1; 000 - 128B; + 001:256B; 010: 512B; 11:1K:100:2K; 01:4K */ +#define PXP2_REG_RQ_RD_MBS1 0x120168 /* [RW 2] Endian mode for src */ #define PXP2_REG_RQ_SRC_ENDIAN_M 0x12019c /* [RW 3] page size in L2P table for SRC module; -4k; -8k; -16k; -32k; -64k; @@ -2000,10 +2127,17 @@ /* [RW 3] Max burst size filed for write requests port 0; 000 - 128B; 001:256B; 010: 512B; */ #define PXP2_REG_RQ_WR_MBS0 0x12015c +/* [RW 3] Max burst size filed for write requests port 1; 000 - 128B; + 001:256B; 010: 512B; */ +#define PXP2_REG_RQ_WR_MBS1 0x120164 /* [RW 10] if Number of entries in dmae fifo will be higer than this threshold then has_payload indication will be asserted; the default value should be equal to > write MBS size! */ #define PXP2_REG_WR_DMAE_TH 0x120368 +/* [RW 10] if Number of entries in usdmdp fifo will be higer than this + threshold then has_payload indication will be asserted; the default value + should be equal to > write MBS size! */ +#define PXP2_REG_WR_USDMDP_TH 0x120348 /* [R 1] debug only: Indication if PSWHST arbiter is idle */ #define PXP_REG_HST_ARB_IS_IDLE 0x103004 /* [R 8] debug only: A bit mask for all PSWHST arbiter clients. '1' means @@ -2021,6 +2155,8 @@ #define PXP_REG_PXP_INT_STS_CLR_0 0x10306c /* [RW 26] Parity mask register #0 read/write */ #define PXP_REG_PXP_PRTY_MASK 0x103094 +/* [R 26] Parity register #0 read */ +#define PXP_REG_PXP_PRTY_STS 0x103088 /* [RW 4] The activity counter initial increment value sent in the load request */ #define QM_REG_ACTCTRINITVAL_0 0x168040 @@ -2127,6 +2263,8 @@ #define QM_REG_QM_INT_STS 0x168438 /* [RW 9] Parity mask register #0 read/write */ #define QM_REG_QM_PRTY_MASK 0x168454 +/* [R 9] Parity register #0 read */ +#define QM_REG_QM_PRTY_STS 0x168448 /* [R 32] Current queues in pipeline: Queues from 32 to 63 */ #define QM_REG_QSTATUS_HIGH 0x16802c /* [R 32] Current queues in pipeline: Queues from 0 to 31 */ @@ -2410,6 +2548,8 @@ #define SRC_REG_SRC_INT_STS 0x404ac /* [RW 3] Parity mask register #0 read/write */ #define SRC_REG_SRC_PRTY_MASK 0x404c8 +/* [R 3] Parity register #0 read */ +#define SRC_REG_SRC_PRTY_STS 0x404bc /* [R 4] Used to read the value of the XX protection CAM occupancy counter. */ #define TCM_REG_CAM_OCCUP 0x5017c /* [RW 1] CDU AG read Interface enable. If 0 - the request input is @@ -2730,6 +2870,8 @@ #define TSDM_REG_TSDM_INT_MASK_1 0x422ac /* [RW 11] Parity mask register #0 read/write */ #define TSDM_REG_TSDM_PRTY_MASK 0x422bc +/* [R 11] Parity register #0 read */ +#define TSDM_REG_TSDM_PRTY_STS 0x422b0 /* [RW 5] The number of time_slots in the arbitration cycle */ #define TSEM_REG_ARB_CYCLE_SIZE 0x180034 /* [RW 3] The source that is associated with arbitration element 0. Source @@ -2854,6 +2996,9 @@ /* [RW 32] Parity mask register #0 read/write */ #define TSEM_REG_TSEM_PRTY_MASK_0 0x180120 #define TSEM_REG_TSEM_PRTY_MASK_1 0x180130 +/* [R 32] Parity register #0 read */ +#define TSEM_REG_TSEM_PRTY_STS_0 0x180114 +#define TSEM_REG_TSEM_PRTY_STS_1 0x180124 /* [R 5] Used to read the XX protection CAM occupancy counter. */ #define UCM_REG_CAM_OCCUP 0xe0170 /* [RW 1] CDU AG read Interface enable. If 0 - the request input is @@ -3155,6 +3300,8 @@ #define USDM_REG_USDM_INT_MASK_1 0xc42b0 /* [RW 11] Parity mask register #0 read/write */ #define USDM_REG_USDM_PRTY_MASK 0xc42c0 +/* [R 11] Parity register #0 read */ +#define USDM_REG_USDM_PRTY_STS 0xc42b4 /* [RW 5] The number of time_slots in the arbitration cycle */ #define USEM_REG_ARB_CYCLE_SIZE 0x300034 /* [RW 3] The source that is associated with arbitration element 0. Source @@ -3279,6 +3426,9 @@ /* [RW 32] Parity mask register #0 read/write */ #define USEM_REG_USEM_PRTY_MASK_0 0x300130 #define USEM_REG_USEM_PRTY_MASK_1 0x300140 +/* [R 32] Parity register #0 read */ +#define USEM_REG_USEM_PRTY_STS_0 0x300124 +#define USEM_REG_USEM_PRTY_STS_1 0x300134 /* [RW 2] The queue index for registration on Aux1 counter flag. */ #define XCM_REG_AUX1_Q 0x20134 /* [RW 2] Per each decision rule the queue index to register to. */ @@ -3684,6 +3834,8 @@ #define XSDM_REG_XSDM_INT_MASK_1 0x1662ac /* [RW 11] Parity mask register #0 read/write */ #define XSDM_REG_XSDM_PRTY_MASK 0x1662bc +/* [R 11] Parity register #0 read */ +#define XSDM_REG_XSDM_PRTY_STS 0x1662b0 /* [RW 5] The number of time_slots in the arbitration cycle */ #define XSEM_REG_ARB_CYCLE_SIZE 0x280034 /* [RW 3] The source that is associated with arbitration element 0. Source @@ -3808,6 +3960,9 @@ /* [RW 32] Parity mask register #0 read/write */ #define XSEM_REG_XSEM_PRTY_MASK_0 0x280130 #define XSEM_REG_XSEM_PRTY_MASK_1 0x280140 +/* [R 32] Parity register #0 read */ +#define XSEM_REG_XSEM_PRTY_STS_0 0x280124 +#define XSEM_REG_XSEM_PRTY_STS_1 0x280134 #define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0) #define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1) #define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) @@ -3847,6 +4002,8 @@ #define EMAC_MDIO_COMM_START_BUSY (1L<<29) #define EMAC_MDIO_MODE_AUTO_POLL (1L<<4) #define EMAC_MDIO_MODE_CLAUSE_45 (1L<<31) +#define EMAC_MDIO_MODE_CLOCK_CNT (0x3fL<<16) +#define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT 16 #define EMAC_MODE_25G_MODE (1L<<5) #define EMAC_MODE_ACPI_RCVD (1L<<20) #define EMAC_MODE_HALF_DUPLEX (1L<<1) @@ -3874,6 +4031,17 @@ #define EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) #define EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) #define EMAC_TX_MODE_RESET (1L<<0) +#define MISC_REGISTERS_GPIO_1 1 +#define MISC_REGISTERS_GPIO_2 2 +#define MISC_REGISTERS_GPIO_3 3 +#define MISC_REGISTERS_GPIO_CLR_POS 16 +#define MISC_REGISTERS_GPIO_FLOAT (0xffL<<24) +#define MISC_REGISTERS_GPIO_FLOAT_POS 24 +#define MISC_REGISTERS_GPIO_INPUT_HI_Z 2 +#define MISC_REGISTERS_GPIO_OUTPUT_HIGH 1 +#define MISC_REGISTERS_GPIO_OUTPUT_LOW 0 +#define MISC_REGISTERS_GPIO_PORT_SHIFT 4 +#define MISC_REGISTERS_GPIO_SET_POS 8 #define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588 #define MISC_REGISTERS_RESET_REG_1_SET 0x584 #define MISC_REGISTERS_RESET_REG_2_CLEAR 0x598 @@ -3891,6 +4059,25 @@ #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW (0x1<<4) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB (0x1<<8) #define MISC_REGISTERS_RESET_REG_3_SET 0x5a4 +#define MISC_REGISTERS_SPIO_4 4 +#define MISC_REGISTERS_SPIO_5 5 +#define MISC_REGISTERS_SPIO_7 7 +#define MISC_REGISTERS_SPIO_CLR_POS 16 +#define MISC_REGISTERS_SPIO_FLOAT (0xffL<<24) +#define GRC_MISC_REGISTERS_SPIO_FLOAT7 0x80000000 +#define GRC_MISC_REGISTERS_SPIO_FLOAT6 0x40000000 +#define GRC_MISC_REGISTERS_SPIO_FLOAT5 0x20000000 +#define GRC_MISC_REGISTERS_SPIO_FLOAT4 0x10000000 +#define MISC_REGISTERS_SPIO_FLOAT_POS 24 +#define MISC_REGISTERS_SPIO_INPUT_HI_Z 2 +#define MISC_REGISTERS_SPIO_INT_OLD_SET_POS 16 +#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1 +#define MISC_REGISTERS_SPIO_OUTPUT_LOW 0 +#define MISC_REGISTERS_SPIO_SET_POS 8 +#define HW_LOCK_MAX_RESOURCE_VALUE 31 +#define HW_LOCK_RESOURCE_8072_MDIO 0 +#define HW_LOCK_RESOURCE_GPIO 1 +#define HW_LOCK_RESOURCE_SPIO 2 #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (1<<18) #define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (1<<31) #define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (1<<9) @@ -3918,6 +4105,7 @@ #define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (1<<3) #define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (1<<2) #define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (1<<22) +#define AEU_INPUTS_ATTN_BITS_SPIO5 (1<<15) #define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (1<<27) #define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (1<<5) #define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (1<<25) @@ -4206,6 +4394,9 @@ #define MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE 0x4000 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP 0x11 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE 0x8000 +#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G 0x14 +#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS 0x0001 +#define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS 0x0010 #define MDIO_XGXS_BLOCK2_TEST_MODE_LANE 0x15 #define MDIO_REG_BANK_GP_STATUS 0x8120 @@ -4362,11 +4553,13 @@ #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_SGMII_MODE 0x0001 +#define EXT_PHY_AUTO_NEG_DEVAD 0x7 #define EXT_PHY_OPT_PMA_PMD_DEVAD 0x1 #define EXT_PHY_OPT_WIS_DEVAD 0x2 #define EXT_PHY_OPT_PCS_DEVAD 0x3 #define EXT_PHY_OPT_PHY_XS_DEVAD 0x4 #define EXT_PHY_OPT_CNTL 0x0 +#define EXT_PHY_OPT_CNTL2 0x7 #define EXT_PHY_OPT_PMD_RX_SD 0xa #define EXT_PHY_OPT_PMD_MISC_CNTL 0xca0a #define EXT_PHY_OPT_PHY_IDENTIFIER 0xc800 @@ -4378,11 +4571,24 @@ #define EXT_PHY_OPT_LASI_STATUS 0x9005 #define EXT_PHY_OPT_PCS_STATUS 0x0020 #define EXT_PHY_OPT_XGXS_LANE_STATUS 0x0018 +#define EXT_PHY_OPT_AN_LINK_STATUS 0x8304 +#define EXT_PHY_OPT_AN_CL37_CL73 0x8370 +#define EXT_PHY_OPT_AN_CL37_FD 0xffe4 +#define EXT_PHY_OPT_AN_CL37_AN 0xffe0 +#define EXT_PHY_OPT_AN_ADV 0x11 #define EXT_PHY_KR_PMA_PMD_DEVAD 0x1 #define EXT_PHY_KR_PCS_DEVAD 0x3 #define EXT_PHY_KR_AUTO_NEG_DEVAD 0x7 #define EXT_PHY_KR_CTRL 0x0000 +#define EXT_PHY_KR_STATUS 0x0001 +#define EXT_PHY_KR_AUTO_NEG_COMPLETE 0x0020 +#define EXT_PHY_KR_AUTO_NEG_ADVERT 0x0010 +#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE 0x0400 +#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_ASYMMETRIC 0x0800 +#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_BOTH 0x0C00 +#define EXT_PHY_KR_AUTO_NEG_ADVERT_PAUSE_MASK 0x0C00 +#define EXT_PHY_KR_LP_AUTO_NEG 0x0013 #define EXT_PHY_KR_CTRL2 0x0007 #define EXT_PHY_KR_PCS_STATUS 0x0020 #define EXT_PHY_KR_PMD_CTRL 0x0096 @@ -4391,4 +4597,8 @@ #define EXT_PHY_KR_MISC_CTRL1 0xca85 #define EXT_PHY_KR_GEN_CTRL 0xca10 #define EXT_PHY_KR_ROM_CODE 0xca19 +#define EXT_PHY_KR_ROM_RESET_INTERNAL_MP 0x0188 +#define EXT_PHY_KR_ROM_MICRO_RESET 0x018a + +#define EXT_PHY_SFX7101_XGXS_TEST1 0xc00a diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 57175097513..348371fda59 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -172,30 +172,30 @@ static char version[] __initdata = them to system IRQ numbers. This mapping is card specific and is set to the configuration of the Cirrus Eval board for this chip. */ #ifdef CONFIG_ARCH_CLPS7500 -static unsigned int netcard_portlist[] __initdata = +static unsigned int netcard_portlist[] __used __initdata = { 0x80090303, 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; static unsigned int cs8900_irq_map[] = {12,0,0,0}; #elif defined(CONFIG_SH_HICOSH4) -static unsigned int netcard_portlist[] __initdata = +static unsigned int netcard_portlist[] __used __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; #elif defined(CONFIG_MACH_IXDP2351) -static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; +static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; #include <asm/irq.h> #elif defined(CONFIG_ARCH_IXDP2X01) #include <asm/irq.h> -static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; +static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; #elif defined(CONFIG_ARCH_PNX010X) #include <asm/irq.h> #include <asm/arch/gpio.h> #define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ #define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */ -static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0}; +static unsigned int netcard_portlist[] __used __initdata = {CIRRUS_DEFAULT_BASE, 0}; static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0}; #else -static unsigned int netcard_portlist[] __initdata = +static unsigned int netcard_portlist[] __used __initdata = { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; static unsigned int cs8900_irq_map[] = {10,11,12,5}; #endif diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d876787ce33..85e66f4c788 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -50,7 +50,7 @@ struct e1000_stats { int stat_offset; }; -#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ +#define E1000_STAT(m) FIELD_SIZEOF(struct e1000_adapter, m), \ offsetof(struct e1000_adapter, m) static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(stats.gprc) }, diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index d4ee8ec34b5..0991648c53d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1195,6 +1195,14 @@ e1000_probe(struct pci_dev *pdev, printk("%s\n", print_mac(mac, netdev->dev_addr)); + if (adapter->hw.bus_type == e1000_bus_type_pci_express) { + DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no " + "longer be supported by this driver in the future.\n", + pdev->vendor, pdev->device); + DPRINTK(PROBE, WARNING, "please use the \"e1000e\" " + "driver instead.\n"); + } + /* reset the hardware with the new settings */ e1000_reset(adapter); diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 3beace55b58..7fe20310eb5 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -438,7 +438,7 @@ static void e1000_release_nvm_82571(struct e1000_hw *hw) * For non-82573 silicon, write data to EEPROM at offset using SPI interface. * * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likley contain an invalid checksum. + * EEPROM will most likely contain an invalid checksum. **/ static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) @@ -547,7 +547,7 @@ static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) * poll for completion. * * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likley contain an invalid checksum. + * EEPROM will most likely contain an invalid checksum. **/ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) @@ -1053,7 +1053,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) /* If SerDes loopback mode is entered, there is no form * of reset to take the adapter out of that mode. So we * have to explicitly take the adapter out of loopback - * mode. This prevents drivers from twidling their thumbs + * mode. This prevents drivers from twiddling their thumbs * if another tool failed to take it out of loopback mode. */ ew32(SCTL, @@ -1098,7 +1098,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) * e1000e_get_laa_state_82571 - Get locally administered address state * @hw: pointer to the HW structure * - * Retrieve and return the current locally administed address state. + * Retrieve and return the current locally administered address state. **/ bool e1000e_get_laa_state_82571(struct e1000_hw *hw) { @@ -1113,7 +1113,7 @@ bool e1000e_get_laa_state_82571(struct e1000_hw *hw) * @hw: pointer to the HW structure * @state: enable/disable locally administered address * - * Enable/Disable the current locally administed address state. + * Enable/Disable the current locally administers address state. **/ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) { @@ -1281,16 +1281,6 @@ static struct e1000_phy_operations e82_phy_ops_m88 = { static struct e1000_nvm_operations e82571_nvm_ops = { .acquire_nvm = e1000_acquire_nvm_82571, - .read_nvm = e1000e_read_nvm_spi, - .release_nvm = e1000_release_nvm_82571, - .update_nvm = e1000_update_nvm_checksum_82571, - .valid_led_default = e1000_valid_led_default_82571, - .validate_nvm = e1000_validate_nvm_checksum_82571, - .write_nvm = e1000_write_nvm_82571, -}; - -static struct e1000_nvm_operations e82573_nvm_ops = { - .acquire_nvm = e1000_acquire_nvm_82571, .read_nvm = e1000e_read_nvm_eerd, .release_nvm = e1000_release_nvm_82571, .update_nvm = e1000_update_nvm_checksum_82571, @@ -1355,6 +1345,6 @@ struct e1000_info e1000_82573_info = { .get_invariants = e1000_get_invariants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_m88, - .nvm_ops = &e82573_nvm_ops, + .nvm_ops = &e82571_nvm_ops, }; diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 6232c3e9668..a4f511f549f 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -66,7 +66,7 @@ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ /* Extended Device Control */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ +#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 @@ -75,12 +75,12 @@ #define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ #define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ -/* Receive Decriptor bit definitions */ +/* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ #define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ #define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */ +#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ @@ -223,7 +223,7 @@ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ -/* Constants used to intrepret the masked PCI-X bus speed. */ +/* Constants used to interpret the masked PCI-X bus speed. */ #define HALF_DUPLEX 1 #define FULL_DUPLEX 2 @@ -517,7 +517,7 @@ /* PHY 1000 MII Register/Bit Definitions */ /* PHY Registers defined by IEEE */ #define PHY_CONTROL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Regiser */ +#define PHY_STATUS 0x01 /* Status Register */ #define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 8b88c226e85..327c0620da3 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -42,8 +42,7 @@ struct e1000_info; #define ndev_printk(level, netdev, format, arg...) \ - printk(level "%s: %s: " format, (netdev)->dev.parent->bus_id, \ - (netdev)->name, ## arg) + printk(level "%s: " format, (netdev)->name, ## arg) #ifdef DEBUG #define ndev_dbg(netdev, format, arg...) \ diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 3c5862f97db..916025b30fc 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -184,7 +184,7 @@ enum e1e_registers { E1000_ICRXDMTC = 0x04120, /* Irq Cause Rx Desc MinThreshold Count */ E1000_ICRXOC = 0x04124, /* Irq Cause Receiver Overrun Count */ E1000_RXCSUM = 0x05000, /* RX Checksum Control - RW */ - E1000_RFCTL = 0x05008, /* Receive Filter Control*/ + E1000_RFCTL = 0x05008, /* Receive Filter Control */ E1000_MTA = 0x05200, /* Multicast Table Array - RW Array */ E1000_RA = 0x05400, /* Receive Address - RW Array */ E1000_VFTA = 0x05600, /* VLAN Filter Table Array - RW Array */ @@ -202,7 +202,7 @@ enum e1e_registers { E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */ E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ - E1000_HICR = 0x08F00, /* Host Inteface Control */ + E1000_HICR = 0x08F00, /* Host Interface Control */ }; /* RSS registers */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 8f8139de1f4..0ae39550768 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -671,7 +671,7 @@ static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw) * e1000_check_polarity_ife_ich8lan - Check cable polarity for IFE PHY * @hw: pointer to the HW structure * - * Polarity is determined on the polarity reveral feature being enabled. + * Polarity is determined on the polarity reversal feature being enabled. * This function is only called by other family-specific * routines. **/ @@ -947,7 +947,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or * FDONE bit should be changed in the hardware so that it - * is 1 after harware reset, which can then be used as an + * is 1 after hardware reset, which can then be used as an * indication whether a cycle is in progress or has been * completed. */ @@ -1155,7 +1155,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, * which writes the checksum to the shadow ram. The changes in the shadow * ram are then committed to the EEPROM by processing each bank at a time * checking for the modified bit and writing only the pending changes. - * After a succesful commit, the shadow ram is cleared and is ready for + * After a successful commit, the shadow ram is cleared and is ready for * future writes. **/ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) @@ -1680,7 +1680,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) * - initialize LED identification * - setup receive address registers * - setup flow control - * - setup transmit discriptors + * - setup transmit descriptors * - clear statistics **/ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) @@ -1961,7 +1961,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); ew32(PHY_CTRL, phy_ctrl); - /* Call gig speed drop workaround on Giga disable before accessing + /* Call gig speed drop workaround on Gig disable before accessing * any PHY registers */ e1000e_gig_downshift_workaround_ich8lan(hw); @@ -1972,7 +1972,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) /** * e1000_set_kmrn_lock_loss_workaound_ich8lan - Set Kumeran workaround state * @hw: pointer to the HW structure - * @state: boolean value used to set the current Kumaran workaround state + * @state: boolean value used to set the current Kumeran workaround state * * If ICH8, set the current Kumeran workaround state (enabled - TRUE * /disabled - FALSE). @@ -2017,7 +2017,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); ew32(PHY_CTRL, reg); - /* Call gig speed drop workaround on Giga disable before + /* Call gig speed drop workaround on Gig disable before * accessing any PHY registers */ if (hw->mac.type == e1000_ich8lan) e1000e_gig_downshift_workaround_ich8lan(hw); @@ -2045,7 +2045,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) * @hw: pointer to the HW structure * * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), - * LPLU, Giga disable, MDIC PHY reset): + * LPLU, Gig disable, MDIC PHY reset): * 1) Set Kumeran Near-end loopback * 2) Clear Kumeran Near-end loopback * Should only be called for ICH8[m] devices with IGP_3 Phy. @@ -2089,10 +2089,10 @@ static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) } /** - * e1000_led_on_ich8lan - Turn LED's on + * e1000_led_on_ich8lan - Turn LEDs on * @hw: pointer to the HW structure * - * Turn on the LED's. + * Turn on the LEDs. **/ static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) { @@ -2105,10 +2105,10 @@ static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) } /** - * e1000_led_off_ich8lan - Turn LED's off + * e1000_led_off_ich8lan - Turn LEDs off * @hw: pointer to the HW structure * - * Turn off the LED's. + * Turn off the LEDs. **/ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) { diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 16f35fadb74..95f75a43c9f 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -589,9 +589,6 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) s32 ret_val; u16 nvm_data; - if (mac->fc != e1000_fc_default) - return 0; - /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or @@ -1107,34 +1104,13 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { mac->fc = e1000_fc_rx_pause; hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n"); - } - /* Per the IEEE spec, at this point flow control should be - * disabled. However, we want to consider that we could - * be connected to a legacy switch that doesn't advertise - * desired flow control, but can be forced on the link - * partner. So if we advertised no flow control, that is - * what we will resolve to. If we advertised some kind of - * receive capability (Rx Pause Only or Full Flow Control) - * and the link partner advertised none, we will configure - * ourselves to enable Rx Flow Control only. We can do - * this safely for two reasons: If the link partner really - * didn't want flow control enabled, and we enable Rx, no - * harm done since we won't be receiving any PAUSE frames - * anyway. If the intent on the link partner was to have - * flow control enabled, then by us enabling RX only, we - * can at least receive pause frames and process them. - * This is a good idea because in most cases, since we are - * predominantly a server NIC, more times than not we will - * be asked to delay transmission of packets than asking - * our link partner to pause transmission of frames. - */ - else if ((mac->original_fc == e1000_fc_none) || - (mac->original_fc == e1000_fc_tx_pause)) { + } else { + /* + * Per the IEEE spec, at this point flow control + * should be disabled. + */ mac->fc = e1000_fc_none; hw_dbg(hw, "Flow Control = NONE.\r\n"); - } else { - mac->fc = e1000_fc_rx_pause; - hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n"); } /* Now we need to do one last check... If we auto- @@ -1164,7 +1140,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) } /** - * e1000e_get_speed_and_duplex_copper - Retreive current speed/duplex + * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex @@ -1200,7 +1176,7 @@ s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *dup } /** - * e1000e_get_speed_and_duplex_fiber_serdes - Retreive current speed/duplex + * e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex @@ -1410,7 +1386,7 @@ s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) * e1000e_blink_led - Blink LED * @hw: pointer to the HW structure * - * Blink the led's which are set to be on. + * Blink the LEDs which are set to be on. **/ s32 e1000e_blink_led(struct e1000_hw *hw) { @@ -1515,7 +1491,7 @@ void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) * @hw: pointer to the HW structure * * Returns 0 if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not casued + * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused * the master requests to be disabled. * * Disables PCI-Express master access and verifies there are no pending @@ -1876,7 +1852,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) } /** - * e1000e_read_nvm_spi - Read EEPROM's using SPI + * e1000e_read_nvm_spi - Reads EEPROM using SPI * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read @@ -1980,7 +1956,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) * Writes data to EEPROM at offset using SPI interface. * * If e1000e_update_nvm_checksum is not called after this function , the - * EEPROM will most likley contain an invalid checksum. + * EEPROM will most likely contain an invalid checksum. **/ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { @@ -2222,7 +2198,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length) * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * - * This function checks whether the HOST IF is enabled for command operaton + * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ @@ -2254,7 +2230,7 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) } /** - * e1000e_check_mng_mode - check managament mode + * e1000e_check_mng_mode - check management mode * @hw: pointer to the HW structure * * Reads the firmware semaphore register and returns true (>0) if diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f58f017ee47..fc5c63f4f57 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1006,7 +1006,7 @@ static void e1000_irq_enable(struct e1000_adapter *adapter) * e1000_get_hw_control - get control of the h/w from f/w * @adapter: address of board private structure * - * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit. + * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that * the driver is loaded. For AMT version (only with 82573) * of the f/w this means that the network i/f is open. @@ -1032,7 +1032,7 @@ static void e1000_get_hw_control(struct e1000_adapter *adapter) * e1000_release_hw_control - release control of the h/w to f/w * @adapter: address of board private structure * - * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. + * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. For AMT version (only with 82573) i * of the f/w this means that the network i/f is closed. @@ -1055,23 +1055,6 @@ static void e1000_release_hw_control(struct e1000_adapter *adapter) } } -static void e1000_release_manageability(struct e1000_adapter *adapter) -{ - if (adapter->flags & FLAG_MNG_PT_ENABLED) { - struct e1000_hw *hw = &adapter->hw; - - u32 manc = er32(MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - manc &= ~E1000_MANC_EN_MNG2HOST; - - /* don't explicitly have to mess with MANC2H since - * MANC has an enable disable that gates MANC2H */ - ew32(MANC, manc); - } -} - /** * @e1000_alloc_ring - allocate memory for a ring structure **/ @@ -1258,6 +1241,11 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter) /** * e1000_update_itr - update the dynamic ITR value based on statistics + * @adapter: pointer to adapter + * @itr_setting: current adapter->itr + * @packets: the number of packets during this measurement interval + * @bytes: the number of bytes during this measurement interval + * * Stores a new ITR value based on packets and byte * counts during the last interrupt. The advantage of per interrupt * computation is faster updates and more accurate ITR for the current @@ -1267,10 +1255,6 @@ void e1000e_free_rx_resources(struct e1000_adapter *adapter) * while increasing bulk throughput. * this functionality is controlled by the InterruptThrottleRate module * parameter (see e1000_param.c) - * @adapter: pointer to adapter - * @itr_setting: current adapter->itr - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval **/ static unsigned int e1000_update_itr(struct e1000_adapter *adapter, u16 itr_setting, int packets, @@ -1383,6 +1367,7 @@ set_itr_now: /** * e1000_clean - NAPI Rx polling callback * @adapter: board private structure + * @budget: amount of packets driver is allowed to process this poll **/ static int e1000_clean(struct napi_struct *napi, int budget) { @@ -1561,9 +1546,6 @@ static void e1000_init_manageability(struct e1000_adapter *adapter) manc = er32(MANC); - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - /* enable receiving management packets to the host. this will probably * generate destination unreachable messages from the host OS, but * the packets will be handled on SMBUS */ @@ -1690,6 +1672,9 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) else rctl |= E1000_RCTL_LPE; + /* Enable hardware CRC frame stripping */ + rctl |= E1000_RCTL_SECRC; + /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -1755,9 +1740,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) /* Enable Packet split descriptors */ rctl |= E1000_RCTL_DTYP_PS; - - /* Enable hardware CRC frame stripping */ - rctl |= E1000_RCTL_SECRC; psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; @@ -2008,7 +1990,7 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter) u16 mii_reg; /* WoL is enabled */ - if (!adapter->wol) + if (adapter->wol) return; /* non-copper PHY? */ @@ -2020,7 +2002,7 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter) e1000_check_reset_block(hw)) return; - /* managebility (AMT) is enabled */ + /* manageability (AMT) is enabled */ if (er32(MANC) & E1000_MANC_SMBUS_EN) return; @@ -2140,8 +2122,6 @@ void e1000e_reset(struct e1000_adapter *adapter) phy_data &= ~IGP02E1000_PM_SPD; e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); } - - e1000_release_manageability(adapter); } int e1000e_up(struct e1000_adapter *adapter) @@ -3487,8 +3467,6 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - e1000_release_manageability(adapter); - /* make sure adapter isn't asleep if manageability is enabled */ if (adapter->flags & FLAG_MNG_PT_ENABLED) { pci_enable_wake(pdev, PCI_D3hot, 1); @@ -3512,7 +3490,6 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) static void e1000e_disable_l1aspm(struct pci_dev *pdev) { int pos; - u32 cap; u16 val; /* @@ -3527,7 +3504,6 @@ static void e1000e_disable_l1aspm(struct pci_dev *pdev) * active. */ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); - pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &cap); pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); if (val & 0x2) { dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); @@ -4054,8 +4030,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev) flush_scheduled_work(); - e1000_release_manageability(adapter); - /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ e1000_release_hw_control(adapter); diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index fc6fee112f1..dab3c468a76 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -121,7 +121,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) * @offset: register offset to be read * @data: pointer to the read data * - * Reads the MDI control regsiter in the PHY at offset and stores the + * Reads the MDI control register in the PHY at offset and stores the * information read to data. **/ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) @@ -1172,7 +1172,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) } /** - * e1000e_check_downshift - Checks whether a downshift in speed occured + * e1000e_check_downshift - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 @@ -1388,8 +1388,8 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which reperesent the - * cobination of course and fine gain value, the value can be put + * cable. By reading the AGC registers, which represent the + * combination of course and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ @@ -1619,7 +1619,7 @@ s32 e1000e_phy_sw_reset(struct e1000_hw *hw) * Verify the reset block is not blocking us from resetting. Acquire * semaphore (if necessary) and read/set/write the device control reset * bit in the PHY. Wait the appropriate delay time for the device to - * reset and relase the semaphore (if necessary). + * reset and release the semaphore (if necessary). **/ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) { diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 88fb53eba71..7c4ead35cfa 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0083" +#define DRV_VERSION "EHEA_0087" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -386,6 +386,13 @@ struct ehea_port_res { #define EHEA_MAX_PORTS 16 + +#define EHEA_NUM_PORTRES_FW_HANDLES 6 /* QP handle, SendCQ handle, + RecvCQ handle, EQ handle, + SendMR handle, RecvMR handle */ +#define EHEA_NUM_PORT_FW_HANDLES 1 /* EQ handle */ +#define EHEA_NUM_ADAPTER_FW_HANDLES 2 /* MR handle, NEQ handle */ + struct ehea_adapter { u64 handle; struct of_device *ofdev; @@ -405,6 +412,31 @@ struct ehea_mc_list { u64 macaddr; }; +/* kdump support */ +struct ehea_fw_handle_entry { + u64 adh; /* Adapter Handle */ + u64 fwh; /* Firmware Handle */ +}; + +struct ehea_fw_handle_array { + struct ehea_fw_handle_entry *arr; + int num_entries; + struct semaphore lock; +}; + +struct ehea_bcmc_reg_entry { + u64 adh; /* Adapter Handle */ + u32 port_id; /* Logical Port Id */ + u8 reg_type; /* Registration Type */ + u64 macaddr; +}; + +struct ehea_bcmc_reg_array { + struct ehea_bcmc_reg_entry *arr; + int num_entries; + struct semaphore lock; +}; + #define EHEA_PORT_UP 1 #define EHEA_PORT_DOWN 0 #define EHEA_PHY_LINK_UP 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index c051c7e09b9..21af674b764 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -35,6 +35,7 @@ #include <linux/if_ether.h> #include <linux/notifier.h> #include <linux/reboot.h> +#include <asm/kexec.h> #include <net/ip.h> @@ -98,8 +99,10 @@ static int port_name_cnt; static LIST_HEAD(adapter_list); u64 ehea_driver_flags; struct work_struct ehea_rereg_mr_task; - struct semaphore dlpar_mem_lock; +struct ehea_fw_handle_array ehea_fw_handles; +struct ehea_bcmc_reg_array ehea_bcmc_regs; + static int __devinit ehea_probe_adapter(struct of_device *dev, const struct of_device_id *id); @@ -132,6 +135,160 @@ void ehea_dump(void *adr, int len, char *msg) } } +static void ehea_update_firmware_handles(void) +{ + struct ehea_fw_handle_entry *arr = NULL; + struct ehea_adapter *adapter; + int num_adapters = 0; + int num_ports = 0; + int num_portres = 0; + int i = 0; + int num_fw_handles, k, l; + + /* Determine number of handles */ + list_for_each_entry(adapter, &adapter_list, list) { + num_adapters++; + + for (k = 0; k < EHEA_MAX_PORTS; k++) { + struct ehea_port *port = adapter->port[k]; + + if (!port || (port->state != EHEA_PORT_UP)) + continue; + + num_ports++; + num_portres += port->num_def_qps + port->num_add_tx_qps; + } + } + + num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES + + num_ports * EHEA_NUM_PORT_FW_HANDLES + + num_portres * EHEA_NUM_PORTRES_FW_HANDLES; + + if (num_fw_handles) { + arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL); + if (!arr) + return; /* Keep the existing array */ + } else + goto out_update; + + list_for_each_entry(adapter, &adapter_list, list) { + for (k = 0; k < EHEA_MAX_PORTS; k++) { + struct ehea_port *port = adapter->port[k]; + + if (!port || (port->state != EHEA_PORT_UP)) + continue; + + for (l = 0; + l < port->num_def_qps + port->num_add_tx_qps; + l++) { + struct ehea_port_res *pr = &port->port_res[l]; + + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->qp->fw_handle; + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->send_cq->fw_handle; + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->recv_cq->fw_handle; + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->eq->fw_handle; + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->send_mr.handle; + arr[i].adh = adapter->handle; + arr[i++].fwh = pr->recv_mr.handle; + } + arr[i].adh = adapter->handle; + arr[i++].fwh = port->qp_eq->fw_handle; + } + + arr[i].adh = adapter->handle; + arr[i++].fwh = adapter->neq->fw_handle; + + if (adapter->mr.handle) { + arr[i].adh = adapter->handle; + arr[i++].fwh = adapter->mr.handle; + } + } + +out_update: + kfree(ehea_fw_handles.arr); + ehea_fw_handles.arr = arr; + ehea_fw_handles.num_entries = i; +} + +static void ehea_update_bcmc_registrations(void) +{ + struct ehea_bcmc_reg_entry *arr = NULL; + struct ehea_adapter *adapter; + struct ehea_mc_list *mc_entry; + int num_registrations = 0; + int i = 0; + int k; + + /* Determine number of registrations */ + list_for_each_entry(adapter, &adapter_list, list) + for (k = 0; k < EHEA_MAX_PORTS; k++) { + struct ehea_port *port = adapter->port[k]; + + if (!port || (port->state != EHEA_PORT_UP)) + continue; + + num_registrations += 2; /* Broadcast registrations */ + + list_for_each_entry(mc_entry, &port->mc_list->list,list) + num_registrations += 2; + } + + if (num_registrations) { + arr = kzalloc(num_registrations * sizeof(*arr), GFP_KERNEL); + if (!arr) + return; /* Keep the existing array */ + } else + goto out_update; + + list_for_each_entry(adapter, &adapter_list, list) { + for (k = 0; k < EHEA_MAX_PORTS; k++) { + struct ehea_port *port = adapter->port[k]; + + if (!port || (port->state != EHEA_PORT_UP)) + continue; + + arr[i].adh = adapter->handle; + arr[i].port_id = port->logical_port_id; + arr[i].reg_type = EHEA_BCMC_BROADCAST | + EHEA_BCMC_UNTAGGED; + arr[i++].macaddr = port->mac_addr; + + arr[i].adh = adapter->handle; + arr[i].port_id = port->logical_port_id; + arr[i].reg_type = EHEA_BCMC_BROADCAST | + EHEA_BCMC_VLANID_ALL; + arr[i++].macaddr = port->mac_addr; + + list_for_each_entry(mc_entry, + &port->mc_list->list, list) { + arr[i].adh = adapter->handle; + arr[i].port_id = port->logical_port_id; + arr[i].reg_type = EHEA_BCMC_SCOPE_ALL | + EHEA_BCMC_MULTICAST | + EHEA_BCMC_UNTAGGED; + arr[i++].macaddr = mc_entry->macaddr; + + arr[i].adh = adapter->handle; + arr[i].port_id = port->logical_port_id; + arr[i].reg_type = EHEA_BCMC_SCOPE_ALL | + EHEA_BCMC_MULTICAST | + EHEA_BCMC_VLANID_ALL; + arr[i++].macaddr = mc_entry->macaddr; + } + } + } + +out_update: + kfree(ehea_bcmc_regs.arr); + ehea_bcmc_regs.arr = arr; + ehea_bcmc_regs.num_entries = i; +} + static struct net_device_stats *ehea_get_stats(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); @@ -1601,19 +1758,25 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); + down(&ehea_bcmc_regs.lock); + /* Deregister old MAC in pHYP */ ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); if (ret) - goto out_free; + goto out_upregs; port->mac_addr = cb0->port_mac_addr << 16; /* Register new MAC in pHYP */ ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); if (ret) - goto out_free; + goto out_upregs; ret = 0; + +out_upregs: + ehea_update_bcmc_registrations(); + up(&ehea_bcmc_regs.lock); out_free: kfree(cb0); out: @@ -1775,9 +1938,11 @@ static void ehea_set_multicast_list(struct net_device *dev) } ehea_promiscuous(dev, 0); + down(&ehea_bcmc_regs.lock); + if (dev->flags & IFF_ALLMULTI) { ehea_allmulti(dev, 1); - return; + goto out; } ehea_allmulti(dev, 0); @@ -1803,6 +1968,8 @@ static void ehea_set_multicast_list(struct net_device *dev) } out: + ehea_update_bcmc_registrations(); + up(&ehea_bcmc_regs.lock); return; } @@ -2285,6 +2452,8 @@ static int ehea_up(struct net_device *dev) if (port->state == EHEA_PORT_UP) return 0; + down(&ehea_fw_handles.lock); + ret = ehea_port_res_setup(port, port->num_def_qps, port->num_add_tx_qps); if (ret) { @@ -2321,8 +2490,17 @@ static int ehea_up(struct net_device *dev) } } - ret = 0; + down(&ehea_bcmc_regs.lock); + + ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); + if (ret) { + ret = -EIO; + goto out_free_irqs; + } + port->state = EHEA_PORT_UP; + + ret = 0; goto out; out_free_irqs: @@ -2334,6 +2512,12 @@ out: if (ret) ehea_info("Failed starting %s. ret=%i", dev->name, ret); + ehea_update_bcmc_registrations(); + up(&ehea_bcmc_regs.lock); + + ehea_update_firmware_handles(); + up(&ehea_fw_handles.lock); + return ret; } @@ -2382,16 +2566,27 @@ static int ehea_down(struct net_device *dev) if (port->state == EHEA_PORT_DOWN) return 0; + down(&ehea_bcmc_regs.lock); ehea_drop_multicast_list(dev); + ehea_broadcast_reg_helper(port, H_DEREG_BCMC); + ehea_free_interrupts(dev); + down(&ehea_fw_handles.lock); + port->state = EHEA_PORT_DOWN; + ehea_update_bcmc_registrations(); + up(&ehea_bcmc_regs.lock); + ret = ehea_clean_all_portres(port); if (ret) ehea_info("Failed freeing resources for %s. ret=%i", dev->name, ret); + ehea_update_firmware_handles(); + up(&ehea_fw_handles.lock); + return ret; } @@ -2920,19 +3115,12 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; INIT_WORK(&port->reset_task, ehea_reset_port); - - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); - if (ret) { - ret = -EIO; - goto out_unreg_port; - } - ehea_set_ethtool_ops(dev); ret = register_netdev(dev); if (ret) { ehea_error("register_netdev failed. ret=%d", ret); - goto out_dereg_bc; + goto out_unreg_port; } port->lro_max_aggr = lro_max_aggr; @@ -2949,9 +3137,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, return port; -out_dereg_bc: - ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - out_unreg_port: ehea_unregister_port(port); @@ -2971,7 +3156,6 @@ static void ehea_shutdown_single_port(struct ehea_port *port) { unregister_netdev(port->netdev); ehea_unregister_port(port); - ehea_broadcast_reg_helper(port, H_DEREG_BCMC); kfree(port->mc_list); free_netdev(port->netdev); port->adapter->active_ports--; @@ -3014,7 +3198,6 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) i++; }; - return 0; } @@ -3159,6 +3342,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ehea_error("Invalid ibmebus device probed"); return -EINVAL; } + down(&ehea_fw_handles.lock); adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { @@ -3239,7 +3423,10 @@ out_kill_eq: out_free_ad: kfree(adapter); + out: + ehea_update_firmware_handles(); + up(&ehea_fw_handles.lock); return ret; } @@ -3258,18 +3445,41 @@ static int __devexit ehea_remove(struct of_device *dev) flush_scheduled_work(); + down(&ehea_fw_handles.lock); + ibmebus_free_irq(adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); ehea_destroy_eq(adapter->neq); ehea_remove_adapter_mr(adapter); list_del(&adapter->list); - kfree(adapter); + ehea_update_firmware_handles(); + up(&ehea_fw_handles.lock); + return 0; } +void ehea_crash_handler(void) +{ + int i; + + if (ehea_fw_handles.arr) + for (i = 0; i < ehea_fw_handles.num_entries; i++) + ehea_h_free_resource(ehea_fw_handles.arr[i].adh, + ehea_fw_handles.arr[i].fwh, + FORCE_FREE); + + if (ehea_bcmc_regs.arr) + for (i = 0; i < ehea_bcmc_regs.num_entries; i++) + ehea_h_reg_dereg_bcmc(ehea_bcmc_regs.arr[i].adh, + ehea_bcmc_regs.arr[i].port_id, + ehea_bcmc_regs.arr[i].reg_type, + ehea_bcmc_regs.arr[i].macaddr, + 0, H_DEREG_BCMC); +} + static int ehea_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) { @@ -3330,7 +3540,12 @@ int __init ehea_module_init(void) INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs); + memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles)); + memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs)); + sema_init(&dlpar_mem_lock, 1); + sema_init(&ehea_fw_handles.lock, 1); + sema_init(&ehea_bcmc_regs.lock, 1); ret = check_module_parm(); if (ret) @@ -3340,12 +3555,18 @@ int __init ehea_module_init(void) if (ret) goto out; - register_reboot_notifier(&ehea_reboot_nb); + ret = register_reboot_notifier(&ehea_reboot_nb); + if (ret) + ehea_info("failed registering reboot notifier"); + + ret = crash_shutdown_register(&ehea_crash_handler); + if (ret) + ehea_info("failed registering crash handler"); ret = ibmebus_register_driver(&ehea_driver); if (ret) { ehea_error("failed registering eHEA device driver on ebus"); - goto out; + goto out2; } ret = driver_create_file(&ehea_driver.driver, @@ -3353,21 +3574,33 @@ int __init ehea_module_init(void) if (ret) { ehea_error("failed to register capabilities attribute, ret=%d", ret); - unregister_reboot_notifier(&ehea_reboot_nb); - ibmebus_unregister_driver(&ehea_driver); - goto out; + goto out3; } + return ret; + +out3: + ibmebus_unregister_driver(&ehea_driver); +out2: + unregister_reboot_notifier(&ehea_reboot_nb); + crash_shutdown_unregister(&ehea_crash_handler); out: return ret; } static void __exit ehea_module_exit(void) { + int ret; + flush_scheduled_work(); driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); unregister_reboot_notifier(&ehea_reboot_nb); + ret = crash_shutdown_unregister(&ehea_crash_handler); + if (ret) + ehea_info("failed unregistering crash handler"); + kfree(ehea_fw_handles.arr); + kfree(ehea_bcmc_regs.arr); ehea_destroy_busmap(); } diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 42d94edeee2..af869cf9ae7 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -946,16 +946,11 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct fs_enet_private *fep = netdev_priv(dev); struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data; - unsigned long flags; - int rc; if (!netif_running(dev)) return -EINVAL; - spin_lock_irqsave(&fep->lock, flags); - rc = phy_mii_ioctl(fep->phydev, mii, cmd); - spin_unlock_irqrestore(&fep->lock, flags); - return rc; + return phy_mii_ioctl(fep->phydev, mii, cmd); } extern int fs_mii_connect(struct net_device *dev); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0431e9ed0fa..718cf77e345 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -130,8 +130,8 @@ static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); static void gfar_configure_serdes(struct net_device *dev); -extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); -extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); +extern int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value); +extern int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct napi_struct *napi, int budget); #endif @@ -605,7 +605,7 @@ void stop_gfar(struct net_device *dev) free_skb_resources(priv); - dma_free_coherent(NULL, + dma_free_coherent(&dev->dev, sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, @@ -626,7 +626,7 @@ static void free_skb_resources(struct gfar_private *priv) for (i = 0; i < priv->tx_ring_size; i++) { if (priv->tx_skbuff[i]) { - dma_unmap_single(NULL, txbdp->bufPtr, + dma_unmap_single(&priv->dev->dev, txbdp->bufPtr, txbdp->length, DMA_TO_DEVICE); dev_kfree_skb_any(priv->tx_skbuff[i]); @@ -643,7 +643,7 @@ static void free_skb_resources(struct gfar_private *priv) if(priv->rx_skbuff != NULL) { for (i = 0; i < priv->rx_ring_size; i++) { if (priv->rx_skbuff[i]) { - dma_unmap_single(NULL, rxbdp->bufPtr, + dma_unmap_single(&priv->dev->dev, rxbdp->bufPtr, priv->rx_buffer_size, DMA_FROM_DEVICE); @@ -708,7 +708,7 @@ int startup_gfar(struct net_device *dev) gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - vaddr = (unsigned long) dma_alloc_coherent(NULL, + vaddr = (unsigned long) dma_alloc_coherent(&dev->dev, sizeof (struct txbd8) * priv->tx_ring_size + sizeof (struct rxbd8) * priv->rx_ring_size, &addr, GFP_KERNEL); @@ -919,7 +919,7 @@ err_irq_fail: rx_skb_fail: free_skb_resources(priv); tx_skb_fail: - dma_free_coherent(NULL, + dma_free_coherent(&dev->dev, sizeof(struct txbd8)*priv->tx_ring_size + sizeof(struct rxbd8)*priv->rx_ring_size, priv->tx_bd_base, @@ -1053,7 +1053,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Set buffer length and pointer */ txbdp->length = skb->len; - txbdp->bufPtr = dma_map_single(NULL, skb->data, + txbdp->bufPtr = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE); /* Save the skb pointer so we can free it later */ @@ -1332,7 +1332,7 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) */ skb_reserve(skb, alignamount); - bdp->bufPtr = dma_map_single(NULL, skb->data, + bdp->bufPtr = dma_map_single(&dev->dev, skb->data, priv->rx_buffer_size, DMA_FROM_DEVICE); bdp->length = 0; diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 6a647d95e6e..24327629bf0 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -51,7 +51,7 @@ * the local mdio pins, which may not be the same as system mdio bus, used for * controlling the external PHYs, for example. */ -int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, +int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value) { /* Set the PHY address and the register address we want to write */ @@ -77,7 +77,7 @@ int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, * and are always tied to the local mdio pins, which may not be the * same as system mdio bus, used for controlling the external PHYs, for eg. */ -int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) +int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum) { u16 value; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index cfcd15af501..30c9b3b0d13 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -289,7 +289,6 @@ static void ax_bump(struct mkiss *ax) *ax->rbuff &= ~0x20; } } - spin_unlock_bh(&ax->buflock); count = ax->rcount; @@ -297,17 +296,17 @@ static void ax_bump(struct mkiss *ax) printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name); ax->stats.rx_dropped++; + spin_unlock_bh(&ax->buflock); return; } - spin_lock_bh(&ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); - spin_unlock_bh(&ax->buflock); skb->protocol = ax25_type_trans(skb, ax->dev); netif_rx(skb); ax->dev->last_rx = jiffies; ax->stats.rx_packets++; ax->stats.rx_bytes += count; + spin_unlock_bh(&ax->buflock); } static void kiss_unesc(struct mkiss *ax, unsigned char s) diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 9bc1132fa78..5757788227b 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c @@ -302,7 +302,6 @@ static int __devexit rgmii_remove(struct of_device *ofdev) static struct of_device_id rgmii_match[] = { { - .type = "rgmii-interface", .compatible = "ibm,rgmii", }, { diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index f69721e4eaa..0447f9bcd27 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -43,7 +43,7 @@ struct igb_stats { int stat_offset; }; -#define IGB_STAT(m) sizeof(((struct igb_adapter *)0)->m), \ +#define IGB_STAT(m) FIELD_SIZEOF(struct igb_adapter, m), \ offsetof(struct igb_adapter, m) static const struct igb_stats igb_gstrings_stats[] = { { "rx_packets", IGB_STAT(stats.gprc) }, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d4eb8e2d872..6a1f2309209 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -439,7 +439,7 @@ static int igb_request_irq(struct igb_adapter *adapter) err = igb_request_msix(adapter); if (!err) { /* enable IAM, auto-mask, - * DO NOT USE EIAME or IAME in legacy mode */ + * DO NOT USE EIAM or IAM in legacy mode */ wr32(E1000_IAM, IMS_ENABLE_MASK); goto request_done; } @@ -465,14 +465,9 @@ static int igb_request_irq(struct igb_adapter *adapter) err = request_irq(adapter->pdev->irq, &igb_intr, IRQF_SHARED, netdev->name, netdev); - if (err) { + if (err) dev_err(&adapter->pdev->dev, "Error %d getting interrupt\n", err); - goto request_done; - } - - /* enable IAM, auto-mask */ - wr32(E1000_IAM, IMS_ENABLE_MASK); request_done: return err; @@ -606,9 +601,6 @@ static void igb_init_manageability(struct igb_adapter *adapter) u32 manc2h = rd32(E1000_MANC2H); u32 manc = rd32(E1000_MANC); - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - /* enable receiving management packets to the host */ /* this will probably generate destination unreachable messages * from the host OS, but the packets will be handled on SMBUS */ @@ -623,25 +615,6 @@ static void igb_init_manageability(struct igb_adapter *adapter) } } -static void igb_release_manageability(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = rd32(E1000_MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - manc &= ~E1000_MANC_EN_MNG2HOST; - - /* don't explicitly have to mess with MANC2H since - * MANC has an enable disable that gates MANC2H */ - - /* XXX stop the hardware watchdog ? */ - wr32(E1000_MANC, manc); - } -} - /** * igb_configure - configure the hardware for RX and TX * @adapter: private board structure @@ -843,8 +816,8 @@ void igb_reset(struct igb_adapter *adapter) wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); igb_reset_adaptive(&adapter->hw); - adapter->hw.phy.ops.get_phy_info(&adapter->hw); - igb_release_manageability(adapter); + if (adapter->hw.phy.ops.get_phy_info) + adapter->hw.phy.ops.get_phy_info(&adapter->hw); } /** @@ -1178,9 +1151,6 @@ static void __devexit igb_remove(struct pci_dev *pdev) flush_scheduled_work(); - - igb_release_manageability(adapter); - /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ igb_release_hw_control(adapter); @@ -2083,7 +2053,8 @@ static void igb_set_multi(struct net_device *netdev) static void igb_update_phy_info(unsigned long data) { struct igb_adapter *adapter = (struct igb_adapter *) data; - adapter->hw.phy.ops.get_phy_info(&adapter->hw); + if (adapter->hw.phy.ops.get_phy_info) + adapter->hw.phy.ops.get_phy_info(&adapter->hw); } /** @@ -3955,8 +3926,6 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - igb_release_manageability(adapter); - /* make sure adapter isn't asleep if manageability is enabled */ if (adapter->en_mng_pt) { pci_enable_wake(pdev, PCI_D3hot, 1); diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index a267dd86252..75f3a68ee35 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -49,7 +49,7 @@ struct ixgb_stats { int stat_offset; }; -#define IXGB_STAT(m) sizeof(((struct ixgb_adapter *)0)->m), \ +#define IXGB_STAT(m) FIELD_SIZEOF(struct ixgb_adapter, m), \ offsetof(struct ixgb_adapter, m) static struct ixgb_stats ixgb_gstrings_stats[] = { {"rx_packets", IXGB_STAT(net_stats.rx_packets)}, @@ -67,6 +67,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = { {"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)}, {"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)}, {"rx_frame_errors", IXGB_STAT(net_stats.rx_frame_errors)}, + {"rx_no_buffer_count", IXGB_STAT(stats.rnbc)}, {"rx_fifo_errors", IXGB_STAT(net_stats.rx_fifo_errors)}, {"rx_missed_errors", IXGB_STAT(net_stats.rx_missed_errors)}, {"tx_aborted_errors", IXGB_STAT(net_stats.tx_aborted_errors)}, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ead49e54f31..23d0a4afe0e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -220,7 +220,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, tx_ring->stats.bytes += tx_buffer_info->length; if (cleaned) { struct sk_buff *skb = tx_buffer_info->skb; -#ifdef NETIF_F_TSO unsigned int segs, bytecount; segs = skb_shinfo(skb)->gso_segs ?: 1; /* multiply data chunks by size of headers */ @@ -228,10 +227,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, skb->len; total_tx_packets += segs; total_tx_bytes += bytecount; -#else - total_tx_packets++; - total_tx_bytes += skb->len; -#endif } ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); @@ -1942,6 +1937,10 @@ static int ixgbe_open(struct net_device *netdev) int err; u32 num_rx_queues = adapter->num_rx_queues; + /* disallow open during test */ + if (test_bit(__IXGBE_TESTING, &adapter->state)) + return -EBUSY; + try_intr_reinit: /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); @@ -2278,11 +2277,29 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, IXGBE_ADVTXD_DTYP_CTXT); if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb->protocol == htons(ETH_P_IP)) + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; + + case __constant_htons(ETH_P_IPV6): + /* XXX what about other V6 headers?? */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; - if (skb->sk->sk_protocol == IPPROTO_TCP) - type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + default: + if (unlikely(net_ratelimit())) { + DPRINTK(PROBE, WARNING, + "partial checksum but proto=%x!\n", + skb->protocol); + } + break; + } } context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl); @@ -2778,6 +2795,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->mac.type, hw->phy.type, (part_num >> 8), (part_num & 0xff)); + if (link_width <= IXGBE_PCI_LINK_WIDTH_4) { + dev_warn(&pdev->dev, "PCI-Express bandwidth available for " + "this card is not sufficient for optimal " + "performance.\n"); + dev_warn(&pdev->dev, "For optimal performance a x8 " + "PCI-Express slot is required.\n"); + } + /* reset the hardware with the new settings */ ixgbe_start_hw(hw); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 81bf005ff28..1d210ed4613 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -148,7 +148,7 @@ static void macb_handle_link_change(struct net_device *dev) if (phydev->duplex) reg |= MACB_BIT(FD); - if (phydev->speed) + if (phydev->speed == SPEED_100) reg |= MACB_BIT(SPD); macb_writel(bp, NCFGR, reg); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2fe14b0c5c6..d11ba61baa4 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -33,8 +33,8 @@ #define DRV_MODULE_NAME "niu" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.6" -#define DRV_MODULE_RELDATE "January 5, 2008" +#define DRV_MODULE_VERSION "0.7" +#define DRV_MODULE_RELDATE "February 18, 2008" static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -1616,12 +1616,13 @@ static int niu_enable_alt_mac(struct niu *np, int index, int on) if (index >= niu_num_alt_addr(np)) return -EINVAL; - if (np->flags & NIU_FLAGS_XMAC) + if (np->flags & NIU_FLAGS_XMAC) { reg = XMAC_ADDR_CMPEN; - else + mask = 1 << index; + } else { reg = BMAC_ADDR_CMPEN; - - mask = 1 << index; + mask = 1 << (index + 1); + } val = nr64_mac(reg); if (on) @@ -5147,7 +5148,12 @@ static void niu_set_rx_mode(struct net_device *dev) index++; } } else { - for (i = 0; i < niu_num_alt_addr(np); i++) { + int alt_start; + if (np->flags & NIU_FLAGS_XMAC) + alt_start = 0; + else + alt_start = 1; + for (i = alt_start; i < niu_num_alt_addr(np); i++) { err = niu_enable_alt_mac(np, i, 0); if (err) printk(KERN_WARNING PFX "%s: Error %d " diff --git a/drivers/net/niu.h b/drivers/net/niu.h index 0e8626adc57..59dc05fcd37 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -499,7 +499,7 @@ #define BMAC_ADDR2 0x00110UL #define BMAC_ADDR2_ADDR2 0x000000000000ffffULL -#define BMAC_NUM_ALT_ADDR 7 +#define BMAC_NUM_ALT_ADDR 6 #define BMAC_ALT_ADDR0(NUM) (0x00118UL + (NUM)*0x18UL) #define BMAC_ALT_ADDR0_ADDR0 0x000000000000ffffULL diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 6323988dfa1..fd8158a86f6 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -590,6 +590,13 @@ static int pcnet_config(struct pcmcia_device *link) dev->if_port = 0; } + if ((link->conf.ConfigBase == 0x03c0) + && (link->manf_id == 0x149) && (link->card_id = 0xc1ab)) { + printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); + printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); + goto failed; + } + local_hw_info = get_hwinfo(link); if (local_hw_info == NULL) local_hw_info = get_prom(link); @@ -1567,12 +1574,11 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145), PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230), PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530), -/* PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), conflict with axnet_cs */ + PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041), PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452), -/* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), conflict with axnet_cs */ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307), PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index f18eca9831e..250eb1954c3 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -559,8 +559,16 @@ static int mhz_setup(struct pcmcia_device *link) /* Read the station address from the CIS. It is stored as the last (fourth) string in the Version 1 Version/ID tuple. */ - if (link->prod_id[3]) { - station_addr = link->prod_id[3]; + tuple->DesiredTuple = CISTPL_VERS_1; + if (first_tuple(link, tuple, parse) != CS_SUCCESS) { + rc = -1; + goto free_cfg_mem; + } + /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ + if (next_tuple(link, tuple, parse) != CS_SUCCESS) + first_tuple(link, tuple, parse); + if (parse->version_1.ns > 3) { + station_addr = parse->version_1.str + parse->version_1.ofs[3]; if (cvt_ascii_address(dev, station_addr) == 0) { rc = 0; goto free_cfg_mem; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6e9f619c491..963630c65ca 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -49,13 +49,13 @@ int mdiobus_register(struct mii_bus *bus) int i; int err = 0; - mutex_init(&bus->mdio_lock); - if (NULL == bus || NULL == bus->name || NULL == bus->read || NULL == bus->write) return -EINVAL; + mutex_init(&bus->mdio_lock); + if (bus->reset) bus->reset(bus); diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 750d2a99cb4..daf5abab953 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2690,6 +2690,7 @@ int gelic_wl_driver_probe(struct gelic_card *card) return -ENOMEM; /* setup net_device structure */ + SET_NETDEV_DEV(netdev, &card->dev->core); gelic_wl_setup_netdev_ops(netdev); /* setup some of net_device and register it */ diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 202fdf35662..20745fd4e97 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1633,13 +1633,18 @@ static inline void sis190_init_rxfilter(struct net_device *dev) static int __devinit sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev) { - u8 from; + int rc; + + rc = sis190_get_mac_addr_from_eeprom(pdev, dev); + if (rc < 0) { + u8 reg; - pci_read_config_byte(pdev, 0x73, &from); + pci_read_config_byte(pdev, 0x73, ®); - return (from & 0x00000001) ? - sis190_get_mac_addr_from_apc(pdev, dev) : - sis190_get_mac_addr_from_eeprom(pdev, dev); + if (reg & 0x00000001) + rc = sis190_get_mac_addr_from_apc(pdev, dev); + } + return rc; } static void sis190_set_speed_auto(struct net_device *dev) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 9a6295909e4..54c662690f6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -572,8 +572,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) default: /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; + /* turn off the Rx LED (LED_RX) */ - ledover &= ~PHY_M_LED_MO_RX; + ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); } if (hw->chip_id == CHIP_ID_YUKON_EC_U && @@ -602,7 +603,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { /* turn on 100 Mbps LED (LED_LINK100) */ - ledover |= PHY_M_LED_MO_100; + ledover |= PHY_M_LED_MO_100(MO_LED_ON); } if (ledover) @@ -3322,82 +3323,80 @@ static void sky2_set_multicast(struct net_device *dev) /* Can have one global because blinking is controlled by * ethtool and that is always under RTNL mutex */ -static void sky2_led(struct sky2_hw *hw, unsigned port, int on) +static void sky2_led(struct sky2_port *sky2, enum led_mode mode) { - u16 pg; + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; - switch (hw->chip_id) { - case CHIP_ID_YUKON_XL: + spin_lock_bh(&sky2->phy_lock); + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX || + hw->chip_id == CHIP_ID_YUKON_SUPR) { + u16 pg; pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, - on ? (PHY_M_LEDC_LOS_CTRL(1) | - PHY_M_LEDC_INIT_CTRL(7) | - PHY_M_LEDC_STA1_CTRL(7) | - PHY_M_LEDC_STA0_CTRL(7)) - : 0); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - break; + switch (mode) { + case MO_LED_OFF: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(8) | + PHY_M_LEDC_INIT_CTRL(8) | + PHY_M_LEDC_STA1_CTRL(8) | + PHY_M_LEDC_STA0_CTRL(8)); + break; + case MO_LED_ON: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(9) | + PHY_M_LEDC_INIT_CTRL(9) | + PHY_M_LEDC_STA1_CTRL(9) | + PHY_M_LEDC_STA0_CTRL(9)); + break; + case MO_LED_BLINK: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(0xa) | + PHY_M_LEDC_INIT_CTRL(0xa) | + PHY_M_LEDC_STA1_CTRL(0xa) | + PHY_M_LEDC_STA0_CTRL(0xa)); + break; + case MO_LED_NORM: + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, + PHY_M_LEDC_LOS_CTRL(1) | + PHY_M_LEDC_INIT_CTRL(8) | + PHY_M_LEDC_STA1_CTRL(7) | + PHY_M_LEDC_STA0_CTRL(7)); + } - default: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); + } else gm_phy_write(hw, port, PHY_MARV_LED_OVER, - on ? PHY_M_LED_ALL : 0); - } + PHY_M_LED_MO_DUP(mode) | + PHY_M_LED_MO_10(mode) | + PHY_M_LED_MO_100(mode) | + PHY_M_LED_MO_1000(mode) | + PHY_M_LED_MO_RX(mode) | + PHY_M_LED_MO_TX(mode)); + + spin_unlock_bh(&sky2->phy_lock); } /* blink LED's for finding board */ static int sky2_phys_id(struct net_device *dev, u32 data) { struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - unsigned port = sky2->port; - u16 ledctrl, ledover = 0; - long ms; - int interrupted; - int onoff = 1; + unsigned int i; - if (!data || data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ)) - ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT); - else - ms = data * 1000; - - /* save initial values */ - spin_lock_bh(&sky2->phy_lock); - if (hw->chip_id == CHIP_ID_YUKON_XL) { - u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); - ledctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - } else { - ledctrl = gm_phy_read(hw, port, PHY_MARV_LED_CTRL); - ledover = gm_phy_read(hw, port, PHY_MARV_LED_OVER); - } - - interrupted = 0; - while (!interrupted && ms > 0) { - sky2_led(hw, port, onoff); - onoff = !onoff; - - spin_unlock_bh(&sky2->phy_lock); - interrupted = msleep_interruptible(250); - spin_lock_bh(&sky2->phy_lock); - - ms -= 250; - } + if (data == 0) + data = UINT_MAX; - /* resume regularly scheduled programming */ - if (hw->chip_id == CHIP_ID_YUKON_XL) { - u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ledctrl); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); + for (i = 0; i < data; i++) { + sky2_led(sky2, MO_LED_ON); + if (msleep_interruptible(500)) + break; + sky2_led(sky2, MO_LED_OFF); + if (msleep_interruptible(500)) + break; } - spin_unlock_bh(&sky2->phy_lock); + sky2_led(sky2, MO_LED_NORM); return 0; } diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 5ab5c1c7c5a..7bb3ba9bcbd 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1318,18 +1318,21 @@ enum { BLINK_670MS = 4,/* 670 ms */ }; -/**** PHY_MARV_LED_OVER 16 bit r/w LED control */ -enum { - PHY_M_LED_MO_DUP = 3<<10,/* Bit 11..10: Duplex */ - PHY_M_LED_MO_10 = 3<<8, /* Bit 9.. 8: Link 10 */ - PHY_M_LED_MO_100 = 3<<6, /* Bit 7.. 6: Link 100 */ - PHY_M_LED_MO_1000 = 3<<4, /* Bit 5.. 4: Link 1000 */ - PHY_M_LED_MO_RX = 3<<2, /* Bit 3.. 2: Rx */ - PHY_M_LED_MO_TX = 3<<0, /* Bit 1.. 0: Tx */ - - PHY_M_LED_ALL = PHY_M_LED_MO_DUP | PHY_M_LED_MO_10 - | PHY_M_LED_MO_100 | PHY_M_LED_MO_1000 - | PHY_M_LED_MO_RX, +/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ +#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ + +#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ +#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ +#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ +#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ +#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ +#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ + +enum led_mode { + MO_LED_NORM = 0, + MO_LED_BLINK = 1, + MO_LED_OFF = 2, + MO_LED_ON = 3, }; /***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index db606b60388..26ffb67f1da 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8781,7 +8781,7 @@ static int tg3_phys_id(struct net_device *dev, u32 data) return -EAGAIN; if (data == 0) - data = 2; + data = UINT_MAX / 2; for (i = 0; i < (data * 2); i++) { if ((i % 2) == 0) diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 3af5b92b48c..0166407d706 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1400,7 +1400,7 @@ static void TLan_SetMulticastList( struct net_device *dev ) * **************************************************************/ -u32 TLan_HandleInvalid( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleInvalid( struct net_device *dev, u16 host_int ) { /* printk( "TLAN: Invalid interrupt on %s.\n", dev->name ); */ return 0; @@ -1432,7 +1432,7 @@ u32 TLan_HandleInvalid( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) { TLanPrivateInfo *priv = netdev_priv(dev); int eoc = 0; @@ -1518,7 +1518,7 @@ u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int ) { TLan_ReadAndClearStats( dev, TLAN_RECORD ); @@ -1554,7 +1554,7 @@ u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int ) { TLanPrivateInfo *priv = netdev_priv(dev); u32 ack = 0; @@ -1689,7 +1689,7 @@ u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleDummy( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleDummy( struct net_device *dev, u16 host_int ) { printk( "TLAN: Test interrupt on %s.\n", dev->name ); return 1; @@ -1719,7 +1719,7 @@ u32 TLan_HandleDummy( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int ) { TLanPrivateInfo *priv = netdev_priv(dev); TLanList *head_list; @@ -1767,7 +1767,7 @@ u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int ) { TLanPrivateInfo *priv = netdev_priv(dev); u32 ack; @@ -1842,7 +1842,7 @@ u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int ) * **************************************************************/ -u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int ) +static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int ) { TLanPrivateInfo *priv = netdev_priv(dev); dma_addr_t head_list_phys; @@ -1902,7 +1902,7 @@ u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int ) * **************************************************************/ -void TLan_Timer( unsigned long data ) +static void TLan_Timer( unsigned long data ) { struct net_device *dev = (struct net_device *) data; TLanPrivateInfo *priv = netdev_priv(dev); @@ -1983,7 +1983,7 @@ void TLan_Timer( unsigned long data ) * **************************************************************/ -void TLan_ResetLists( struct net_device *dev ) +static void TLan_ResetLists( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); int i; @@ -2043,7 +2043,7 @@ void TLan_ResetLists( struct net_device *dev ) } /* TLan_ResetLists */ -void TLan_FreeLists( struct net_device *dev ) +static void TLan_FreeLists( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); int i; @@ -2092,7 +2092,7 @@ void TLan_FreeLists( struct net_device *dev ) * **************************************************************/ -void TLan_PrintDio( u16 io_base ) +static void TLan_PrintDio( u16 io_base ) { u32 data0, data1; int i; @@ -2127,7 +2127,7 @@ void TLan_PrintDio( u16 io_base ) * **************************************************************/ -void TLan_PrintList( TLanList *list, char *type, int num) +static void TLan_PrintList( TLanList *list, char *type, int num) { int i; @@ -2163,7 +2163,7 @@ void TLan_PrintList( TLanList *list, char *type, int num) * **************************************************************/ -void TLan_ReadAndClearStats( struct net_device *dev, int record ) +static void TLan_ReadAndClearStats( struct net_device *dev, int record ) { TLanPrivateInfo *priv = netdev_priv(dev); u32 tx_good, tx_under; @@ -2238,7 +2238,7 @@ void TLan_ReadAndClearStats( struct net_device *dev, int record ) * **************************************************************/ -void +static void TLan_ResetAdapter( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); @@ -2324,7 +2324,7 @@ TLan_ResetAdapter( struct net_device *dev ) -void +static void TLan_FinishReset( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); @@ -2448,7 +2448,7 @@ TLan_FinishReset( struct net_device *dev ) * **************************************************************/ -void TLan_SetMac( struct net_device *dev, int areg, char *mac ) +static void TLan_SetMac( struct net_device *dev, int areg, char *mac ) { int i; @@ -2490,7 +2490,7 @@ void TLan_SetMac( struct net_device *dev, int areg, char *mac ) * ********************************************************************/ -void TLan_PhyPrint( struct net_device *dev ) +static void TLan_PhyPrint( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 i, data0, data1, data2, data3, phy; @@ -2539,7 +2539,7 @@ void TLan_PhyPrint( struct net_device *dev ) * ********************************************************************/ -void TLan_PhyDetect( struct net_device *dev ) +static void TLan_PhyDetect( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 control; @@ -2586,7 +2586,7 @@ void TLan_PhyDetect( struct net_device *dev ) -void TLan_PhyPowerDown( struct net_device *dev ) +static void TLan_PhyPowerDown( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 value; @@ -2611,7 +2611,7 @@ void TLan_PhyPowerDown( struct net_device *dev ) -void TLan_PhyPowerUp( struct net_device *dev ) +static void TLan_PhyPowerUp( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 value; @@ -2632,7 +2632,7 @@ void TLan_PhyPowerUp( struct net_device *dev ) -void TLan_PhyReset( struct net_device *dev ) +static void TLan_PhyReset( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 phy; @@ -2660,7 +2660,7 @@ void TLan_PhyReset( struct net_device *dev ) -void TLan_PhyStartLink( struct net_device *dev ) +static void TLan_PhyStartLink( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 ability; @@ -2747,7 +2747,7 @@ void TLan_PhyStartLink( struct net_device *dev ) -void TLan_PhyFinishAutoNeg( struct net_device *dev ) +static void TLan_PhyFinishAutoNeg( struct net_device *dev ) { TLanPrivateInfo *priv = netdev_priv(dev); u16 an_adv; @@ -2903,7 +2903,7 @@ void TLan_PhyMonitor( struct net_device *dev ) * **************************************************************/ -int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) +static int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) { u8 nack; u16 sio, tmp; @@ -2993,7 +2993,7 @@ int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) * **************************************************************/ -void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits ) +static void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits ) { u16 sio; u32 i; @@ -3035,7 +3035,7 @@ void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits ) * **************************************************************/ -void TLan_MiiSync( u16 base_port ) +static void TLan_MiiSync( u16 base_port ) { int i; u16 sio; @@ -3074,7 +3074,7 @@ void TLan_MiiSync( u16 base_port ) * **************************************************************/ -void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val ) +static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val ) { u16 sio; int minten; @@ -3144,7 +3144,7 @@ void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val ) * **************************************************************/ -void TLan_EeSendStart( u16 io_base ) +static void TLan_EeSendStart( u16 io_base ) { u16 sio; @@ -3184,7 +3184,7 @@ void TLan_EeSendStart( u16 io_base ) * **************************************************************/ -int TLan_EeSendByte( u16 io_base, u8 data, int stop ) +static int TLan_EeSendByte( u16 io_base, u8 data, int stop ) { int err; u8 place; @@ -3245,7 +3245,7 @@ int TLan_EeSendByte( u16 io_base, u8 data, int stop ) * **************************************************************/ -void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ) +static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ) { u8 place; u16 sio; @@ -3303,7 +3303,7 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ) * **************************************************************/ -int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data ) +static int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data ) { int err; TLanPrivateInfo *priv = netdev_priv(dev); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 35d15e85007..6f33f84d37b 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -36,6 +36,7 @@ #include <linux/net.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/ethtool.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/spinlock.h> @@ -297,18 +298,11 @@ static void tsi108_check_phy(struct net_device *dev) u32 speed; unsigned long flags; - /* Do a dummy read, as for some reason the first read - * after a link becomes up returns link down, even if - * it's been a while since the link came up. - */ - spin_lock_irqsave(&phy_lock, flags); if (!data->phy_ok) goto out; - tsi108_read_mii(data, MII_BMSR); - duplex = mii_check_media(&data->mii_if, netif_msg_link(data), data->init_media); data->init_media = 0; @@ -345,22 +339,21 @@ static void tsi108_check_phy(struct net_device *dev) TSI_WRITE(TSI108_MAC_CFG2, mac_cfg2_reg); TSI_WRITE(TSI108_EC_PORTCTRL, portctrl_reg); + } - if (data->link_up == 0) { - /* The manual says it can take 3-4 usecs for the speed change - * to take effect. - */ - udelay(5); + if (data->link_up == 0) { + /* The manual says it can take 3-4 usecs for the speed change + * to take effect. + */ + udelay(5); - spin_lock(&data->txlock); - if (is_valid_ether_addr(dev->dev_addr) && data->txfree) - netif_wake_queue(dev); + spin_lock(&data->txlock); + if (is_valid_ether_addr(dev->dev_addr) && data->txfree) + netif_wake_queue(dev); - data->link_up = 1; - spin_unlock(&data->txlock); - } + data->link_up = 1; + spin_unlock(&data->txlock); } - } else { if (data->link_up == 1) { netif_stop_queue(dev); @@ -1274,12 +1267,11 @@ static void tsi108_init_phy(struct net_device *dev) * PHY_STAT register before the link up status bit is set. */ - data->link_up = 1; + data->link_up = 0; while (!((phyval = tsi108_read_mii(data, MII_BMSR)) & BMSR_LSTATUS)) { if (i++ > (MII_READ_DELAY / 10)) { - data->link_up = 0; break; } spin_unlock_irqrestore(&phy_lock, flags); @@ -1287,6 +1279,7 @@ static void tsi108_init_phy(struct net_device *dev) spin_lock_irqsave(&phy_lock, flags); } + data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if); printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval); data->phy_ok = 1; data->init_media = 1; @@ -1527,12 +1520,46 @@ static void tsi108_init_mac(struct net_device *dev) TSI_WRITE(TSI108_EC_INTMASK, ~0); } +static int tsi108_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&data->txlock, flags); + rc = mii_ethtool_gset(&data->mii_if, cmd); + spin_unlock_irqrestore(&data->txlock, flags); + + return rc; +} + +static int tsi108_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&data->txlock, flags); + rc = mii_ethtool_sset(&data->mii_if, cmd); + spin_unlock_irqrestore(&data->txlock, flags); + + return rc; +} + static int tsi108_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct tsi108_prv_data *data = netdev_priv(dev); + if (!netif_running(dev)) + return -EINVAL; return generic_mii_ioctl(&data->mii_if, if_mii(rq), cmd, NULL); } +static const struct ethtool_ops tsi108_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_settings = tsi108_get_settings, + .set_settings = tsi108_set_settings, +}; + static int tsi108_init_one(struct platform_device *pdev) { @@ -1584,7 +1611,6 @@ tsi108_init_one(struct platform_device *pdev) data->mii_if.phy_id = einfo->phy; data->mii_if.phy_id_mask = 0x1f; data->mii_if.reg_num_mask = 0x1f; - data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if); data->phy = einfo->phy; data->phy_type = einfo->phy_type; @@ -1598,6 +1624,7 @@ tsi108_init_one(struct platform_device *pdev) dev->get_stats = tsi108_get_stats; netif_napi_add(dev, &data->napi, tsi108_poll, 64); dev->do_ioctl = tsi108_do_ioctl; + dev->ethtool_ops = &tsi108_ethtool_ops; /* Apparently, the Linux networking code won't use scatter-gather * if the hardware doesn't do checksums. However, it's faster @@ -1629,6 +1656,7 @@ tsi108_init_one(struct platform_device *pdev) goto register_fail; } + platform_set_drvdata(pdev, dev); printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n", dev->name, print_mac(mac, dev->dev_addr)); #ifdef DEBUG diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index a7afeea156b..a59c1f224aa 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -482,9 +482,11 @@ static void uli526x_init(struct net_device *dev) struct uli526x_board_info *db = netdev_priv(dev); unsigned long ioaddr = db->ioaddr; u8 phy_tmp; + u8 timeout; u16 phy_value; u16 phy_reg_reset; + ULI526X_DBUG(0, "uli526x_init()", 0); /* Reset M526x MAC controller */ @@ -509,11 +511,19 @@ static void uli526x_init(struct net_device *dev) /* Parser SROM and media mode */ db->media_mode = uli526x_media_mode; - /* Phyxcer capability setting */ + /* phyxcer capability setting */ phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id); phy_reg_reset = (phy_reg_reset | 0x8000); phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id); + + /* See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management + * functions") or phy data sheet for details on phy reset + */ udelay(500); + timeout = 10; + while (timeout-- && + phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id) & 0x8000) + udelay(100); /* Process Phyxcer Media Mode */ uli526x_set_phyxcer(db); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 3f67a29593b..e2ad98bee6e 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -244,18 +244,6 @@ static int veth_open(struct net_device *dev) return 0; } -static int veth_close(struct net_device *dev) -{ - struct veth_priv *priv; - - if (netif_carrier_ok(dev)) { - priv = netdev_priv(dev); - netif_carrier_off(dev); - netif_carrier_off(priv->peer); - } - return 0; -} - static int veth_dev_init(struct net_device *dev) { struct veth_net_stats *stats; @@ -286,13 +274,50 @@ static void veth_setup(struct net_device *dev) dev->hard_start_xmit = veth_xmit; dev->get_stats = veth_get_stats; dev->open = veth_open; - dev->stop = veth_close; dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; dev->init = veth_dev_init; dev->destructor = veth_dev_free; } +static void veth_change_state(struct net_device *dev) +{ + struct net_device *peer; + struct veth_priv *priv; + + priv = netdev_priv(dev); + peer = priv->peer; + + if (netif_carrier_ok(peer)) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else { + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); + } +} + +static int veth_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + if (dev->open != veth_open) + goto out; + + switch (event) { + case NETDEV_CHANGE: + veth_change_state(dev); + break; + } +out: + return NOTIFY_DONE; +} + +static struct notifier_block veth_notifier_block __read_mostly = { + .notifier_call = veth_device_event, +}; + /* * netlink interface */ @@ -454,12 +479,14 @@ static struct rtnl_link_ops veth_link_ops = { static __init int veth_init(void) { + register_netdevice_notifier(&veth_notifier_block); return rtnl_link_register(&veth_link_ops); } static __exit void veth_exit(void) { rtnl_link_unregister(&veth_link_ops); + unregister_netdevice_notifier(&veth_notifier_block); } module_init(veth_init); diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 7c851b1e6da..8c9d6ae2bb3 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1893,7 +1893,7 @@ static void rhine_shutdown (struct pci_dev *pdev) /* Make sure we use pattern 0, 1 and not 4, 5 */ if (rp->quirks & rq6patterns) - iowrite8(0x04, ioaddr + 0xA7); + iowrite8(0x04, ioaddr + WOLcgClr); if (rp->wolopts & WAKE_MAGIC) { iowrite8(WOLmagic, ioaddr + WOLcrSet); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fdc23678117..19fd4cb0ddf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -361,6 +361,7 @@ static int virtnet_probe(struct virtio_device *vdev) netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight); vi->dev = dev; vi->vdev = vdev; + vdev->priv = vi; /* We expect two virtqueues, receive then send. */ vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); @@ -395,7 +396,6 @@ static int virtnet_probe(struct virtio_device *vdev) } pr_debug("virtnet: registered device %s\n", dev->name); - vdev->priv = vi; return 0; unregister: diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index c79066b38d3..69dea339261 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -1035,7 +1035,7 @@ struct ath5k_hw { unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); - bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, + int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ddc87149fe3..bef967ce34a 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -668,7 +668,10 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) * return false w/o doing anything. MAC's that do * support it will return true w/o doing anything. */ - if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0)) + ret = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + if (ret < 0) + goto err; + if (ret > 0) __set_bit(ATH_STAT_MRRETRY, sc->status); /* @@ -1256,7 +1259,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, if (ctl->flags & IEEE80211_TXCTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; - pktlen = skb->len + FCS_LEN; + pktlen = skb->len; if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) { keyidx = ctl->key_idx; @@ -1715,6 +1718,7 @@ ath5k_tasklet_rx(unsigned long data) break; else if (unlikely(ret)) { ATH5K_ERR(sc, "error in processing rx descriptor\n"); + spin_unlock(&sc->rxbuflock); return; } @@ -1952,7 +1956,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, } ds->ds_data = bf->skbaddr; - ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN, + ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1, AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); @@ -2126,8 +2130,9 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) "updated timers based on beacon TSF\n"); ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", - bc_tsf, hw_tsf, bc_tu, hw_tu, nexttbtt); + "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", + (unsigned long long) bc_tsf, + (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", intval & AR5K_BEACON_PERIOD, intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", @@ -2385,10 +2390,11 @@ ath5k_intr(int irq, void *dev_id) u64 tsf = ath5k_hw_get_tsf64(ah); sc->nexttbtt += sc->bintval; ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), tsf); + "SWBA nexttbtt: %x hw_tu: %x " + "TSF: %llx\n", + sc->nexttbtt, + TSF_TO_TU(tsf), + (unsigned long long) tsf); } else { ath5k_beacon_send(sc); } diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 3a4bf4035a2..c2de2d958e8 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -45,7 +45,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, +static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *); @@ -3506,7 +3506,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, { u32 frame_type; struct ath5k_hw_2w_tx_desc *tx_desc; - unsigned int buff_len; + unsigned int frame_len; tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; @@ -3537,22 +3537,25 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* Setup control descriptor */ /* Verify and set frame length */ - if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) + + /* remove padding we might have added before */ + frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; + + if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; + tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ - buff_len = pkt_len - FCS_LEN; /* NB: beacon's BufLen must be a multiple of 4 bytes */ if(type == AR5K_PKT_TYPE_BEACON) - buff_len = roundup(buff_len, 4); + pkt_len = roundup(pkt_len, 4); - if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) + if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; + tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; /* * Verify and set header length @@ -3634,7 +3637,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_desc *tx_desc; struct ath5k_hw_tx_status *tx_status; - unsigned int buff_len; + unsigned int frame_len; ATH5K_TRACE(ah->ah_sc); tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; @@ -3669,22 +3672,25 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* Setup control descriptor */ /* Verify and set frame length */ - if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) + + /* remove padding we might have added before */ + frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; + + if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ - buff_len = pkt_len - FCS_LEN; /* NB: beacon's BufLen must be a multiple of 4 bytes */ if(type == AR5K_PKT_TYPE_BEACON) - buff_len = roundup(buff_len, 4); + pkt_len = roundup(pkt_len, 4); - if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) + if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; tx_desc->tx_control_0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | @@ -3737,7 +3743,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* * Initialize a 4-word multirate tx descriptor on 5212 */ -static bool +static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) @@ -3777,10 +3783,10 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, #undef _XTX_TRIES - return true; + return 1; } - return false; + return 0; } /* diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 1a2141dabdc..8bc4bc4c330 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -32,6 +32,7 @@ config B43_PCI_AUTOSELECT bool depends on B43 && SSB_PCIHOST_POSSIBLE select SSB_PCIHOST + select SSB_B43_PCI_BRIDGE default y # Auto-select SSB PCICORE driver, if possible diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 08a011f0834..f13346ba9dd 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -14,6 +14,12 @@ #include "lo.h" #include "phy.h" + +/* The unique identifier of the firmware that's officially supported by + * this driver version. */ +#define B43_SUPPORTED_FIRMWARE_ID "FW13" + + #ifdef CONFIG_B43_DEBUG # define B43_DEBUG 1 #else diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ef65c41af00..51dfce16178 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -58,6 +58,8 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); + static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); @@ -1859,11 +1861,11 @@ static int b43_upload_microcode(struct b43_wldev *dev) err = -EOPNOTSUPP; goto error; } - b43dbg(dev->wl, "Loading firmware version %u.%u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", - fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + b43info(dev->wl, "Loading firmware version %u.%u " + "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", + fwrev, fwpatch, + (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, + (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); dev->fw.rev = fwrev; dev->fw.patch = fwpatch; @@ -4200,6 +4202,33 @@ static struct ssb_driver b43_ssb_driver = { .resume = b43_resume, }; +static void b43_print_driverinfo(void) +{ + const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", + *feat_leds = "", *feat_rfkill = ""; + +#ifdef CONFIG_B43_PCI_AUTOSELECT + feat_pci = "P"; +#endif +#ifdef CONFIG_B43_PCMCIA + feat_pcmcia = "M"; +#endif +#ifdef CONFIG_B43_NPHY + feat_nphy = "N"; +#endif +#ifdef CONFIG_B43_LEDS + feat_leds = "L"; +#endif +#ifdef CONFIG_B43_RFKILL + feat_rfkill = "R"; +#endif + printk(KERN_INFO "Broadcom 43xx driver loaded " + "[ Features: %s%s%s%s%s, Firmware-ID: " + B43_SUPPORTED_FIRMWARE_ID " ]\n", + feat_pci, feat_pcmcia, feat_nphy, + feat_leds, feat_rfkill); +} + static int __init b43_init(void) { int err; @@ -4211,6 +4240,7 @@ static int __init b43_init(void) err = ssb_driver_register(&b43_ssb_driver); if (err) goto err_pcmcia_exit; + b43_print_driverinfo(); return err; diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig index 6745579ba96..13c65faf024 100644 --- a/drivers/net/wireless/b43legacy/Kconfig +++ b/drivers/net/wireless/b43legacy/Kconfig @@ -25,6 +25,7 @@ config B43LEGACY_PCI_AUTOSELECT bool depends on B43LEGACY && SSB_PCIHOST_POSSIBLE select SSB_PCIHOST + select SSB_B43_PCI_BRIDGE default y # Auto-select SSB PCICORE driver, if possible diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index c80edd2b904..93d45b71799 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -23,6 +23,10 @@ #include "phy.h" +/* The unique identifier of the firmware that's officially supported by this + * driver version. */ +#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10" + #define B43legacy_IRQWAIT_MAX_RETRIES 20 #define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 6e08405e802..e87b427d5e4 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -354,7 +354,8 @@ return 0; } -u16 b43legacy_dmacontroller_base(int dma64bit, int controller_idx) +static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type, + int controller_idx) { static const u16 map64[] = { B43legacy_MMIO_DMA64_BASE0, @@ -373,7 +374,7 @@ u16 b43legacy_dmacontroller_base(int dma64bit, int controller_idx) B43legacy_MMIO_DMA32_BASE5, }; - if (dma64bit) { + if (type == B43legacy_DMA_64BIT) { B43legacy_WARN_ON(!(controller_idx >= 0 && controller_idx < ARRAY_SIZE(map64))); return map64[controller_idx]; @@ -480,8 +481,9 @@ static void free_ringmemory(struct b43legacy_dmaring *ring) } /* Reset the RX DMA channel */ -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, int dma64) +static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, + u16 mmio_base, + enum b43legacy_dmatype type) { int i; u32 value; @@ -489,13 +491,14 @@ int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, might_sleep(); - offset = dma64 ? B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL; b43legacy_write32(dev, mmio_base + offset, 0); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_RXSTATUS : - B43legacy_DMA32_RXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_RXSTAT; if (value == B43legacy_DMA64_RXSTAT_DISABLED) { i = -1; @@ -519,8 +522,9 @@ int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, } /* Reset the RX DMA channel */ -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, int dma64) +static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, + u16 mmio_base, + enum b43legacy_dmatype type) { int i; u32 value; @@ -529,10 +533,10 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, might_sleep(); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_TXSTATUS : - B43legacy_DMA32_TXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_TXSTAT; if (value == B43legacy_DMA64_TXSTAT_DISABLED || value == B43legacy_DMA64_TXSTAT_IDLEWAIT || @@ -547,13 +551,14 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, } msleep(1); } - offset = dma64 ? B43legacy_DMA64_TXCTL : B43legacy_DMA32_TXCTL; + offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL : + B43legacy_DMA32_TXCTL; b43legacy_write32(dev, mmio_base + offset, 0); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_TXSTATUS : - B43legacy_DMA32_TXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_TXSTAT; if (value == B43legacy_DMA64_TXSTAT_DISABLED) { i = -1; @@ -578,6 +583,32 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, return 0; } +/* Check if a DMA mapping address is invalid. */ +static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, + dma_addr_t addr, + size_t buffersize) +{ + if (unlikely(dma_mapping_error(addr))) + return 1; + + switch (ring->type) { + case B43legacy_DMA_30BIT: + if ((u64)addr + buffersize > (1ULL << 30)) + return 1; + break; + case B43legacy_DMA_32BIT: + if ((u64)addr + buffersize > (1ULL << 32)) + return 1; + break; + case B43legacy_DMA_64BIT: + /* Currently we can't have addresses beyond 64 bits in the kernel. */ + break; + } + + /* The address is OK. */ + return 0; +} + static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, struct b43legacy_dmadesc_generic *desc, struct b43legacy_dmadesc_meta *meta, @@ -595,7 +626,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, return -ENOMEM; dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - if (dma_mapping_error(dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { /* ugh. try to realloc in zone_dma */ gfp_flags |= GFP_DMA; @@ -608,7 +639,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, ring->rx_buffersize, 0); } - if (dma_mapping_error(dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { dev_kfree_skb_any(skb); return -EIO; } @@ -674,7 +705,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring) u32 trans = ssb_dma_translation(ring->dev->dev); if (ring->tx) { - if (ring->dma64) { + if (ring->type == B43legacy_DMA_64BIT) { u64 ringbase = (u64)(ring->dmabase); addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) @@ -709,7 +740,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring) err = alloc_initial_descbuffers(ring); if (err) goto out; - if (ring->dma64) { + if (ring->type == B43legacy_DMA_64BIT) { u64 ringbase = (u64)(ring->dmabase); addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) @@ -760,16 +791,16 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring) { if (ring->tx) { b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base, - ring->dma64); - if (ring->dma64) { + ring->type); + if (ring->type == B43legacy_DMA_64BIT) { b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0); b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0); } else b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0); } else { b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base, - ring->dma64); - if (ring->dma64) { + ring->type); + if (ring->type == B43legacy_DMA_64BIT) { b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0); b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0); } else @@ -824,11 +855,10 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev) /* Main initialization function. */ static -struct b43legacy_dmaring *b43legacy_setup_dmaring( - struct b43legacy_wldev *dev, - int controller_index, - int for_tx, - int dma64) +struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, + int controller_index, + int for_tx, + enum b43legacy_dmatype type) { struct b43legacy_dmaring *ring; int err; @@ -838,6 +868,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) goto out; + ring->type = type; nr_slots = B43legacy_RXRING_SLOTS; if (for_tx) @@ -855,12 +886,12 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = dma_map_single(dev->dev->dev, - ring->txhdr_cache, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, + sizeof(struct b43legacy_txhdr_fw3), + DMA_TO_DEVICE); - if (dma_mapping_error(dma_test)) { + if (b43legacy_dma_mapping_error(ring, dma_test, + sizeof(struct b43legacy_txhdr_fw3))) { /* ugh realloc */ kfree(ring->txhdr_cache); ring->txhdr_cache = kcalloc(nr_slots, @@ -874,7 +905,8 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( sizeof(struct b43legacy_txhdr_fw3), DMA_TO_DEVICE); - if (dma_mapping_error(dma_test)) + if (b43legacy_dma_mapping_error(ring, dma_test, + sizeof(struct b43legacy_txhdr_fw3))) goto err_kfree_txhdr_cache; } @@ -885,11 +917,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( ring->dev = dev; ring->nr_slots = nr_slots; - ring->mmio_base = b43legacy_dmacontroller_base(dma64, - controller_index); + ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); ring->index = controller_index; - ring->dma64 = !!dma64; - if (dma64) + if (type == B43legacy_DMA_64BIT) ring->ops = &dma64_ops; else ring->ops = &dma32_ops; @@ -939,10 +969,10 @@ static void b43legacy_destroy_dmaring(struct b43legacy_dmaring *ring) if (!ring) return; - b43legacydbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots:" - " %d/%d\n", (ring->dma64) ? "64" : "32", ring->mmio_base, - (ring->tx) ? "TX" : "RX", - ring->max_used_slots, ring->nr_slots); + b43legacydbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots:" + " %d/%d\n", (unsigned int)(ring->type), ring->mmio_base, + (ring->tx) ? "TX" : "RX", ring->max_used_slots, + ring->nr_slots); /* Device IRQs are disabled prior entering this function, * so no need to take care of concurrency with rx handler stuff. */ @@ -988,11 +1018,22 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) struct b43legacy_dmaring *ring; int err; u64 dmamask; - int dma64 = 0; + enum b43legacy_dmatype type; dmamask = supported_dma_mask(dev); - if (dmamask == DMA_64BIT_MASK) - dma64 = 1; + switch (dmamask) { + default: + B43legacy_WARN_ON(1); + case DMA_30BIT_MASK: + type = B43legacy_DMA_30BIT; + break; + case DMA_32BIT_MASK: + type = B43legacy_DMA_32BIT; + break; + case DMA_64BIT_MASK: + type = B43legacy_DMA_64BIT; + break; + } err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { @@ -1010,52 +1051,50 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) err = -ENOMEM; /* setup TX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 0, 1, type); if (!ring) goto out; dma->tx_ring0 = ring; - ring = b43legacy_setup_dmaring(dev, 1, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 1, 1, type); if (!ring) goto err_destroy_tx0; dma->tx_ring1 = ring; - ring = b43legacy_setup_dmaring(dev, 2, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 2, 1, type); if (!ring) goto err_destroy_tx1; dma->tx_ring2 = ring; - ring = b43legacy_setup_dmaring(dev, 3, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 3, 1, type); if (!ring) goto err_destroy_tx2; dma->tx_ring3 = ring; - ring = b43legacy_setup_dmaring(dev, 4, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 4, 1, type); if (!ring) goto err_destroy_tx3; dma->tx_ring4 = ring; - ring = b43legacy_setup_dmaring(dev, 5, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 5, 1, type); if (!ring) goto err_destroy_tx4; dma->tx_ring5 = ring; /* setup RX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 0, dma64); + ring = b43legacy_setup_dmaring(dev, 0, 0, type); if (!ring) goto err_destroy_tx5; dma->rx_ring0 = ring; if (dev->dev->id.revision < 5) { - ring = b43legacy_setup_dmaring(dev, 3, 0, dma64); + ring = b43legacy_setup_dmaring(dev, 3, 0, type); if (!ring) goto err_destroy_rx0; dma->rx_ring3 = ring; } - b43legacydbg(dev->wl, "%d-bit DMA initialized\n", - (dmamask == DMA_64BIT_MASK) ? 64 : - (dmamask == DMA_32BIT_MASK) ? 32 : 30); + b43legacydbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); err = 0; out: return err; @@ -1194,9 +1233,13 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, } meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - sizeof(struct b43legacy_txhdr_fw3), 1); - if (dma_mapping_error(meta_hdr->dmaaddr)) + sizeof(struct b43legacy_txhdr_fw3), 1); + if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr, + sizeof(struct b43legacy_txhdr_fw3))) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; return -EIO; + } ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0); @@ -1211,7 +1254,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ - if (dma_mapping_error(meta->dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { ring->current_slot = old_top_slot; @@ -1225,7 +1268,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (dma_mapping_error(meta->dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -EIO; diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index 26f6ab08de7..2dd488c5be2 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h @@ -218,6 +218,12 @@ struct b43legacy_dma_ops { void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot); }; +enum b43legacy_dmatype { + B43legacy_DMA_30BIT = 30, + B43legacy_DMA_32BIT = 32, + B43legacy_DMA_64BIT = 64, +}; + struct b43legacy_dmaring { /* Lowlevel DMA ops. */ const struct b43legacy_dma_ops *ops; @@ -250,8 +256,8 @@ struct b43legacy_dmaring { int index; /* Boolean. Is this a TX ring? */ bool tx; - /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ - bool dma64; + /* The type of DMA engine used. */ + enum b43legacy_dmatype type; /* Boolean. Is this ring stopped at ieee80211 level? */ bool stopped; /* Lock, only used for TX. */ @@ -284,15 +290,6 @@ void b43legacy_dma_write(struct b43legacy_dmaring *ring, int b43legacy_dma_init(struct b43legacy_wldev *dev); void b43legacy_dma_free(struct b43legacy_wldev *dev); -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64); -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64); - -u16 b43legacy_dmacontroller_base(int dma64bit, int dmacontroller_idx); - void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); @@ -320,20 +317,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) { } static inline -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, struct ieee80211_tx_queue_stats *stats) { diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 53f7f2e9761..c39de422e22 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3,7 +3,7 @@ * Broadcom B43legacy wireless driver * * Copyright (c) 2005 Martin Langer <martin-langer@gmx.de> - * Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> + * Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it> * Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de> * Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> * Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> @@ -60,6 +60,8 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); + #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); @@ -1640,10 +1642,11 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) err = -EOPNOTSUPP; goto error; } - b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u " + "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, + (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, + (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, + fwtime & 0x1F); dev->fw.rev = fwrev; dev->fw.patch = fwpatch; @@ -3806,6 +3809,32 @@ static struct ssb_driver b43legacy_ssb_driver = { .resume = b43legacy_resume, }; +static void b43legacy_print_driverinfo(void) +{ + const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "", + *feat_pio = "", *feat_dma = ""; + +#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT + feat_pci = "P"; +#endif +#ifdef CONFIG_B43LEGACY_LEDS + feat_leds = "L"; +#endif +#ifdef CONFIG_B43LEGACY_RFKILL + feat_rfkill = "R"; +#endif +#ifdef CONFIG_B43LEGACY_PIO + feat_pio = "I"; +#endif +#ifdef CONFIG_B43LEGACY_DMA + feat_dma = "D"; +#endif + printk(KERN_INFO "Broadcom 43xx driver loaded " + "[ Features: %s%s%s%s%s, Firmware-ID: " + B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", + feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); +} + static int __init b43legacy_init(void) { int err; @@ -3816,6 +3845,8 @@ static int __init b43legacy_init(void) if (err) goto err_dfs_exit; + b43legacy_print_driverinfo(); + return err; err_dfs_exit: diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 0159701e845..afb8f4305c2 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -1,6 +1,6 @@ config BCM43XX tristate "Broadcom BCM43xx wireless support (DEPRECATED)" - depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && EXPERIMENTAL + depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL select WIRELESS_EXT select FW_LOADER select HW_RANDOM diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3e6ad7b92c8..a56d9fc6354 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -3365,7 +3365,6 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv, /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); } @@ -3607,7 +3606,22 @@ static int ipw_load(struct ipw_priv *priv) * Driver allocates buffers of this size for Rx */ -static inline int ipw_queue_space(const struct clx2_queue *q) +/** + * ipw_rx_queue_space - Return number of free slots available in queue. + */ +static int ipw_rx_queue_space(const struct ipw_rx_queue *q) +{ + int s = q->read - q->write; + if (s <= 0) + s += RX_QUEUE_SIZE; + /* keep some buffer to not confuse full and empty queue */ + s -= 2; + if (s < 0) + s = 0; + return s; +} + +static inline int ipw_tx_queue_space(const struct clx2_queue *q) { int s = q->last_used - q->first_empty; if (s <= 0) @@ -4947,7 +4961,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv, priv->tx_packets++; } done: - if ((ipw_queue_space(q) > q->low_mark) && + if ((ipw_tx_queue_space(q) > q->low_mark) && (qindex >= 0) && (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev)) netif_wake_queue(priv->net_dev); @@ -4965,7 +4979,7 @@ static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, struct clx2_queue *q = &txq->q; struct tfd_frame *tfd; - if (ipw_queue_space(q) < (sync ? 1 : 2)) { + if (ipw_tx_queue_space(q) < (sync ? 1 : 2)) { IPW_ERROR("No space for Tx\n"); return -EBUSY; } @@ -5070,7 +5084,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) spin_lock_irqsave(&rxq->lock, flags); write = rxq->write; - while ((rxq->write != rxq->processed) && (rxq->free_count)) { + while ((ipw_rx_queue_space(rxq) > 0) && (rxq->free_count)) { element = rxq->rx_free.next; rxb = list_entry(element, struct ipw_rx_mem_buffer, list); list_del(element); @@ -5187,7 +5201,6 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv) /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; return rxq; @@ -8223,13 +8236,17 @@ static void ipw_rx(struct ipw_priv *priv) struct ieee80211_hdr_4addr *header; u32 r, w, i; u8 network_packet; + u8 fill_rx = 0; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); DECLARE_MAC_BUF(mac3); r = ipw_read32(priv, IPW_RX_READ_INDEX); w = ipw_read32(priv, IPW_RX_WRITE_INDEX); - i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; + i = priv->rxq->read; + + if (ipw_rx_queue_space (priv->rxq) > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; while (i != r) { rxb = priv->rxq->queue[i]; @@ -8404,11 +8421,17 @@ static void ipw_rx(struct ipw_priv *priv) list_add_tail(&rxb->list, &priv->rxq->rx_used); i = (i + 1) % RX_QUEUE_SIZE; + + /* If there are a lot of unsued frames, restock the Rx queue + * so the ucode won't assert */ + if (fill_rx) { + priv->rxq->read = i; + ipw_rx_queue_replenish(priv); + } } /* Backtrack one entry */ - priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1; - + priv->rxq->read = i; ipw_rx_queue_restock(priv); } @@ -10336,7 +10359,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); - if (ipw_queue_space(q) < q->high_mark) + if (ipw_tx_queue_space(q) < q->high_mark) netif_stop_queue(priv->net_dev); return NETDEV_TX_OK; @@ -10357,7 +10380,7 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri) struct clx2_tx_queue *txq = &priv->txq[0]; #endif /* CONFIG_IPW2200_QOS */ - if (ipw_queue_space(&txq->q) < txq->q.high_mark) + if (ipw_tx_queue_space(&txq->q) < txq->q.high_mark) return 1; return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5ee1ad69898..40b71bc2c4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -687,6 +687,12 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); + + if (iwl3945_is_rfkill(priv)) { + IWL_DEBUG_INFO("Not sending command - RF KILL"); + return -EIO; + } + if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERROR("No space for Tx\n"); return -ENOSPC; @@ -1580,7 +1586,7 @@ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) */ int iwl3945_eeprom_init(struct iwl3945_priv *priv) { - __le16 *e = (__le16 *)&priv->eeprom; + u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); @@ -1623,7 +1629,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) IWL_ERROR("Time out reading EEPROM[%d]", addr); return -ETIMEDOUT; } - e[addr / 2] = cpu_to_le16(r >> 16); + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } return 0; @@ -2806,7 +2812,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, #endif /* drop all data frame if we are not associated */ - if ((!iwl3945_is_associated(priv) || !priv->assoc_id) && + if ((!iwl3945_is_associated(priv) || + ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; @@ -4281,7 +4288,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) int reclaim; unsigned long flags; u8 fill_rx = 0; - u32 count = 0; + u32 count = 8; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -6256,6 +6263,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND; goto exit; @@ -6267,6 +6276,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f423241b956..a23d4798653 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -692,6 +692,11 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); + if (iwl4965_is_rfkill(priv)) { + IWL_DEBUG_INFO("Not sending command - RF KILL"); + return -EIO; + } + if (iwl4965_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERROR("No space for Tx\n"); return -ENOSPC; @@ -1654,7 +1659,7 @@ static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) */ int iwl4965_eeprom_init(struct iwl4965_priv *priv) { - __le16 *e = (__le16 *)&priv->eeprom; + u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); @@ -1698,7 +1703,7 @@ int iwl4965_eeprom_init(struct iwl4965_priv *priv) rc = -ETIMEDOUT; goto done; } - e[addr / 2] = cpu_to_le16(r >> 16); + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } rc = 0; @@ -2935,7 +2940,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, /* drop all data frame if we are not associated */ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && (!iwl4965_is_associated(priv) || - !priv->assoc_id || + ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); goto drop_unlock; @@ -4664,7 +4669,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) int reclaim; unsigned long flags; u8 fill_rx = 0; - u32 count = 0; + u32 count = 8; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -6680,6 +6685,8 @@ static void __iwl4965_down(struct iwl4965_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND; goto exit; @@ -6691,6 +6698,8 @@ static void __iwl4965_down(struct iwl4965_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index eab020338fd..b3c1acbcc65 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1040,7 +1040,6 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, lbs_deb_leave(LBS_DEB_CMD); return ret; } -EXPORT_SYMBOL_GPL(lbs_mesh_access); int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan) { @@ -1576,7 +1575,6 @@ done: lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); return ret; } -EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command); /** * @brief This function allocates the command buffer and link diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index aaacd9bd6bd..4e22341b4f3 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -69,7 +69,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev); int lbs_remove_card(struct lbs_private *priv); int lbs_start_card(struct lbs_private *priv); int lbs_stop_card(struct lbs_private *priv); -int lbs_reset_device(struct lbs_private *priv); void lbs_host_to_card_done(struct lbs_private *priv); int lbs_update_channel(struct lbs_private *priv); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 84fb49ca0fa..4d4e2f3b66a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1351,8 +1351,6 @@ done: lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); return ret; } -EXPORT_SYMBOL_GPL(lbs_add_mesh); - static void lbs_remove_mesh(struct lbs_private *priv) { @@ -1372,7 +1370,6 @@ static void lbs_remove_mesh(struct lbs_private *priv) free_netdev(mesh_dev); lbs_deb_leave(LBS_DEB_MESH); } -EXPORT_SYMBOL_GPL(lbs_remove_mesh); /** * @brief This function finds the CFP in @@ -1458,20 +1455,6 @@ void lbs_interrupt(struct lbs_private *priv) } EXPORT_SYMBOL_GPL(lbs_interrupt); -int lbs_reset_device(struct lbs_private *priv) -{ - int ret; - - lbs_deb_enter(LBS_DEB_MAIN); - ret = lbs_prepare_and_send_command(priv, CMD_802_11_RESET, - CMD_ACT_HALT, 0, 0, NULL); - msleep_interruptible(10); - - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(lbs_reset_device); - static int __init lbs_init_module(void) { lbs_deb_enter(LBS_DEB_MAIN); diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c index 60d286eb0b8..e7d4aee8799 100644 --- a/drivers/net/wireless/p54usb.c +++ b/drivers/net/wireless/p54usb.c @@ -35,6 +35,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ + {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ @@ -62,6 +63,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ + {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index d3ecf89abd9..d9460aed1f2 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -228,9 +228,9 @@ struct NDIS_WLAN_BSSID_EX { struct NDIS_802_11_SSID Ssid; __le32 Privacy; __le32 Rssi; - enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + __le32 NetworkTypeInUse; struct NDIS_802_11_CONFIGURATION Configuration; - enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + __le32 InfrastructureMode; u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; __le32 IELength; u8 IEs[0]; @@ -279,11 +279,11 @@ struct RNDIS_CONFIG_PARAMETER_INFOBUFFER { } __attribute__((packed)); /* these have to match what is in wpa_supplicant */ -enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; -enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 } - wpa_cipher; -enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA, - KEY_MGMT_WPA_NONE } wpa_key_mgmt; +enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP }; +enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, + CIPHER_WEP104 }; +enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE }; /* * private data @@ -2300,7 +2300,7 @@ static void rndis_update_wireless_stats(struct work_struct *work) struct usbnet *usbdev = priv->usbdev; struct iw_statistics iwstats; __le32 rssi, tmp; - int len, ret, bitrate, j; + int len, ret, j; unsigned long flags; int update_jiffies = STATS_UPDATE_JIFFIES; void *buf; @@ -2352,14 +2352,10 @@ static void rndis_update_wireless_stats(struct work_struct *work) if (ret == 0) iwstats.discard.misc += le32_to_cpu(tmp); - /* Workaround transfer stalls on poor quality links. */ - len = sizeof(tmp); - ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len); - if (ret == 0) { - bitrate = le32_to_cpu(tmp) * 100; - if (bitrate > 11000000) - goto end; - + /* Workaround transfer stalls on poor quality links. + * TODO: find right way to fix these stalls (as stalls do not happen + * with ndiswrapper/windows driver). */ + if (iwstats.qual.qual <= 25) { /* Decrease stats worker interval to catch stalls. * faster. Faster than 400-500ms causes packet loss, * Slower doesn't catch stalls fast enough. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d6cba138c7a..c69f85ed766 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -960,8 +960,12 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2400pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + break; case STATE_RADIO_RX_OFF: - rt2400pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_OFF_LINK: + rt2400pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index e874fdcae20..91e87b53374 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1112,8 +1112,12 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2500pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + break; case STATE_RADIO_RX_OFF: - rt2500pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_OFF_LINK: + rt2500pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 86ded4066f5..638c3d24310 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1001,8 +1001,12 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt2500usb_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + break; case STATE_RADIO_RX_OFF: - rt2500usb_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_OFF_LINK: + rt2500usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: @@ -1839,11 +1843,11 @@ static struct usb_device_id rt2500usb_device_table[] = { /* Hercules */ { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Melco */ + { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* MSI */ { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 72cfe00c1ed..07adc576db4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -97,12 +97,16 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, libconf.ant.rx = rx; libconf.ant.tx = tx; + if (rx == rt2x00dev->link.ant.active.rx && + tx == rt2x00dev->link.ant.active.tx) + return; + /* * Antenna setup changes require the RX to be disabled, * else the changes will be ignored by the device. */ if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); /* * Write new antenna setup to device and reset the link tuner. @@ -116,7 +120,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00dev->link.ant.active.tx = libconf.ant.tx; if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); } void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c4be2ac4d7a..0d51f478bcd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -61,11 +61,33 @@ EXPORT_SYMBOL_GPL(rt2x00lib_get_ring); /* * Link tuning handlers */ -static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) +void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) { + if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + /* + * Reset link information. + * Both the currently active vgc level as well as + * the link tuner counter should be reset. Resetting + * the counter is important for devices where the + * device should only perform link tuning during the + * first minute after being enabled. + */ rt2x00dev->link.count = 0; rt2x00dev->link.vgc_level = 0; + /* + * Reset the link tuner. + */ + rt2x00dev->ops->lib->reset_tuner(rt2x00dev); +} + +static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) +{ + /* + * Clear all (possibly) pre-existing quality statistics. + */ memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual)); /* @@ -79,10 +101,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) rt2x00dev->link.qual.rx_percentage = 50; rt2x00dev->link.qual.tx_percentage = 50; - /* - * Reset the link tuner. - */ - rt2x00dev->ops->lib->reset_tuner(rt2x00dev); + rt2x00lib_reset_link_tuner(rt2x00dev); queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); @@ -93,15 +112,6 @@ static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev) cancel_delayed_work_sync(&rt2x00dev->link.work); } -void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - rt2x00lib_stop_link_tuner(rt2x00dev); - rt2x00lib_start_link_tuner(rt2x00dev); -} - /* * Ring initialization */ @@ -260,19 +270,11 @@ static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) if (sample_a == sample_b) return; - if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) { - if (sample_a > sample_b && rx == ANTENNA_B) - rx = ANTENNA_A; - else if (rx == ANTENNA_A) - rx = ANTENNA_B; - } + if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) + rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; - if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) { - if (sample_a > sample_b && tx == ANTENNA_B) - tx = ANTENNA_A; - else if (tx == ANTENNA_A) - tx = ANTENNA_B; - } + if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) + tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; rt2x00lib_config_antenna(rt2x00dev, rx, tx); } @@ -293,7 +295,7 @@ static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) * sample the rssi from the other antenna to make a valid * comparison between the 2 antennas. */ - if ((rssi_curr - rssi_old) > -5 || (rssi_curr - rssi_old) < 5) + if (abs(rssi_curr - rssi_old) < 5) return; rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; @@ -319,15 +321,15 @@ static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY; if (rt2x00dev->hw->conf.antenna_sel_rx == 0 && - rt2x00dev->default_ant.rx != ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY; if (rt2x00dev->hw->conf.antenna_sel_tx == 0 && - rt2x00dev->default_ant.tx != ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY; if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) && !(rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)) { - rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE; + rt2x00dev->link.ant.flags = 0; return; } @@ -441,17 +443,18 @@ static void rt2x00lib_link_tuner(struct work_struct *work) rt2x00dev->ops->lib->link_tuner(rt2x00dev); /* - * Evaluate antenna setup. - */ - rt2x00lib_evaluate_antenna(rt2x00dev); - - /* * Precalculate a portion of the link signal which is * in based on the tx/rx success/failure counters. */ rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual); /* + * Evaluate antenna setup, make this the last step since this could + * possibly reset some statistics. + */ + rt2x00lib_evaluate_antenna(rt2x00dev); + + /* * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 838421216da..b1915dc7dda 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -85,6 +85,8 @@ enum dev_state { STATE_RADIO_OFF, STATE_RADIO_RX_ON, STATE_RADIO_RX_OFF, + STATE_RADIO_RX_ON_LINK, + STATE_RADIO_RX_OFF_LINK, STATE_RADIO_IRQ_ON, STATE_RADIO_IRQ_OFF, }; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b31f0c26c32..e808db98f2f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1482,8 +1482,12 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt61pci_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + break; case STATE_RADIO_RX_OFF: - rt61pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_OFF_LINK: + rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4d576ab3e7f..4fac2d414d8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1208,8 +1208,12 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt73usb_disable_radio(rt2x00dev); break; case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + break; case STATE_RADIO_RX_OFF: - rt73usb_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_OFF_LINK: + rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); break; case STATE_DEEP_SLEEP: case STATE_SLEEP: diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 27ebd689aa2..5e9a8ace0d8 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -135,13 +135,15 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) while (skb_queue_len(&ring->queue)) { struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb; - struct ieee80211_tx_status status = { {0} }; + struct ieee80211_tx_status status; struct ieee80211_tx_control *control; u32 flags = le32_to_cpu(entry->flags); if (flags & RTL8180_TX_DESC_FLAG_OWN) return; + memset(&status, 0, sizeof(status)); + ring->idx = (ring->idx + 1) % ring->entries; skb = __skb_dequeue(&ring->queue); pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 0d71716d750..f44505994a0 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -113,10 +113,12 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) static void rtl8187_tx_cb(struct urb *urb) { - struct ieee80211_tx_status status = { {0} }; + struct ieee80211_tx_status status; struct sk_buff *skb = (struct sk_buff *)urb->context; struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb; + memset(&status, 0, sizeof(status)); + usb_free_urb(info->urb); if (info->control) memcpy(&status.control, info->control, sizeof(status.control)); diff --git a/drivers/net/wireless/wavelan.h b/drivers/net/wireless/wavelan.h index 27172cde5a3..9ab360558ff 100644 --- a/drivers/net/wireless/wavelan.h +++ b/drivers/net/wireless/wavelan.h @@ -85,7 +85,7 @@ union hacs_u #define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ #define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ #define HASR_PSA_BUSY 0x0008 /* LAN parameter storage area busy */ -}; +} __attribute__ ((packed)); typedef struct ha_t ha_t; struct ha_t @@ -292,7 +292,7 @@ struct mmw_t #define MMW_EXT_ANT_INTERNAL 0x00 /* Internal antenna */ #define MMW_EXT_ANT_EXTERNAL 0x03 /* External antenna */ #define MMW_EXT_ANT_IQ_TEST 0x1C /* IQ test pattern (set to 0) */ -}; +} __attribute__ ((packed)); #define MMW_SIZE 37 @@ -347,7 +347,7 @@ struct mmr_t unsigned char mmr_unused4[1]; /* unused */ unsigned char mmr_fee_data_l; /* Read data from EEPROM (low) */ unsigned char mmr_fee_data_h; /* Read data from EEPROM (high) */ -}; +} __attribute__ ((packed)); #define MMR_SIZE 36 diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 49127e4b42c..76ef2d83919 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -360,11 +360,14 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) { struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; struct sk_buff *skb; - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; skb = skb_dequeue(q); if (skb == NULL) return; + + memset(&status, 0, sizeof(status)); + tx_status(hw, skb, &status, 0); } @@ -389,7 +392,8 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error) if (unlikely(error || (cb->control->flags & IEEE80211_TXCTL_NO_ACK))) { - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; + memset(&status, 0, sizeof(status)); tx_status(hw, skb, &status, !error); } else { struct sk_buff_head *q = @@ -603,7 +607,9 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, tx_hdr = (struct ieee80211_hdr *)skb->data; if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) { - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; + + memset(&status, 0, sizeof(status)); status.flags = IEEE80211_TX_STATUS_ACK; status.ack_signal = stats->ssi; __skb_unlink(skb, q); |