1adfc5217SJeff Kirsher /* bnx2.c: Broadcom NX2 network driver. 2adfc5217SJeff Kirsher * 3adfc5217SJeff Kirsher * Copyright (c) 2004-2011 Broadcom Corporation 4adfc5217SJeff Kirsher * 5adfc5217SJeff Kirsher * This program is free software; you can redistribute it and/or modify 6adfc5217SJeff Kirsher * it under the terms of the GNU General Public License as published by 7adfc5217SJeff Kirsher * the Free Software Foundation. 8adfc5217SJeff Kirsher * 9adfc5217SJeff Kirsher * Written by: Michael Chan (mchan@broadcom.com) 10adfc5217SJeff Kirsher */ 11adfc5217SJeff Kirsher 12adfc5217SJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13adfc5217SJeff Kirsher 14adfc5217SJeff Kirsher #include <linux/module.h> 15adfc5217SJeff Kirsher #include <linux/moduleparam.h> 16adfc5217SJeff Kirsher 17adfc5217SJeff Kirsher #include <linux/kernel.h> 18adfc5217SJeff Kirsher #include <linux/timer.h> 19adfc5217SJeff Kirsher #include <linux/errno.h> 20adfc5217SJeff Kirsher #include <linux/ioport.h> 21adfc5217SJeff Kirsher #include <linux/slab.h> 22adfc5217SJeff Kirsher #include <linux/vmalloc.h> 23adfc5217SJeff Kirsher #include <linux/interrupt.h> 24adfc5217SJeff Kirsher #include <linux/pci.h> 25adfc5217SJeff Kirsher #include <linux/init.h> 26adfc5217SJeff Kirsher #include <linux/netdevice.h> 27adfc5217SJeff Kirsher #include <linux/etherdevice.h> 28adfc5217SJeff Kirsher #include <linux/skbuff.h> 29adfc5217SJeff Kirsher #include <linux/dma-mapping.h> 30adfc5217SJeff Kirsher #include <linux/bitops.h> 31adfc5217SJeff Kirsher #include <asm/io.h> 32adfc5217SJeff Kirsher #include <asm/irq.h> 33adfc5217SJeff Kirsher #include <linux/delay.h> 34adfc5217SJeff Kirsher #include <asm/byteorder.h> 35adfc5217SJeff Kirsher #include <asm/page.h> 36adfc5217SJeff Kirsher #include <linux/time.h> 37adfc5217SJeff Kirsher #include <linux/ethtool.h> 38adfc5217SJeff Kirsher #include <linux/mii.h> 3901789349SJiri Pirko #include <linux/if.h> 40adfc5217SJeff Kirsher #include <linux/if_vlan.h> 41adfc5217SJeff Kirsher #include <net/ip.h> 42adfc5217SJeff Kirsher #include <net/tcp.h> 43adfc5217SJeff Kirsher #include <net/checksum.h> 44adfc5217SJeff Kirsher #include <linux/workqueue.h> 45adfc5217SJeff Kirsher #include <linux/crc32.h> 46adfc5217SJeff Kirsher #include <linux/prefetch.h> 47adfc5217SJeff Kirsher #include <linux/cache.h> 48adfc5217SJeff Kirsher #include <linux/firmware.h> 49adfc5217SJeff Kirsher #include <linux/log2.h> 50adfc5217SJeff Kirsher #include <linux/aer.h> 51adfc5217SJeff Kirsher 52adfc5217SJeff Kirsher #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) 53adfc5217SJeff Kirsher #define BCM_CNIC 1 54adfc5217SJeff Kirsher #include "cnic_if.h" 55adfc5217SJeff Kirsher #endif 56adfc5217SJeff Kirsher #include "bnx2.h" 57adfc5217SJeff Kirsher #include "bnx2_fw.h" 58adfc5217SJeff Kirsher 59adfc5217SJeff Kirsher #define DRV_MODULE_NAME "bnx2" 60c2c20ef4SMichael Chan #define DRV_MODULE_VERSION "2.2.1" 61c2c20ef4SMichael Chan #define DRV_MODULE_RELDATE "Dec 18, 2011" 62c2c20ef4SMichael Chan #define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.2.3.fw" 63adfc5217SJeff Kirsher #define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw" 64c2c20ef4SMichael Chan #define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.2.1b.fw" 65adfc5217SJeff Kirsher #define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-6.0.17.fw" 66adfc5217SJeff Kirsher #define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-6.0.17.fw" 67adfc5217SJeff Kirsher 68adfc5217SJeff Kirsher #define RUN_AT(x) (jiffies + (x)) 69adfc5217SJeff Kirsher 70adfc5217SJeff Kirsher /* Time in jiffies before concluding the transmitter is hung. */ 71adfc5217SJeff Kirsher #define TX_TIMEOUT (5*HZ) 72adfc5217SJeff Kirsher 73adfc5217SJeff Kirsher static char version[] __devinitdata = 74adfc5217SJeff Kirsher "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; 75adfc5217SJeff Kirsher 76adfc5217SJeff Kirsher MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>"); 77adfc5217SJeff Kirsher MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver"); 78adfc5217SJeff Kirsher MODULE_LICENSE("GPL"); 79adfc5217SJeff Kirsher MODULE_VERSION(DRV_MODULE_VERSION); 80adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_MIPS_FILE_06); 81adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_06); 82adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_MIPS_FILE_09); 83adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_09); 84adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax); 85adfc5217SJeff Kirsher 86adfc5217SJeff Kirsher static int disable_msi = 0; 87adfc5217SJeff Kirsher 88adfc5217SJeff Kirsher module_param(disable_msi, int, 0); 89adfc5217SJeff Kirsher MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); 90adfc5217SJeff Kirsher 91adfc5217SJeff Kirsher typedef enum { 92adfc5217SJeff Kirsher BCM5706 = 0, 93adfc5217SJeff Kirsher NC370T, 94adfc5217SJeff Kirsher NC370I, 95adfc5217SJeff Kirsher BCM5706S, 96adfc5217SJeff Kirsher NC370F, 97adfc5217SJeff Kirsher BCM5708, 98adfc5217SJeff Kirsher BCM5708S, 99adfc5217SJeff Kirsher BCM5709, 100adfc5217SJeff Kirsher BCM5709S, 101adfc5217SJeff Kirsher BCM5716, 102adfc5217SJeff Kirsher BCM5716S, 103adfc5217SJeff Kirsher } board_t; 104adfc5217SJeff Kirsher 105adfc5217SJeff Kirsher /* indexed by board_t, above */ 106adfc5217SJeff Kirsher static struct { 107adfc5217SJeff Kirsher char *name; 108adfc5217SJeff Kirsher } board_info[] __devinitdata = { 109adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5706 1000Base-T" }, 110adfc5217SJeff Kirsher { "HP NC370T Multifunction Gigabit Server Adapter" }, 111adfc5217SJeff Kirsher { "HP NC370i Multifunction Gigabit Server Adapter" }, 112adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5706 1000Base-SX" }, 113adfc5217SJeff Kirsher { "HP NC370F Multifunction Gigabit Server Adapter" }, 114adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5708 1000Base-T" }, 115adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, 116adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5709 1000Base-T" }, 117adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5709 1000Base-SX" }, 118adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5716 1000Base-T" }, 119adfc5217SJeff Kirsher { "Broadcom NetXtreme II BCM5716 1000Base-SX" }, 120adfc5217SJeff Kirsher }; 121adfc5217SJeff Kirsher 122adfc5217SJeff Kirsher static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = { 123adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, 124adfc5217SJeff Kirsher PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T }, 125adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, 126adfc5217SJeff Kirsher PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I }, 127adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, 128adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 }, 129adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708, 130adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 }, 131adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, 132adfc5217SJeff Kirsher PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F }, 133adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, 134adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, 135adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S, 136adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, 137adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709, 138adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 }, 139adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S, 140adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S }, 141adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, 0x163b, 142adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 }, 143adfc5217SJeff Kirsher { PCI_VENDOR_ID_BROADCOM, 0x163c, 144adfc5217SJeff Kirsher PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716S }, 145adfc5217SJeff Kirsher { 0, } 146adfc5217SJeff Kirsher }; 147adfc5217SJeff Kirsher 148adfc5217SJeff Kirsher static const struct flash_spec flash_table[] = 149adfc5217SJeff Kirsher { 150adfc5217SJeff Kirsher #define BUFFERED_FLAGS (BNX2_NV_BUFFERED | BNX2_NV_TRANSLATE) 151adfc5217SJeff Kirsher #define NONBUFFERED_FLAGS (BNX2_NV_WREN) 152adfc5217SJeff Kirsher /* Slow EEPROM */ 153adfc5217SJeff Kirsher {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, 154adfc5217SJeff Kirsher BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 155adfc5217SJeff Kirsher SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 156adfc5217SJeff Kirsher "EEPROM - slow"}, 157adfc5217SJeff Kirsher /* Expansion entry 0001 */ 158adfc5217SJeff Kirsher {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, 159adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 160adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 161adfc5217SJeff Kirsher "Entry 0001"}, 162adfc5217SJeff Kirsher /* Saifun SA25F010 (non-buffered flash) */ 163adfc5217SJeff Kirsher /* strap, cfg1, & write1 need updates */ 164adfc5217SJeff Kirsher {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, 165adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 166adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, 167adfc5217SJeff Kirsher "Non-buffered flash (128kB)"}, 168adfc5217SJeff Kirsher /* Saifun SA25F020 (non-buffered flash) */ 169adfc5217SJeff Kirsher /* strap, cfg1, & write1 need updates */ 170adfc5217SJeff Kirsher {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, 171adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 172adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, 173adfc5217SJeff Kirsher "Non-buffered flash (256kB)"}, 174adfc5217SJeff Kirsher /* Expansion entry 0100 */ 175adfc5217SJeff Kirsher {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, 176adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 177adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 178adfc5217SJeff Kirsher "Entry 0100"}, 179adfc5217SJeff Kirsher /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ 180adfc5217SJeff Kirsher {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, 181adfc5217SJeff Kirsher NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 182adfc5217SJeff Kirsher ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, 183adfc5217SJeff Kirsher "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, 184adfc5217SJeff Kirsher /* Entry 0110: ST M45PE20 (non-buffered flash)*/ 185adfc5217SJeff Kirsher {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, 186adfc5217SJeff Kirsher NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, 187adfc5217SJeff Kirsher ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, 188adfc5217SJeff Kirsher "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, 189adfc5217SJeff Kirsher /* Saifun SA25F005 (non-buffered flash) */ 190adfc5217SJeff Kirsher /* strap, cfg1, & write1 need updates */ 191adfc5217SJeff Kirsher {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, 192adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 193adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, 194adfc5217SJeff Kirsher "Non-buffered flash (64kB)"}, 195adfc5217SJeff Kirsher /* Fast EEPROM */ 196adfc5217SJeff Kirsher {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, 197adfc5217SJeff Kirsher BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, 198adfc5217SJeff Kirsher SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, 199adfc5217SJeff Kirsher "EEPROM - fast"}, 200adfc5217SJeff Kirsher /* Expansion entry 1001 */ 201adfc5217SJeff Kirsher {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, 202adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 203adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 204adfc5217SJeff Kirsher "Entry 1001"}, 205adfc5217SJeff Kirsher /* Expansion entry 1010 */ 206adfc5217SJeff Kirsher {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, 207adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 208adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 209adfc5217SJeff Kirsher "Entry 1010"}, 210adfc5217SJeff Kirsher /* ATMEL AT45DB011B (buffered flash) */ 211adfc5217SJeff Kirsher {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, 212adfc5217SJeff Kirsher BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 213adfc5217SJeff Kirsher BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, 214adfc5217SJeff Kirsher "Buffered flash (128kB)"}, 215adfc5217SJeff Kirsher /* Expansion entry 1100 */ 216adfc5217SJeff Kirsher {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, 217adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 218adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 219adfc5217SJeff Kirsher "Entry 1100"}, 220adfc5217SJeff Kirsher /* Expansion entry 1101 */ 221adfc5217SJeff Kirsher {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, 222adfc5217SJeff Kirsher NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, 223adfc5217SJeff Kirsher SAIFUN_FLASH_BYTE_ADDR_MASK, 0, 224adfc5217SJeff Kirsher "Entry 1101"}, 225adfc5217SJeff Kirsher /* Ateml Expansion entry 1110 */ 226adfc5217SJeff Kirsher {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, 227adfc5217SJeff Kirsher BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 228adfc5217SJeff Kirsher BUFFERED_FLASH_BYTE_ADDR_MASK, 0, 229adfc5217SJeff Kirsher "Entry 1110 (Atmel)"}, 230adfc5217SJeff Kirsher /* ATMEL AT45DB021B (buffered flash) */ 231adfc5217SJeff Kirsher {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, 232adfc5217SJeff Kirsher BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, 233adfc5217SJeff Kirsher BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, 234adfc5217SJeff Kirsher "Buffered flash (256kB)"}, 235adfc5217SJeff Kirsher }; 236adfc5217SJeff Kirsher 237adfc5217SJeff Kirsher static const struct flash_spec flash_5709 = { 238adfc5217SJeff Kirsher .flags = BNX2_NV_BUFFERED, 239adfc5217SJeff Kirsher .page_bits = BCM5709_FLASH_PAGE_BITS, 240adfc5217SJeff Kirsher .page_size = BCM5709_FLASH_PAGE_SIZE, 241adfc5217SJeff Kirsher .addr_mask = BCM5709_FLASH_BYTE_ADDR_MASK, 242adfc5217SJeff Kirsher .total_size = BUFFERED_FLASH_TOTAL_SIZE*2, 243adfc5217SJeff Kirsher .name = "5709 Buffered flash (256kB)", 244adfc5217SJeff Kirsher }; 245adfc5217SJeff Kirsher 246adfc5217SJeff Kirsher MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); 247adfc5217SJeff Kirsher 248adfc5217SJeff Kirsher static void bnx2_init_napi(struct bnx2 *bp); 249adfc5217SJeff Kirsher static void bnx2_del_napi(struct bnx2 *bp); 250adfc5217SJeff Kirsher 251adfc5217SJeff Kirsher static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) 252adfc5217SJeff Kirsher { 253adfc5217SJeff Kirsher u32 diff; 254adfc5217SJeff Kirsher 255adfc5217SJeff Kirsher /* Tell compiler to fetch tx_prod and tx_cons from memory. */ 256adfc5217SJeff Kirsher barrier(); 257adfc5217SJeff Kirsher 258adfc5217SJeff Kirsher /* The ring uses 256 indices for 255 entries, one of them 259adfc5217SJeff Kirsher * needs to be skipped. 260adfc5217SJeff Kirsher */ 261adfc5217SJeff Kirsher diff = txr->tx_prod - txr->tx_cons; 262adfc5217SJeff Kirsher if (unlikely(diff >= TX_DESC_CNT)) { 263adfc5217SJeff Kirsher diff &= 0xffff; 264adfc5217SJeff Kirsher if (diff == TX_DESC_CNT) 265adfc5217SJeff Kirsher diff = MAX_TX_DESC_CNT; 266adfc5217SJeff Kirsher } 267adfc5217SJeff Kirsher return bp->tx_ring_size - diff; 268adfc5217SJeff Kirsher } 269adfc5217SJeff Kirsher 270adfc5217SJeff Kirsher static u32 271adfc5217SJeff Kirsher bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) 272adfc5217SJeff Kirsher { 273adfc5217SJeff Kirsher u32 val; 274adfc5217SJeff Kirsher 275adfc5217SJeff Kirsher spin_lock_bh(&bp->indirect_lock); 276adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); 277adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW); 278adfc5217SJeff Kirsher spin_unlock_bh(&bp->indirect_lock); 279adfc5217SJeff Kirsher return val; 280adfc5217SJeff Kirsher } 281adfc5217SJeff Kirsher 282adfc5217SJeff Kirsher static void 283adfc5217SJeff Kirsher bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) 284adfc5217SJeff Kirsher { 285adfc5217SJeff Kirsher spin_lock_bh(&bp->indirect_lock); 286adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); 287adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val); 288adfc5217SJeff Kirsher spin_unlock_bh(&bp->indirect_lock); 289adfc5217SJeff Kirsher } 290adfc5217SJeff Kirsher 291adfc5217SJeff Kirsher static void 292adfc5217SJeff Kirsher bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val) 293adfc5217SJeff Kirsher { 294adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, bp->shmem_base + offset, val); 295adfc5217SJeff Kirsher } 296adfc5217SJeff Kirsher 297adfc5217SJeff Kirsher static u32 298adfc5217SJeff Kirsher bnx2_shmem_rd(struct bnx2 *bp, u32 offset) 299adfc5217SJeff Kirsher { 300adfc5217SJeff Kirsher return bnx2_reg_rd_ind(bp, bp->shmem_base + offset); 301adfc5217SJeff Kirsher } 302adfc5217SJeff Kirsher 303adfc5217SJeff Kirsher static void 304adfc5217SJeff Kirsher bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) 305adfc5217SJeff Kirsher { 306adfc5217SJeff Kirsher offset += cid_addr; 307adfc5217SJeff Kirsher spin_lock_bh(&bp->indirect_lock); 308adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 309adfc5217SJeff Kirsher int i; 310adfc5217SJeff Kirsher 311adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_CTX_DATA, val); 312adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_CTX_CTRL, 313adfc5217SJeff Kirsher offset | BNX2_CTX_CTX_CTRL_WRITE_REQ); 314adfc5217SJeff Kirsher for (i = 0; i < 5; i++) { 315adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_CTX_CTX_CTRL); 316adfc5217SJeff Kirsher if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0) 317adfc5217SJeff Kirsher break; 318adfc5217SJeff Kirsher udelay(5); 319adfc5217SJeff Kirsher } 320adfc5217SJeff Kirsher } else { 321adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_DATA_ADR, offset); 322adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_DATA, val); 323adfc5217SJeff Kirsher } 324adfc5217SJeff Kirsher spin_unlock_bh(&bp->indirect_lock); 325adfc5217SJeff Kirsher } 326adfc5217SJeff Kirsher 327adfc5217SJeff Kirsher #ifdef BCM_CNIC 328adfc5217SJeff Kirsher static int 329adfc5217SJeff Kirsher bnx2_drv_ctl(struct net_device *dev, struct drv_ctl_info *info) 330adfc5217SJeff Kirsher { 331adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 332adfc5217SJeff Kirsher struct drv_ctl_io *io = &info->data.io; 333adfc5217SJeff Kirsher 334adfc5217SJeff Kirsher switch (info->cmd) { 335adfc5217SJeff Kirsher case DRV_CTL_IO_WR_CMD: 336adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, io->offset, io->data); 337adfc5217SJeff Kirsher break; 338adfc5217SJeff Kirsher case DRV_CTL_IO_RD_CMD: 339adfc5217SJeff Kirsher io->data = bnx2_reg_rd_ind(bp, io->offset); 340adfc5217SJeff Kirsher break; 341adfc5217SJeff Kirsher case DRV_CTL_CTX_WR_CMD: 342adfc5217SJeff Kirsher bnx2_ctx_wr(bp, io->cid_addr, io->offset, io->data); 343adfc5217SJeff Kirsher break; 344adfc5217SJeff Kirsher default: 345adfc5217SJeff Kirsher return -EINVAL; 346adfc5217SJeff Kirsher } 347adfc5217SJeff Kirsher return 0; 348adfc5217SJeff Kirsher } 349adfc5217SJeff Kirsher 350adfc5217SJeff Kirsher static void bnx2_setup_cnic_irq_info(struct bnx2 *bp) 351adfc5217SJeff Kirsher { 352adfc5217SJeff Kirsher struct cnic_eth_dev *cp = &bp->cnic_eth_dev; 353adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 354adfc5217SJeff Kirsher int sb_id; 355adfc5217SJeff Kirsher 356adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSIX) { 357adfc5217SJeff Kirsher cp->drv_state |= CNIC_DRV_STATE_USING_MSIX; 358adfc5217SJeff Kirsher bnapi->cnic_present = 0; 359adfc5217SJeff Kirsher sb_id = bp->irq_nvecs; 360adfc5217SJeff Kirsher cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX; 361adfc5217SJeff Kirsher } else { 362adfc5217SJeff Kirsher cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX; 363adfc5217SJeff Kirsher bnapi->cnic_tag = bnapi->last_status_idx; 364adfc5217SJeff Kirsher bnapi->cnic_present = 1; 365adfc5217SJeff Kirsher sb_id = 0; 366adfc5217SJeff Kirsher cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX; 367adfc5217SJeff Kirsher } 368adfc5217SJeff Kirsher 369adfc5217SJeff Kirsher cp->irq_arr[0].vector = bp->irq_tbl[sb_id].vector; 370adfc5217SJeff Kirsher cp->irq_arr[0].status_blk = (void *) 371adfc5217SJeff Kirsher ((unsigned long) bnapi->status_blk.msi + 372adfc5217SJeff Kirsher (BNX2_SBLK_MSIX_ALIGN_SIZE * sb_id)); 373adfc5217SJeff Kirsher cp->irq_arr[0].status_blk_num = sb_id; 374adfc5217SJeff Kirsher cp->num_irq = 1; 375adfc5217SJeff Kirsher } 376adfc5217SJeff Kirsher 377adfc5217SJeff Kirsher static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops, 378adfc5217SJeff Kirsher void *data) 379adfc5217SJeff Kirsher { 380adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 381adfc5217SJeff Kirsher struct cnic_eth_dev *cp = &bp->cnic_eth_dev; 382adfc5217SJeff Kirsher 383adfc5217SJeff Kirsher if (ops == NULL) 384adfc5217SJeff Kirsher return -EINVAL; 385adfc5217SJeff Kirsher 386adfc5217SJeff Kirsher if (cp->drv_state & CNIC_DRV_STATE_REGD) 387adfc5217SJeff Kirsher return -EBUSY; 388adfc5217SJeff Kirsher 389adfc5217SJeff Kirsher if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN)) 390adfc5217SJeff Kirsher return -ENODEV; 391adfc5217SJeff Kirsher 392adfc5217SJeff Kirsher bp->cnic_data = data; 393adfc5217SJeff Kirsher rcu_assign_pointer(bp->cnic_ops, ops); 394adfc5217SJeff Kirsher 395adfc5217SJeff Kirsher cp->num_irq = 0; 396adfc5217SJeff Kirsher cp->drv_state = CNIC_DRV_STATE_REGD; 397adfc5217SJeff Kirsher 398adfc5217SJeff Kirsher bnx2_setup_cnic_irq_info(bp); 399adfc5217SJeff Kirsher 400adfc5217SJeff Kirsher return 0; 401adfc5217SJeff Kirsher } 402adfc5217SJeff Kirsher 403adfc5217SJeff Kirsher static int bnx2_unregister_cnic(struct net_device *dev) 404adfc5217SJeff Kirsher { 405adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 406adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 407adfc5217SJeff Kirsher struct cnic_eth_dev *cp = &bp->cnic_eth_dev; 408adfc5217SJeff Kirsher 409adfc5217SJeff Kirsher mutex_lock(&bp->cnic_lock); 410adfc5217SJeff Kirsher cp->drv_state = 0; 411adfc5217SJeff Kirsher bnapi->cnic_present = 0; 4122cfa5a04SEric Dumazet RCU_INIT_POINTER(bp->cnic_ops, NULL); 413adfc5217SJeff Kirsher mutex_unlock(&bp->cnic_lock); 414adfc5217SJeff Kirsher synchronize_rcu(); 415adfc5217SJeff Kirsher return 0; 416adfc5217SJeff Kirsher } 417adfc5217SJeff Kirsher 418adfc5217SJeff Kirsher struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev) 419adfc5217SJeff Kirsher { 420adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 421adfc5217SJeff Kirsher struct cnic_eth_dev *cp = &bp->cnic_eth_dev; 422adfc5217SJeff Kirsher 423adfc5217SJeff Kirsher if (!cp->max_iscsi_conn) 424adfc5217SJeff Kirsher return NULL; 425adfc5217SJeff Kirsher 426adfc5217SJeff Kirsher cp->drv_owner = THIS_MODULE; 427adfc5217SJeff Kirsher cp->chip_id = bp->chip_id; 428adfc5217SJeff Kirsher cp->pdev = bp->pdev; 429adfc5217SJeff Kirsher cp->io_base = bp->regview; 430adfc5217SJeff Kirsher cp->drv_ctl = bnx2_drv_ctl; 431adfc5217SJeff Kirsher cp->drv_register_cnic = bnx2_register_cnic; 432adfc5217SJeff Kirsher cp->drv_unregister_cnic = bnx2_unregister_cnic; 433adfc5217SJeff Kirsher 434adfc5217SJeff Kirsher return cp; 435adfc5217SJeff Kirsher } 436adfc5217SJeff Kirsher EXPORT_SYMBOL(bnx2_cnic_probe); 437adfc5217SJeff Kirsher 438adfc5217SJeff Kirsher static void 439adfc5217SJeff Kirsher bnx2_cnic_stop(struct bnx2 *bp) 440adfc5217SJeff Kirsher { 441adfc5217SJeff Kirsher struct cnic_ops *c_ops; 442adfc5217SJeff Kirsher struct cnic_ctl_info info; 443adfc5217SJeff Kirsher 444adfc5217SJeff Kirsher mutex_lock(&bp->cnic_lock); 445adfc5217SJeff Kirsher c_ops = rcu_dereference_protected(bp->cnic_ops, 446adfc5217SJeff Kirsher lockdep_is_held(&bp->cnic_lock)); 447adfc5217SJeff Kirsher if (c_ops) { 448adfc5217SJeff Kirsher info.cmd = CNIC_CTL_STOP_CMD; 449adfc5217SJeff Kirsher c_ops->cnic_ctl(bp->cnic_data, &info); 450adfc5217SJeff Kirsher } 451adfc5217SJeff Kirsher mutex_unlock(&bp->cnic_lock); 452adfc5217SJeff Kirsher } 453adfc5217SJeff Kirsher 454adfc5217SJeff Kirsher static void 455adfc5217SJeff Kirsher bnx2_cnic_start(struct bnx2 *bp) 456adfc5217SJeff Kirsher { 457adfc5217SJeff Kirsher struct cnic_ops *c_ops; 458adfc5217SJeff Kirsher struct cnic_ctl_info info; 459adfc5217SJeff Kirsher 460adfc5217SJeff Kirsher mutex_lock(&bp->cnic_lock); 461adfc5217SJeff Kirsher c_ops = rcu_dereference_protected(bp->cnic_ops, 462adfc5217SJeff Kirsher lockdep_is_held(&bp->cnic_lock)); 463adfc5217SJeff Kirsher if (c_ops) { 464adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_USING_MSIX)) { 465adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 466adfc5217SJeff Kirsher 467adfc5217SJeff Kirsher bnapi->cnic_tag = bnapi->last_status_idx; 468adfc5217SJeff Kirsher } 469adfc5217SJeff Kirsher info.cmd = CNIC_CTL_START_CMD; 470adfc5217SJeff Kirsher c_ops->cnic_ctl(bp->cnic_data, &info); 471adfc5217SJeff Kirsher } 472adfc5217SJeff Kirsher mutex_unlock(&bp->cnic_lock); 473adfc5217SJeff Kirsher } 474adfc5217SJeff Kirsher 475adfc5217SJeff Kirsher #else 476adfc5217SJeff Kirsher 477adfc5217SJeff Kirsher static void 478adfc5217SJeff Kirsher bnx2_cnic_stop(struct bnx2 *bp) 479adfc5217SJeff Kirsher { 480adfc5217SJeff Kirsher } 481adfc5217SJeff Kirsher 482adfc5217SJeff Kirsher static void 483adfc5217SJeff Kirsher bnx2_cnic_start(struct bnx2 *bp) 484adfc5217SJeff Kirsher { 485adfc5217SJeff Kirsher } 486adfc5217SJeff Kirsher 487adfc5217SJeff Kirsher #endif 488adfc5217SJeff Kirsher 489adfc5217SJeff Kirsher static int 490adfc5217SJeff Kirsher bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val) 491adfc5217SJeff Kirsher { 492adfc5217SJeff Kirsher u32 val1; 493adfc5217SJeff Kirsher int i, ret; 494adfc5217SJeff Kirsher 495adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { 496adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); 497adfc5217SJeff Kirsher val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; 498adfc5217SJeff Kirsher 499adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); 500adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_MDIO_MODE); 501adfc5217SJeff Kirsher 502adfc5217SJeff Kirsher udelay(40); 503adfc5217SJeff Kirsher } 504adfc5217SJeff Kirsher 505adfc5217SJeff Kirsher val1 = (bp->phy_addr << 21) | (reg << 16) | 506adfc5217SJeff Kirsher BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT | 507adfc5217SJeff Kirsher BNX2_EMAC_MDIO_COMM_START_BUSY; 508adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); 509adfc5217SJeff Kirsher 510adfc5217SJeff Kirsher for (i = 0; i < 50; i++) { 511adfc5217SJeff Kirsher udelay(10); 512adfc5217SJeff Kirsher 513adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); 514adfc5217SJeff Kirsher if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { 515adfc5217SJeff Kirsher udelay(5); 516adfc5217SJeff Kirsher 517adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); 518adfc5217SJeff Kirsher val1 &= BNX2_EMAC_MDIO_COMM_DATA; 519adfc5217SJeff Kirsher 520adfc5217SJeff Kirsher break; 521adfc5217SJeff Kirsher } 522adfc5217SJeff Kirsher } 523adfc5217SJeff Kirsher 524adfc5217SJeff Kirsher if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) { 525adfc5217SJeff Kirsher *val = 0x0; 526adfc5217SJeff Kirsher ret = -EBUSY; 527adfc5217SJeff Kirsher } 528adfc5217SJeff Kirsher else { 529adfc5217SJeff Kirsher *val = val1; 530adfc5217SJeff Kirsher ret = 0; 531adfc5217SJeff Kirsher } 532adfc5217SJeff Kirsher 533adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { 534adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); 535adfc5217SJeff Kirsher val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; 536adfc5217SJeff Kirsher 537adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); 538adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_MDIO_MODE); 539adfc5217SJeff Kirsher 540adfc5217SJeff Kirsher udelay(40); 541adfc5217SJeff Kirsher } 542adfc5217SJeff Kirsher 543adfc5217SJeff Kirsher return ret; 544adfc5217SJeff Kirsher } 545adfc5217SJeff Kirsher 546adfc5217SJeff Kirsher static int 547adfc5217SJeff Kirsher bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) 548adfc5217SJeff Kirsher { 549adfc5217SJeff Kirsher u32 val1; 550adfc5217SJeff Kirsher int i, ret; 551adfc5217SJeff Kirsher 552adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { 553adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); 554adfc5217SJeff Kirsher val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; 555adfc5217SJeff Kirsher 556adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); 557adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_MDIO_MODE); 558adfc5217SJeff Kirsher 559adfc5217SJeff Kirsher udelay(40); 560adfc5217SJeff Kirsher } 561adfc5217SJeff Kirsher 562adfc5217SJeff Kirsher val1 = (bp->phy_addr << 21) | (reg << 16) | val | 563adfc5217SJeff Kirsher BNX2_EMAC_MDIO_COMM_COMMAND_WRITE | 564adfc5217SJeff Kirsher BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT; 565adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); 566adfc5217SJeff Kirsher 567adfc5217SJeff Kirsher for (i = 0; i < 50; i++) { 568adfc5217SJeff Kirsher udelay(10); 569adfc5217SJeff Kirsher 570adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); 571adfc5217SJeff Kirsher if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { 572adfc5217SJeff Kirsher udelay(5); 573adfc5217SJeff Kirsher break; 574adfc5217SJeff Kirsher } 575adfc5217SJeff Kirsher } 576adfc5217SJeff Kirsher 577adfc5217SJeff Kirsher if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) 578adfc5217SJeff Kirsher ret = -EBUSY; 579adfc5217SJeff Kirsher else 580adfc5217SJeff Kirsher ret = 0; 581adfc5217SJeff Kirsher 582adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { 583adfc5217SJeff Kirsher val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); 584adfc5217SJeff Kirsher val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; 585adfc5217SJeff Kirsher 586adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); 587adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_MDIO_MODE); 588adfc5217SJeff Kirsher 589adfc5217SJeff Kirsher udelay(40); 590adfc5217SJeff Kirsher } 591adfc5217SJeff Kirsher 592adfc5217SJeff Kirsher return ret; 593adfc5217SJeff Kirsher } 594adfc5217SJeff Kirsher 595adfc5217SJeff Kirsher static void 596adfc5217SJeff Kirsher bnx2_disable_int(struct bnx2 *bp) 597adfc5217SJeff Kirsher { 598adfc5217SJeff Kirsher int i; 599adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 600adfc5217SJeff Kirsher 601adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 602adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[i]; 603adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | 604adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_MASK_INT); 605adfc5217SJeff Kirsher } 606adfc5217SJeff Kirsher REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); 607adfc5217SJeff Kirsher } 608adfc5217SJeff Kirsher 609adfc5217SJeff Kirsher static void 610adfc5217SJeff Kirsher bnx2_enable_int(struct bnx2 *bp) 611adfc5217SJeff Kirsher { 612adfc5217SJeff Kirsher int i; 613adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 614adfc5217SJeff Kirsher 615adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 616adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[i]; 617adfc5217SJeff Kirsher 618adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | 619adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 620adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_MASK_INT | 621adfc5217SJeff Kirsher bnapi->last_status_idx); 622adfc5217SJeff Kirsher 623adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | 624adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 625adfc5217SJeff Kirsher bnapi->last_status_idx); 626adfc5217SJeff Kirsher } 627adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); 628adfc5217SJeff Kirsher } 629adfc5217SJeff Kirsher 630adfc5217SJeff Kirsher static void 631adfc5217SJeff Kirsher bnx2_disable_int_sync(struct bnx2 *bp) 632adfc5217SJeff Kirsher { 633adfc5217SJeff Kirsher int i; 634adfc5217SJeff Kirsher 635adfc5217SJeff Kirsher atomic_inc(&bp->intr_sem); 636adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 637adfc5217SJeff Kirsher return; 638adfc5217SJeff Kirsher 639adfc5217SJeff Kirsher bnx2_disable_int(bp); 640adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) 641adfc5217SJeff Kirsher synchronize_irq(bp->irq_tbl[i].vector); 642adfc5217SJeff Kirsher } 643adfc5217SJeff Kirsher 644adfc5217SJeff Kirsher static void 645adfc5217SJeff Kirsher bnx2_napi_disable(struct bnx2 *bp) 646adfc5217SJeff Kirsher { 647adfc5217SJeff Kirsher int i; 648adfc5217SJeff Kirsher 649adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) 650adfc5217SJeff Kirsher napi_disable(&bp->bnx2_napi[i].napi); 651adfc5217SJeff Kirsher } 652adfc5217SJeff Kirsher 653adfc5217SJeff Kirsher static void 654adfc5217SJeff Kirsher bnx2_napi_enable(struct bnx2 *bp) 655adfc5217SJeff Kirsher { 656adfc5217SJeff Kirsher int i; 657adfc5217SJeff Kirsher 658adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) 659adfc5217SJeff Kirsher napi_enable(&bp->bnx2_napi[i].napi); 660adfc5217SJeff Kirsher } 661adfc5217SJeff Kirsher 662adfc5217SJeff Kirsher static void 663adfc5217SJeff Kirsher bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic) 664adfc5217SJeff Kirsher { 665adfc5217SJeff Kirsher if (stop_cnic) 666adfc5217SJeff Kirsher bnx2_cnic_stop(bp); 667adfc5217SJeff Kirsher if (netif_running(bp->dev)) { 668adfc5217SJeff Kirsher bnx2_napi_disable(bp); 669adfc5217SJeff Kirsher netif_tx_disable(bp->dev); 670adfc5217SJeff Kirsher } 671adfc5217SJeff Kirsher bnx2_disable_int_sync(bp); 672adfc5217SJeff Kirsher netif_carrier_off(bp->dev); /* prevent tx timeout */ 673adfc5217SJeff Kirsher } 674adfc5217SJeff Kirsher 675adfc5217SJeff Kirsher static void 676adfc5217SJeff Kirsher bnx2_netif_start(struct bnx2 *bp, bool start_cnic) 677adfc5217SJeff Kirsher { 678adfc5217SJeff Kirsher if (atomic_dec_and_test(&bp->intr_sem)) { 679adfc5217SJeff Kirsher if (netif_running(bp->dev)) { 680adfc5217SJeff Kirsher netif_tx_wake_all_queues(bp->dev); 681adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 682adfc5217SJeff Kirsher if (bp->link_up) 683adfc5217SJeff Kirsher netif_carrier_on(bp->dev); 684adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 685adfc5217SJeff Kirsher bnx2_napi_enable(bp); 686adfc5217SJeff Kirsher bnx2_enable_int(bp); 687adfc5217SJeff Kirsher if (start_cnic) 688adfc5217SJeff Kirsher bnx2_cnic_start(bp); 689adfc5217SJeff Kirsher } 690adfc5217SJeff Kirsher } 691adfc5217SJeff Kirsher } 692adfc5217SJeff Kirsher 693adfc5217SJeff Kirsher static void 694adfc5217SJeff Kirsher bnx2_free_tx_mem(struct bnx2 *bp) 695adfc5217SJeff Kirsher { 696adfc5217SJeff Kirsher int i; 697adfc5217SJeff Kirsher 698adfc5217SJeff Kirsher for (i = 0; i < bp->num_tx_rings; i++) { 699adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 700adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 701adfc5217SJeff Kirsher 702adfc5217SJeff Kirsher if (txr->tx_desc_ring) { 703adfc5217SJeff Kirsher dma_free_coherent(&bp->pdev->dev, TXBD_RING_SIZE, 704adfc5217SJeff Kirsher txr->tx_desc_ring, 705adfc5217SJeff Kirsher txr->tx_desc_mapping); 706adfc5217SJeff Kirsher txr->tx_desc_ring = NULL; 707adfc5217SJeff Kirsher } 708adfc5217SJeff Kirsher kfree(txr->tx_buf_ring); 709adfc5217SJeff Kirsher txr->tx_buf_ring = NULL; 710adfc5217SJeff Kirsher } 711adfc5217SJeff Kirsher } 712adfc5217SJeff Kirsher 713adfc5217SJeff Kirsher static void 714adfc5217SJeff Kirsher bnx2_free_rx_mem(struct bnx2 *bp) 715adfc5217SJeff Kirsher { 716adfc5217SJeff Kirsher int i; 717adfc5217SJeff Kirsher 718adfc5217SJeff Kirsher for (i = 0; i < bp->num_rx_rings; i++) { 719adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 720adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 721adfc5217SJeff Kirsher int j; 722adfc5217SJeff Kirsher 723adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_ring; j++) { 724adfc5217SJeff Kirsher if (rxr->rx_desc_ring[j]) 725adfc5217SJeff Kirsher dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE, 726adfc5217SJeff Kirsher rxr->rx_desc_ring[j], 727adfc5217SJeff Kirsher rxr->rx_desc_mapping[j]); 728adfc5217SJeff Kirsher rxr->rx_desc_ring[j] = NULL; 729adfc5217SJeff Kirsher } 730adfc5217SJeff Kirsher vfree(rxr->rx_buf_ring); 731adfc5217SJeff Kirsher rxr->rx_buf_ring = NULL; 732adfc5217SJeff Kirsher 733adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_pg_ring; j++) { 734adfc5217SJeff Kirsher if (rxr->rx_pg_desc_ring[j]) 735adfc5217SJeff Kirsher dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE, 736adfc5217SJeff Kirsher rxr->rx_pg_desc_ring[j], 737adfc5217SJeff Kirsher rxr->rx_pg_desc_mapping[j]); 738adfc5217SJeff Kirsher rxr->rx_pg_desc_ring[j] = NULL; 739adfc5217SJeff Kirsher } 740adfc5217SJeff Kirsher vfree(rxr->rx_pg_ring); 741adfc5217SJeff Kirsher rxr->rx_pg_ring = NULL; 742adfc5217SJeff Kirsher } 743adfc5217SJeff Kirsher } 744adfc5217SJeff Kirsher 745adfc5217SJeff Kirsher static int 746adfc5217SJeff Kirsher bnx2_alloc_tx_mem(struct bnx2 *bp) 747adfc5217SJeff Kirsher { 748adfc5217SJeff Kirsher int i; 749adfc5217SJeff Kirsher 750adfc5217SJeff Kirsher for (i = 0; i < bp->num_tx_rings; i++) { 751adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 752adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 753adfc5217SJeff Kirsher 754adfc5217SJeff Kirsher txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL); 755adfc5217SJeff Kirsher if (txr->tx_buf_ring == NULL) 756adfc5217SJeff Kirsher return -ENOMEM; 757adfc5217SJeff Kirsher 758adfc5217SJeff Kirsher txr->tx_desc_ring = 759adfc5217SJeff Kirsher dma_alloc_coherent(&bp->pdev->dev, TXBD_RING_SIZE, 760adfc5217SJeff Kirsher &txr->tx_desc_mapping, GFP_KERNEL); 761adfc5217SJeff Kirsher if (txr->tx_desc_ring == NULL) 762adfc5217SJeff Kirsher return -ENOMEM; 763adfc5217SJeff Kirsher } 764adfc5217SJeff Kirsher return 0; 765adfc5217SJeff Kirsher } 766adfc5217SJeff Kirsher 767adfc5217SJeff Kirsher static int 768adfc5217SJeff Kirsher bnx2_alloc_rx_mem(struct bnx2 *bp) 769adfc5217SJeff Kirsher { 770adfc5217SJeff Kirsher int i; 771adfc5217SJeff Kirsher 772adfc5217SJeff Kirsher for (i = 0; i < bp->num_rx_rings; i++) { 773adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 774adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 775adfc5217SJeff Kirsher int j; 776adfc5217SJeff Kirsher 777adfc5217SJeff Kirsher rxr->rx_buf_ring = 778adfc5217SJeff Kirsher vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring); 779adfc5217SJeff Kirsher if (rxr->rx_buf_ring == NULL) 780adfc5217SJeff Kirsher return -ENOMEM; 781adfc5217SJeff Kirsher 782adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_ring; j++) { 783adfc5217SJeff Kirsher rxr->rx_desc_ring[j] = 784adfc5217SJeff Kirsher dma_alloc_coherent(&bp->pdev->dev, 785adfc5217SJeff Kirsher RXBD_RING_SIZE, 786adfc5217SJeff Kirsher &rxr->rx_desc_mapping[j], 787adfc5217SJeff Kirsher GFP_KERNEL); 788adfc5217SJeff Kirsher if (rxr->rx_desc_ring[j] == NULL) 789adfc5217SJeff Kirsher return -ENOMEM; 790adfc5217SJeff Kirsher 791adfc5217SJeff Kirsher } 792adfc5217SJeff Kirsher 793adfc5217SJeff Kirsher if (bp->rx_pg_ring_size) { 794adfc5217SJeff Kirsher rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE * 795adfc5217SJeff Kirsher bp->rx_max_pg_ring); 796adfc5217SJeff Kirsher if (rxr->rx_pg_ring == NULL) 797adfc5217SJeff Kirsher return -ENOMEM; 798adfc5217SJeff Kirsher 799adfc5217SJeff Kirsher } 800adfc5217SJeff Kirsher 801adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_pg_ring; j++) { 802adfc5217SJeff Kirsher rxr->rx_pg_desc_ring[j] = 803adfc5217SJeff Kirsher dma_alloc_coherent(&bp->pdev->dev, 804adfc5217SJeff Kirsher RXBD_RING_SIZE, 805adfc5217SJeff Kirsher &rxr->rx_pg_desc_mapping[j], 806adfc5217SJeff Kirsher GFP_KERNEL); 807adfc5217SJeff Kirsher if (rxr->rx_pg_desc_ring[j] == NULL) 808adfc5217SJeff Kirsher return -ENOMEM; 809adfc5217SJeff Kirsher 810adfc5217SJeff Kirsher } 811adfc5217SJeff Kirsher } 812adfc5217SJeff Kirsher return 0; 813adfc5217SJeff Kirsher } 814adfc5217SJeff Kirsher 815adfc5217SJeff Kirsher static void 816adfc5217SJeff Kirsher bnx2_free_mem(struct bnx2 *bp) 817adfc5217SJeff Kirsher { 818adfc5217SJeff Kirsher int i; 819adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 820adfc5217SJeff Kirsher 821adfc5217SJeff Kirsher bnx2_free_tx_mem(bp); 822adfc5217SJeff Kirsher bnx2_free_rx_mem(bp); 823adfc5217SJeff Kirsher 824adfc5217SJeff Kirsher for (i = 0; i < bp->ctx_pages; i++) { 825adfc5217SJeff Kirsher if (bp->ctx_blk[i]) { 826adfc5217SJeff Kirsher dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE, 827adfc5217SJeff Kirsher bp->ctx_blk[i], 828adfc5217SJeff Kirsher bp->ctx_blk_mapping[i]); 829adfc5217SJeff Kirsher bp->ctx_blk[i] = NULL; 830adfc5217SJeff Kirsher } 831adfc5217SJeff Kirsher } 832adfc5217SJeff Kirsher if (bnapi->status_blk.msi) { 833adfc5217SJeff Kirsher dma_free_coherent(&bp->pdev->dev, bp->status_stats_size, 834adfc5217SJeff Kirsher bnapi->status_blk.msi, 835adfc5217SJeff Kirsher bp->status_blk_mapping); 836adfc5217SJeff Kirsher bnapi->status_blk.msi = NULL; 837adfc5217SJeff Kirsher bp->stats_blk = NULL; 838adfc5217SJeff Kirsher } 839adfc5217SJeff Kirsher } 840adfc5217SJeff Kirsher 841adfc5217SJeff Kirsher static int 842adfc5217SJeff Kirsher bnx2_alloc_mem(struct bnx2 *bp) 843adfc5217SJeff Kirsher { 844adfc5217SJeff Kirsher int i, status_blk_size, err; 845adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 846adfc5217SJeff Kirsher void *status_blk; 847adfc5217SJeff Kirsher 848adfc5217SJeff Kirsher /* Combine status and statistics blocks into one allocation. */ 849adfc5217SJeff Kirsher status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); 850adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_MSIX_CAP) 851adfc5217SJeff Kirsher status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC * 852adfc5217SJeff Kirsher BNX2_SBLK_MSIX_ALIGN_SIZE); 853adfc5217SJeff Kirsher bp->status_stats_size = status_blk_size + 854adfc5217SJeff Kirsher sizeof(struct statistics_block); 855adfc5217SJeff Kirsher 856adfc5217SJeff Kirsher status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size, 857adfc5217SJeff Kirsher &bp->status_blk_mapping, GFP_KERNEL); 858adfc5217SJeff Kirsher if (status_blk == NULL) 859adfc5217SJeff Kirsher goto alloc_mem_err; 860adfc5217SJeff Kirsher 861adfc5217SJeff Kirsher memset(status_blk, 0, bp->status_stats_size); 862adfc5217SJeff Kirsher 863adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[0]; 864adfc5217SJeff Kirsher bnapi->status_blk.msi = status_blk; 865adfc5217SJeff Kirsher bnapi->hw_tx_cons_ptr = 866adfc5217SJeff Kirsher &bnapi->status_blk.msi->status_tx_quick_consumer_index0; 867adfc5217SJeff Kirsher bnapi->hw_rx_cons_ptr = 868adfc5217SJeff Kirsher &bnapi->status_blk.msi->status_rx_quick_consumer_index0; 869adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_MSIX_CAP) { 870adfc5217SJeff Kirsher for (i = 1; i < bp->irq_nvecs; i++) { 871adfc5217SJeff Kirsher struct status_block_msix *sblk; 872adfc5217SJeff Kirsher 873adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[i]; 874adfc5217SJeff Kirsher 875adfc5217SJeff Kirsher sblk = (void *) (status_blk + 876adfc5217SJeff Kirsher BNX2_SBLK_MSIX_ALIGN_SIZE * i); 877adfc5217SJeff Kirsher bnapi->status_blk.msix = sblk; 878adfc5217SJeff Kirsher bnapi->hw_tx_cons_ptr = 879adfc5217SJeff Kirsher &sblk->status_tx_quick_consumer_index; 880adfc5217SJeff Kirsher bnapi->hw_rx_cons_ptr = 881adfc5217SJeff Kirsher &sblk->status_rx_quick_consumer_index; 882adfc5217SJeff Kirsher bnapi->int_num = i << 24; 883adfc5217SJeff Kirsher } 884adfc5217SJeff Kirsher } 885adfc5217SJeff Kirsher 886adfc5217SJeff Kirsher bp->stats_blk = status_blk + status_blk_size; 887adfc5217SJeff Kirsher 888adfc5217SJeff Kirsher bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; 889adfc5217SJeff Kirsher 890adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 891adfc5217SJeff Kirsher bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE; 892adfc5217SJeff Kirsher if (bp->ctx_pages == 0) 893adfc5217SJeff Kirsher bp->ctx_pages = 1; 894adfc5217SJeff Kirsher for (i = 0; i < bp->ctx_pages; i++) { 895adfc5217SJeff Kirsher bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev, 896adfc5217SJeff Kirsher BCM_PAGE_SIZE, 897adfc5217SJeff Kirsher &bp->ctx_blk_mapping[i], 898adfc5217SJeff Kirsher GFP_KERNEL); 899adfc5217SJeff Kirsher if (bp->ctx_blk[i] == NULL) 900adfc5217SJeff Kirsher goto alloc_mem_err; 901adfc5217SJeff Kirsher } 902adfc5217SJeff Kirsher } 903adfc5217SJeff Kirsher 904adfc5217SJeff Kirsher err = bnx2_alloc_rx_mem(bp); 905adfc5217SJeff Kirsher if (err) 906adfc5217SJeff Kirsher goto alloc_mem_err; 907adfc5217SJeff Kirsher 908adfc5217SJeff Kirsher err = bnx2_alloc_tx_mem(bp); 909adfc5217SJeff Kirsher if (err) 910adfc5217SJeff Kirsher goto alloc_mem_err; 911adfc5217SJeff Kirsher 912adfc5217SJeff Kirsher return 0; 913adfc5217SJeff Kirsher 914adfc5217SJeff Kirsher alloc_mem_err: 915adfc5217SJeff Kirsher bnx2_free_mem(bp); 916adfc5217SJeff Kirsher return -ENOMEM; 917adfc5217SJeff Kirsher } 918adfc5217SJeff Kirsher 919adfc5217SJeff Kirsher static void 920adfc5217SJeff Kirsher bnx2_report_fw_link(struct bnx2 *bp) 921adfc5217SJeff Kirsher { 922adfc5217SJeff Kirsher u32 fw_link_status = 0; 923adfc5217SJeff Kirsher 924adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 925adfc5217SJeff Kirsher return; 926adfc5217SJeff Kirsher 927adfc5217SJeff Kirsher if (bp->link_up) { 928adfc5217SJeff Kirsher u32 bmsr; 929adfc5217SJeff Kirsher 930adfc5217SJeff Kirsher switch (bp->line_speed) { 931adfc5217SJeff Kirsher case SPEED_10: 932adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_HALF) 933adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_10HALF; 934adfc5217SJeff Kirsher else 935adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_10FULL; 936adfc5217SJeff Kirsher break; 937adfc5217SJeff Kirsher case SPEED_100: 938adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_HALF) 939adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_100HALF; 940adfc5217SJeff Kirsher else 941adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_100FULL; 942adfc5217SJeff Kirsher break; 943adfc5217SJeff Kirsher case SPEED_1000: 944adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_HALF) 945adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_1000HALF; 946adfc5217SJeff Kirsher else 947adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_1000FULL; 948adfc5217SJeff Kirsher break; 949adfc5217SJeff Kirsher case SPEED_2500: 950adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_HALF) 951adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_2500HALF; 952adfc5217SJeff Kirsher else 953adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_2500FULL; 954adfc5217SJeff Kirsher break; 955adfc5217SJeff Kirsher } 956adfc5217SJeff Kirsher 957adfc5217SJeff Kirsher fw_link_status |= BNX2_LINK_STATUS_LINK_UP; 958adfc5217SJeff Kirsher 959adfc5217SJeff Kirsher if (bp->autoneg) { 960adfc5217SJeff Kirsher fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED; 961adfc5217SJeff Kirsher 962adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 963adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 964adfc5217SJeff Kirsher 965adfc5217SJeff Kirsher if (!(bmsr & BMSR_ANEGCOMPLETE) || 966adfc5217SJeff Kirsher bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT) 967adfc5217SJeff Kirsher fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET; 968adfc5217SJeff Kirsher else 969adfc5217SJeff Kirsher fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE; 970adfc5217SJeff Kirsher } 971adfc5217SJeff Kirsher } 972adfc5217SJeff Kirsher else 973adfc5217SJeff Kirsher fw_link_status = BNX2_LINK_STATUS_LINK_DOWN; 974adfc5217SJeff Kirsher 975adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_LINK_STATUS, fw_link_status); 976adfc5217SJeff Kirsher } 977adfc5217SJeff Kirsher 978adfc5217SJeff Kirsher static char * 979adfc5217SJeff Kirsher bnx2_xceiver_str(struct bnx2 *bp) 980adfc5217SJeff Kirsher { 981adfc5217SJeff Kirsher return (bp->phy_port == PORT_FIBRE) ? "SerDes" : 982adfc5217SJeff Kirsher ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) ? "Remote Copper" : 983adfc5217SJeff Kirsher "Copper"); 984adfc5217SJeff Kirsher } 985adfc5217SJeff Kirsher 986adfc5217SJeff Kirsher static void 987adfc5217SJeff Kirsher bnx2_report_link(struct bnx2 *bp) 988adfc5217SJeff Kirsher { 989adfc5217SJeff Kirsher if (bp->link_up) { 990adfc5217SJeff Kirsher netif_carrier_on(bp->dev); 991adfc5217SJeff Kirsher netdev_info(bp->dev, "NIC %s Link is Up, %d Mbps %s duplex", 992adfc5217SJeff Kirsher bnx2_xceiver_str(bp), 993adfc5217SJeff Kirsher bp->line_speed, 994adfc5217SJeff Kirsher bp->duplex == DUPLEX_FULL ? "full" : "half"); 995adfc5217SJeff Kirsher 996adfc5217SJeff Kirsher if (bp->flow_ctrl) { 997adfc5217SJeff Kirsher if (bp->flow_ctrl & FLOW_CTRL_RX) { 998adfc5217SJeff Kirsher pr_cont(", receive "); 999adfc5217SJeff Kirsher if (bp->flow_ctrl & FLOW_CTRL_TX) 1000adfc5217SJeff Kirsher pr_cont("& transmit "); 1001adfc5217SJeff Kirsher } 1002adfc5217SJeff Kirsher else { 1003adfc5217SJeff Kirsher pr_cont(", transmit "); 1004adfc5217SJeff Kirsher } 1005adfc5217SJeff Kirsher pr_cont("flow control ON"); 1006adfc5217SJeff Kirsher } 1007adfc5217SJeff Kirsher pr_cont("\n"); 1008adfc5217SJeff Kirsher } else { 1009adfc5217SJeff Kirsher netif_carrier_off(bp->dev); 1010adfc5217SJeff Kirsher netdev_err(bp->dev, "NIC %s Link is Down\n", 1011adfc5217SJeff Kirsher bnx2_xceiver_str(bp)); 1012adfc5217SJeff Kirsher } 1013adfc5217SJeff Kirsher 1014adfc5217SJeff Kirsher bnx2_report_fw_link(bp); 1015adfc5217SJeff Kirsher } 1016adfc5217SJeff Kirsher 1017adfc5217SJeff Kirsher static void 1018adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(struct bnx2 *bp) 1019adfc5217SJeff Kirsher { 1020adfc5217SJeff Kirsher u32 local_adv, remote_adv; 1021adfc5217SJeff Kirsher 1022adfc5217SJeff Kirsher bp->flow_ctrl = 0; 1023adfc5217SJeff Kirsher if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != 1024adfc5217SJeff Kirsher (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { 1025adfc5217SJeff Kirsher 1026adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_FULL) { 1027adfc5217SJeff Kirsher bp->flow_ctrl = bp->req_flow_ctrl; 1028adfc5217SJeff Kirsher } 1029adfc5217SJeff Kirsher return; 1030adfc5217SJeff Kirsher } 1031adfc5217SJeff Kirsher 1032adfc5217SJeff Kirsher if (bp->duplex != DUPLEX_FULL) { 1033adfc5217SJeff Kirsher return; 1034adfc5217SJeff Kirsher } 1035adfc5217SJeff Kirsher 1036adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 1037adfc5217SJeff Kirsher (CHIP_NUM(bp) == CHIP_NUM_5708)) { 1038adfc5217SJeff Kirsher u32 val; 1039adfc5217SJeff Kirsher 1040adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); 1041adfc5217SJeff Kirsher if (val & BCM5708S_1000X_STAT1_TX_PAUSE) 1042adfc5217SJeff Kirsher bp->flow_ctrl |= FLOW_CTRL_TX; 1043adfc5217SJeff Kirsher if (val & BCM5708S_1000X_STAT1_RX_PAUSE) 1044adfc5217SJeff Kirsher bp->flow_ctrl |= FLOW_CTRL_RX; 1045adfc5217SJeff Kirsher return; 1046adfc5217SJeff Kirsher } 1047adfc5217SJeff Kirsher 1048adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &local_adv); 1049adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); 1050adfc5217SJeff Kirsher 1051adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1052adfc5217SJeff Kirsher u32 new_local_adv = 0; 1053adfc5217SJeff Kirsher u32 new_remote_adv = 0; 1054adfc5217SJeff Kirsher 1055adfc5217SJeff Kirsher if (local_adv & ADVERTISE_1000XPAUSE) 1056adfc5217SJeff Kirsher new_local_adv |= ADVERTISE_PAUSE_CAP; 1057adfc5217SJeff Kirsher if (local_adv & ADVERTISE_1000XPSE_ASYM) 1058adfc5217SJeff Kirsher new_local_adv |= ADVERTISE_PAUSE_ASYM; 1059adfc5217SJeff Kirsher if (remote_adv & ADVERTISE_1000XPAUSE) 1060adfc5217SJeff Kirsher new_remote_adv |= ADVERTISE_PAUSE_CAP; 1061adfc5217SJeff Kirsher if (remote_adv & ADVERTISE_1000XPSE_ASYM) 1062adfc5217SJeff Kirsher new_remote_adv |= ADVERTISE_PAUSE_ASYM; 1063adfc5217SJeff Kirsher 1064adfc5217SJeff Kirsher local_adv = new_local_adv; 1065adfc5217SJeff Kirsher remote_adv = new_remote_adv; 1066adfc5217SJeff Kirsher } 1067adfc5217SJeff Kirsher 1068adfc5217SJeff Kirsher /* See Table 28B-3 of 802.3ab-1999 spec. */ 1069adfc5217SJeff Kirsher if (local_adv & ADVERTISE_PAUSE_CAP) { 1070adfc5217SJeff Kirsher if(local_adv & ADVERTISE_PAUSE_ASYM) { 1071adfc5217SJeff Kirsher if (remote_adv & ADVERTISE_PAUSE_CAP) { 1072adfc5217SJeff Kirsher bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; 1073adfc5217SJeff Kirsher } 1074adfc5217SJeff Kirsher else if (remote_adv & ADVERTISE_PAUSE_ASYM) { 1075adfc5217SJeff Kirsher bp->flow_ctrl = FLOW_CTRL_RX; 1076adfc5217SJeff Kirsher } 1077adfc5217SJeff Kirsher } 1078adfc5217SJeff Kirsher else { 1079adfc5217SJeff Kirsher if (remote_adv & ADVERTISE_PAUSE_CAP) { 1080adfc5217SJeff Kirsher bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; 1081adfc5217SJeff Kirsher } 1082adfc5217SJeff Kirsher } 1083adfc5217SJeff Kirsher } 1084adfc5217SJeff Kirsher else if (local_adv & ADVERTISE_PAUSE_ASYM) { 1085adfc5217SJeff Kirsher if ((remote_adv & ADVERTISE_PAUSE_CAP) && 1086adfc5217SJeff Kirsher (remote_adv & ADVERTISE_PAUSE_ASYM)) { 1087adfc5217SJeff Kirsher 1088adfc5217SJeff Kirsher bp->flow_ctrl = FLOW_CTRL_TX; 1089adfc5217SJeff Kirsher } 1090adfc5217SJeff Kirsher } 1091adfc5217SJeff Kirsher } 1092adfc5217SJeff Kirsher 1093adfc5217SJeff Kirsher static int 1094adfc5217SJeff Kirsher bnx2_5709s_linkup(struct bnx2 *bp) 1095adfc5217SJeff Kirsher { 1096adfc5217SJeff Kirsher u32 val, speed; 1097adfc5217SJeff Kirsher 1098adfc5217SJeff Kirsher bp->link_up = 1; 1099adfc5217SJeff Kirsher 1100adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS); 1101adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val); 1102adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1103adfc5217SJeff Kirsher 1104adfc5217SJeff Kirsher if ((bp->autoneg & AUTONEG_SPEED) == 0) { 1105adfc5217SJeff Kirsher bp->line_speed = bp->req_line_speed; 1106adfc5217SJeff Kirsher bp->duplex = bp->req_duplex; 1107adfc5217SJeff Kirsher return 0; 1108adfc5217SJeff Kirsher } 1109adfc5217SJeff Kirsher speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK; 1110adfc5217SJeff Kirsher switch (speed) { 1111adfc5217SJeff Kirsher case MII_BNX2_GP_TOP_AN_SPEED_10: 1112adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1113adfc5217SJeff Kirsher break; 1114adfc5217SJeff Kirsher case MII_BNX2_GP_TOP_AN_SPEED_100: 1115adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1116adfc5217SJeff Kirsher break; 1117adfc5217SJeff Kirsher case MII_BNX2_GP_TOP_AN_SPEED_1G: 1118adfc5217SJeff Kirsher case MII_BNX2_GP_TOP_AN_SPEED_1GKV: 1119adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1120adfc5217SJeff Kirsher break; 1121adfc5217SJeff Kirsher case MII_BNX2_GP_TOP_AN_SPEED_2_5G: 1122adfc5217SJeff Kirsher bp->line_speed = SPEED_2500; 1123adfc5217SJeff Kirsher break; 1124adfc5217SJeff Kirsher } 1125adfc5217SJeff Kirsher if (val & MII_BNX2_GP_TOP_AN_FD) 1126adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1127adfc5217SJeff Kirsher else 1128adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1129adfc5217SJeff Kirsher return 0; 1130adfc5217SJeff Kirsher } 1131adfc5217SJeff Kirsher 1132adfc5217SJeff Kirsher static int 1133adfc5217SJeff Kirsher bnx2_5708s_linkup(struct bnx2 *bp) 1134adfc5217SJeff Kirsher { 1135adfc5217SJeff Kirsher u32 val; 1136adfc5217SJeff Kirsher 1137adfc5217SJeff Kirsher bp->link_up = 1; 1138adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); 1139adfc5217SJeff Kirsher switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) { 1140adfc5217SJeff Kirsher case BCM5708S_1000X_STAT1_SPEED_10: 1141adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1142adfc5217SJeff Kirsher break; 1143adfc5217SJeff Kirsher case BCM5708S_1000X_STAT1_SPEED_100: 1144adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1145adfc5217SJeff Kirsher break; 1146adfc5217SJeff Kirsher case BCM5708S_1000X_STAT1_SPEED_1G: 1147adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1148adfc5217SJeff Kirsher break; 1149adfc5217SJeff Kirsher case BCM5708S_1000X_STAT1_SPEED_2G5: 1150adfc5217SJeff Kirsher bp->line_speed = SPEED_2500; 1151adfc5217SJeff Kirsher break; 1152adfc5217SJeff Kirsher } 1153adfc5217SJeff Kirsher if (val & BCM5708S_1000X_STAT1_FD) 1154adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1155adfc5217SJeff Kirsher else 1156adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1157adfc5217SJeff Kirsher 1158adfc5217SJeff Kirsher return 0; 1159adfc5217SJeff Kirsher } 1160adfc5217SJeff Kirsher 1161adfc5217SJeff Kirsher static int 1162adfc5217SJeff Kirsher bnx2_5706s_linkup(struct bnx2 *bp) 1163adfc5217SJeff Kirsher { 1164adfc5217SJeff Kirsher u32 bmcr, local_adv, remote_adv, common; 1165adfc5217SJeff Kirsher 1166adfc5217SJeff Kirsher bp->link_up = 1; 1167adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1168adfc5217SJeff Kirsher 1169adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1170adfc5217SJeff Kirsher if (bmcr & BMCR_FULLDPLX) { 1171adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1172adfc5217SJeff Kirsher } 1173adfc5217SJeff Kirsher else { 1174adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1175adfc5217SJeff Kirsher } 1176adfc5217SJeff Kirsher 1177adfc5217SJeff Kirsher if (!(bmcr & BMCR_ANENABLE)) { 1178adfc5217SJeff Kirsher return 0; 1179adfc5217SJeff Kirsher } 1180adfc5217SJeff Kirsher 1181adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &local_adv); 1182adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); 1183adfc5217SJeff Kirsher 1184adfc5217SJeff Kirsher common = local_adv & remote_adv; 1185adfc5217SJeff Kirsher if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) { 1186adfc5217SJeff Kirsher 1187adfc5217SJeff Kirsher if (common & ADVERTISE_1000XFULL) { 1188adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1189adfc5217SJeff Kirsher } 1190adfc5217SJeff Kirsher else { 1191adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1192adfc5217SJeff Kirsher } 1193adfc5217SJeff Kirsher } 1194adfc5217SJeff Kirsher 1195adfc5217SJeff Kirsher return 0; 1196adfc5217SJeff Kirsher } 1197adfc5217SJeff Kirsher 1198adfc5217SJeff Kirsher static int 1199adfc5217SJeff Kirsher bnx2_copper_linkup(struct bnx2 *bp) 1200adfc5217SJeff Kirsher { 1201adfc5217SJeff Kirsher u32 bmcr; 1202adfc5217SJeff Kirsher 1203adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1204adfc5217SJeff Kirsher if (bmcr & BMCR_ANENABLE) { 1205adfc5217SJeff Kirsher u32 local_adv, remote_adv, common; 1206adfc5217SJeff Kirsher 1207adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_CTRL1000, &local_adv); 1208adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_STAT1000, &remote_adv); 1209adfc5217SJeff Kirsher 1210adfc5217SJeff Kirsher common = local_adv & (remote_adv >> 2); 1211adfc5217SJeff Kirsher if (common & ADVERTISE_1000FULL) { 1212adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1213adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1214adfc5217SJeff Kirsher } 1215adfc5217SJeff Kirsher else if (common & ADVERTISE_1000HALF) { 1216adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1217adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1218adfc5217SJeff Kirsher } 1219adfc5217SJeff Kirsher else { 1220adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &local_adv); 1221adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_lpa, &remote_adv); 1222adfc5217SJeff Kirsher 1223adfc5217SJeff Kirsher common = local_adv & remote_adv; 1224adfc5217SJeff Kirsher if (common & ADVERTISE_100FULL) { 1225adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1226adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1227adfc5217SJeff Kirsher } 1228adfc5217SJeff Kirsher else if (common & ADVERTISE_100HALF) { 1229adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1230adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1231adfc5217SJeff Kirsher } 1232adfc5217SJeff Kirsher else if (common & ADVERTISE_10FULL) { 1233adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1234adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1235adfc5217SJeff Kirsher } 1236adfc5217SJeff Kirsher else if (common & ADVERTISE_10HALF) { 1237adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1238adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1239adfc5217SJeff Kirsher } 1240adfc5217SJeff Kirsher else { 1241adfc5217SJeff Kirsher bp->line_speed = 0; 1242adfc5217SJeff Kirsher bp->link_up = 0; 1243adfc5217SJeff Kirsher } 1244adfc5217SJeff Kirsher } 1245adfc5217SJeff Kirsher } 1246adfc5217SJeff Kirsher else { 1247adfc5217SJeff Kirsher if (bmcr & BMCR_SPEED100) { 1248adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1249adfc5217SJeff Kirsher } 1250adfc5217SJeff Kirsher else { 1251adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1252adfc5217SJeff Kirsher } 1253adfc5217SJeff Kirsher if (bmcr & BMCR_FULLDPLX) { 1254adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1255adfc5217SJeff Kirsher } 1256adfc5217SJeff Kirsher else { 1257adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1258adfc5217SJeff Kirsher } 1259adfc5217SJeff Kirsher } 1260adfc5217SJeff Kirsher 1261adfc5217SJeff Kirsher return 0; 1262adfc5217SJeff Kirsher } 1263adfc5217SJeff Kirsher 1264adfc5217SJeff Kirsher static void 1265adfc5217SJeff Kirsher bnx2_init_rx_context(struct bnx2 *bp, u32 cid) 1266adfc5217SJeff Kirsher { 1267adfc5217SJeff Kirsher u32 val, rx_cid_addr = GET_CID_ADDR(cid); 1268adfc5217SJeff Kirsher 1269adfc5217SJeff Kirsher val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; 1270adfc5217SJeff Kirsher val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; 1271adfc5217SJeff Kirsher val |= 0x02 << 8; 1272adfc5217SJeff Kirsher 1273adfc5217SJeff Kirsher if (bp->flow_ctrl & FLOW_CTRL_TX) 1274adfc5217SJeff Kirsher val |= BNX2_L2CTX_FLOW_CTRL_ENABLE; 1275adfc5217SJeff Kirsher 1276adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val); 1277adfc5217SJeff Kirsher } 1278adfc5217SJeff Kirsher 1279adfc5217SJeff Kirsher static void 1280adfc5217SJeff Kirsher bnx2_init_all_rx_contexts(struct bnx2 *bp) 1281adfc5217SJeff Kirsher { 1282adfc5217SJeff Kirsher int i; 1283adfc5217SJeff Kirsher u32 cid; 1284adfc5217SJeff Kirsher 1285adfc5217SJeff Kirsher for (i = 0, cid = RX_CID; i < bp->num_rx_rings; i++, cid++) { 1286adfc5217SJeff Kirsher if (i == 1) 1287adfc5217SJeff Kirsher cid = RX_RSS_CID; 1288adfc5217SJeff Kirsher bnx2_init_rx_context(bp, cid); 1289adfc5217SJeff Kirsher } 1290adfc5217SJeff Kirsher } 1291adfc5217SJeff Kirsher 1292adfc5217SJeff Kirsher static void 1293adfc5217SJeff Kirsher bnx2_set_mac_link(struct bnx2 *bp) 1294adfc5217SJeff Kirsher { 1295adfc5217SJeff Kirsher u32 val; 1296adfc5217SJeff Kirsher 1297adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620); 1298adfc5217SJeff Kirsher if (bp->link_up && (bp->line_speed == SPEED_1000) && 1299adfc5217SJeff Kirsher (bp->duplex == DUPLEX_HALF)) { 1300adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff); 1301adfc5217SJeff Kirsher } 1302adfc5217SJeff Kirsher 1303adfc5217SJeff Kirsher /* Configure the EMAC mode register. */ 1304adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_EMAC_MODE); 1305adfc5217SJeff Kirsher 1306adfc5217SJeff Kirsher val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | 1307adfc5217SJeff Kirsher BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | 1308adfc5217SJeff Kirsher BNX2_EMAC_MODE_25G_MODE); 1309adfc5217SJeff Kirsher 1310adfc5217SJeff Kirsher if (bp->link_up) { 1311adfc5217SJeff Kirsher switch (bp->line_speed) { 1312adfc5217SJeff Kirsher case SPEED_10: 1313adfc5217SJeff Kirsher if (CHIP_NUM(bp) != CHIP_NUM_5706) { 1314adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_MII_10M; 1315adfc5217SJeff Kirsher break; 1316adfc5217SJeff Kirsher } 1317adfc5217SJeff Kirsher /* fall through */ 1318adfc5217SJeff Kirsher case SPEED_100: 1319adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_MII; 1320adfc5217SJeff Kirsher break; 1321adfc5217SJeff Kirsher case SPEED_2500: 1322adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_25G_MODE; 1323adfc5217SJeff Kirsher /* fall through */ 1324adfc5217SJeff Kirsher case SPEED_1000: 1325adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_GMII; 1326adfc5217SJeff Kirsher break; 1327adfc5217SJeff Kirsher } 1328adfc5217SJeff Kirsher } 1329adfc5217SJeff Kirsher else { 1330adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_GMII; 1331adfc5217SJeff Kirsher } 1332adfc5217SJeff Kirsher 1333adfc5217SJeff Kirsher /* Set the MAC to operate in the appropriate duplex mode. */ 1334adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_HALF) 1335adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_HALF_DUPLEX; 1336adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MODE, val); 1337adfc5217SJeff Kirsher 1338adfc5217SJeff Kirsher /* Enable/disable rx PAUSE. */ 1339adfc5217SJeff Kirsher bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN; 1340adfc5217SJeff Kirsher 1341adfc5217SJeff Kirsher if (bp->flow_ctrl & FLOW_CTRL_RX) 1342adfc5217SJeff Kirsher bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN; 1343adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode); 1344adfc5217SJeff Kirsher 1345adfc5217SJeff Kirsher /* Enable/disable tx PAUSE. */ 1346adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_EMAC_TX_MODE); 1347adfc5217SJeff Kirsher val &= ~BNX2_EMAC_TX_MODE_FLOW_EN; 1348adfc5217SJeff Kirsher 1349adfc5217SJeff Kirsher if (bp->flow_ctrl & FLOW_CTRL_TX) 1350adfc5217SJeff Kirsher val |= BNX2_EMAC_TX_MODE_FLOW_EN; 1351adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_TX_MODE, val); 1352adfc5217SJeff Kirsher 1353adfc5217SJeff Kirsher /* Acknowledge the interrupt. */ 1354adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE); 1355adfc5217SJeff Kirsher 1356adfc5217SJeff Kirsher bnx2_init_all_rx_contexts(bp); 1357adfc5217SJeff Kirsher } 1358adfc5217SJeff Kirsher 1359adfc5217SJeff Kirsher static void 1360adfc5217SJeff Kirsher bnx2_enable_bmsr1(struct bnx2 *bp) 1361adfc5217SJeff Kirsher { 1362adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 1363adfc5217SJeff Kirsher (CHIP_NUM(bp) == CHIP_NUM_5709)) 1364adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1365adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_GP_STATUS); 1366adfc5217SJeff Kirsher } 1367adfc5217SJeff Kirsher 1368adfc5217SJeff Kirsher static void 1369adfc5217SJeff Kirsher bnx2_disable_bmsr1(struct bnx2 *bp) 1370adfc5217SJeff Kirsher { 1371adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 1372adfc5217SJeff Kirsher (CHIP_NUM(bp) == CHIP_NUM_5709)) 1373adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1374adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1375adfc5217SJeff Kirsher } 1376adfc5217SJeff Kirsher 1377adfc5217SJeff Kirsher static int 1378adfc5217SJeff Kirsher bnx2_test_and_enable_2g5(struct bnx2 *bp) 1379adfc5217SJeff Kirsher { 1380adfc5217SJeff Kirsher u32 up1; 1381adfc5217SJeff Kirsher int ret = 1; 1382adfc5217SJeff Kirsher 1383adfc5217SJeff Kirsher if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) 1384adfc5217SJeff Kirsher return 0; 1385adfc5217SJeff Kirsher 1386adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) 1387adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_2500baseX_Full; 1388adfc5217SJeff Kirsher 1389adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 1390adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); 1391adfc5217SJeff Kirsher 1392adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_up1, &up1); 1393adfc5217SJeff Kirsher if (!(up1 & BCM5708S_UP1_2G5)) { 1394adfc5217SJeff Kirsher up1 |= BCM5708S_UP1_2G5; 1395adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_up1, up1); 1396adfc5217SJeff Kirsher ret = 0; 1397adfc5217SJeff Kirsher } 1398adfc5217SJeff Kirsher 1399adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 1400adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1401adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1402adfc5217SJeff Kirsher 1403adfc5217SJeff Kirsher return ret; 1404adfc5217SJeff Kirsher } 1405adfc5217SJeff Kirsher 1406adfc5217SJeff Kirsher static int 1407adfc5217SJeff Kirsher bnx2_test_and_disable_2g5(struct bnx2 *bp) 1408adfc5217SJeff Kirsher { 1409adfc5217SJeff Kirsher u32 up1; 1410adfc5217SJeff Kirsher int ret = 0; 1411adfc5217SJeff Kirsher 1412adfc5217SJeff Kirsher if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) 1413adfc5217SJeff Kirsher return 0; 1414adfc5217SJeff Kirsher 1415adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 1416adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); 1417adfc5217SJeff Kirsher 1418adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_up1, &up1); 1419adfc5217SJeff Kirsher if (up1 & BCM5708S_UP1_2G5) { 1420adfc5217SJeff Kirsher up1 &= ~BCM5708S_UP1_2G5; 1421adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_up1, up1); 1422adfc5217SJeff Kirsher ret = 1; 1423adfc5217SJeff Kirsher } 1424adfc5217SJeff Kirsher 1425adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 1426adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1427adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1428adfc5217SJeff Kirsher 1429adfc5217SJeff Kirsher return ret; 1430adfc5217SJeff Kirsher } 1431adfc5217SJeff Kirsher 1432adfc5217SJeff Kirsher static void 1433adfc5217SJeff Kirsher bnx2_enable_forced_2g5(struct bnx2 *bp) 1434adfc5217SJeff Kirsher { 1435adfc5217SJeff Kirsher u32 uninitialized_var(bmcr); 1436adfc5217SJeff Kirsher int err; 1437adfc5217SJeff Kirsher 1438adfc5217SJeff Kirsher if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) 1439adfc5217SJeff Kirsher return; 1440adfc5217SJeff Kirsher 1441adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 1442adfc5217SJeff Kirsher u32 val; 1443adfc5217SJeff Kirsher 1444adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1445adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_SERDES_DIG); 1446adfc5217SJeff Kirsher if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) { 1447adfc5217SJeff Kirsher val &= ~MII_BNX2_SD_MISC1_FORCE_MSK; 1448adfc5217SJeff Kirsher val |= MII_BNX2_SD_MISC1_FORCE | 1449adfc5217SJeff Kirsher MII_BNX2_SD_MISC1_FORCE_2_5G; 1450adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); 1451adfc5217SJeff Kirsher } 1452adfc5217SJeff Kirsher 1453adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1454adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1455adfc5217SJeff Kirsher err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1456adfc5217SJeff Kirsher 1457adfc5217SJeff Kirsher } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { 1458adfc5217SJeff Kirsher err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1459adfc5217SJeff Kirsher if (!err) 1460adfc5217SJeff Kirsher bmcr |= BCM5708S_BMCR_FORCE_2500; 1461adfc5217SJeff Kirsher } else { 1462adfc5217SJeff Kirsher return; 1463adfc5217SJeff Kirsher } 1464adfc5217SJeff Kirsher 1465adfc5217SJeff Kirsher if (err) 1466adfc5217SJeff Kirsher return; 1467adfc5217SJeff Kirsher 1468adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) { 1469adfc5217SJeff Kirsher bmcr &= ~BMCR_ANENABLE; 1470adfc5217SJeff Kirsher if (bp->req_duplex == DUPLEX_FULL) 1471adfc5217SJeff Kirsher bmcr |= BMCR_FULLDPLX; 1472adfc5217SJeff Kirsher } 1473adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr); 1474adfc5217SJeff Kirsher } 1475adfc5217SJeff Kirsher 1476adfc5217SJeff Kirsher static void 1477adfc5217SJeff Kirsher bnx2_disable_forced_2g5(struct bnx2 *bp) 1478adfc5217SJeff Kirsher { 1479adfc5217SJeff Kirsher u32 uninitialized_var(bmcr); 1480adfc5217SJeff Kirsher int err; 1481adfc5217SJeff Kirsher 1482adfc5217SJeff Kirsher if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) 1483adfc5217SJeff Kirsher return; 1484adfc5217SJeff Kirsher 1485adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 1486adfc5217SJeff Kirsher u32 val; 1487adfc5217SJeff Kirsher 1488adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1489adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_SERDES_DIG); 1490adfc5217SJeff Kirsher if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) { 1491adfc5217SJeff Kirsher val &= ~MII_BNX2_SD_MISC1_FORCE; 1492adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val); 1493adfc5217SJeff Kirsher } 1494adfc5217SJeff Kirsher 1495adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, 1496adfc5217SJeff Kirsher MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 1497adfc5217SJeff Kirsher err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1498adfc5217SJeff Kirsher 1499adfc5217SJeff Kirsher } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { 1500adfc5217SJeff Kirsher err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1501adfc5217SJeff Kirsher if (!err) 1502adfc5217SJeff Kirsher bmcr &= ~BCM5708S_BMCR_FORCE_2500; 1503adfc5217SJeff Kirsher } else { 1504adfc5217SJeff Kirsher return; 1505adfc5217SJeff Kirsher } 1506adfc5217SJeff Kirsher 1507adfc5217SJeff Kirsher if (err) 1508adfc5217SJeff Kirsher return; 1509adfc5217SJeff Kirsher 1510adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) 1511adfc5217SJeff Kirsher bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART; 1512adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr); 1513adfc5217SJeff Kirsher } 1514adfc5217SJeff Kirsher 1515adfc5217SJeff Kirsher static void 1516adfc5217SJeff Kirsher bnx2_5706s_force_link_dn(struct bnx2 *bp, int start) 1517adfc5217SJeff Kirsher { 1518adfc5217SJeff Kirsher u32 val; 1519adfc5217SJeff Kirsher 1520adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_SERDES_CTL); 1521adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val); 1522adfc5217SJeff Kirsher if (start) 1523adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val & 0xff0f); 1524adfc5217SJeff Kirsher else 1525adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val | 0xc0); 1526adfc5217SJeff Kirsher } 1527adfc5217SJeff Kirsher 1528adfc5217SJeff Kirsher static int 1529adfc5217SJeff Kirsher bnx2_set_link(struct bnx2 *bp) 1530adfc5217SJeff Kirsher { 1531adfc5217SJeff Kirsher u32 bmsr; 1532adfc5217SJeff Kirsher u8 link_up; 1533adfc5217SJeff Kirsher 1534adfc5217SJeff Kirsher if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) { 1535adfc5217SJeff Kirsher bp->link_up = 1; 1536adfc5217SJeff Kirsher return 0; 1537adfc5217SJeff Kirsher } 1538adfc5217SJeff Kirsher 1539adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 1540adfc5217SJeff Kirsher return 0; 1541adfc5217SJeff Kirsher 1542adfc5217SJeff Kirsher link_up = bp->link_up; 1543adfc5217SJeff Kirsher 1544adfc5217SJeff Kirsher bnx2_enable_bmsr1(bp); 1545adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); 1546adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); 1547adfc5217SJeff Kirsher bnx2_disable_bmsr1(bp); 1548adfc5217SJeff Kirsher 1549adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 1550adfc5217SJeff Kirsher (CHIP_NUM(bp) == CHIP_NUM_5706)) { 1551adfc5217SJeff Kirsher u32 val, an_dbg; 1552adfc5217SJeff Kirsher 1553adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { 1554adfc5217SJeff Kirsher bnx2_5706s_force_link_dn(bp, 0); 1555adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; 1556adfc5217SJeff Kirsher } 1557adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_EMAC_STATUS); 1558adfc5217SJeff Kirsher 1559adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); 1560adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); 1561adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); 1562adfc5217SJeff Kirsher 1563adfc5217SJeff Kirsher if ((val & BNX2_EMAC_STATUS_LINK) && 1564adfc5217SJeff Kirsher !(an_dbg & MISC_SHDW_AN_DBG_NOSYNC)) 1565adfc5217SJeff Kirsher bmsr |= BMSR_LSTATUS; 1566adfc5217SJeff Kirsher else 1567adfc5217SJeff Kirsher bmsr &= ~BMSR_LSTATUS; 1568adfc5217SJeff Kirsher } 1569adfc5217SJeff Kirsher 1570adfc5217SJeff Kirsher if (bmsr & BMSR_LSTATUS) { 1571adfc5217SJeff Kirsher bp->link_up = 1; 1572adfc5217SJeff Kirsher 1573adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1574adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706) 1575adfc5217SJeff Kirsher bnx2_5706s_linkup(bp); 1576adfc5217SJeff Kirsher else if (CHIP_NUM(bp) == CHIP_NUM_5708) 1577adfc5217SJeff Kirsher bnx2_5708s_linkup(bp); 1578adfc5217SJeff Kirsher else if (CHIP_NUM(bp) == CHIP_NUM_5709) 1579adfc5217SJeff Kirsher bnx2_5709s_linkup(bp); 1580adfc5217SJeff Kirsher } 1581adfc5217SJeff Kirsher else { 1582adfc5217SJeff Kirsher bnx2_copper_linkup(bp); 1583adfc5217SJeff Kirsher } 1584adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 1585adfc5217SJeff Kirsher } 1586adfc5217SJeff Kirsher else { 1587adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 1588adfc5217SJeff Kirsher (bp->autoneg & AUTONEG_SPEED)) 1589adfc5217SJeff Kirsher bnx2_disable_forced_2g5(bp); 1590adfc5217SJeff Kirsher 1591adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT) { 1592adfc5217SJeff Kirsher u32 bmcr; 1593adfc5217SJeff Kirsher 1594adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1595adfc5217SJeff Kirsher bmcr |= BMCR_ANENABLE; 1596adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr); 1597adfc5217SJeff Kirsher 1598adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT; 1599adfc5217SJeff Kirsher } 1600adfc5217SJeff Kirsher bp->link_up = 0; 1601adfc5217SJeff Kirsher } 1602adfc5217SJeff Kirsher 1603adfc5217SJeff Kirsher if (bp->link_up != link_up) { 1604adfc5217SJeff Kirsher bnx2_report_link(bp); 1605adfc5217SJeff Kirsher } 1606adfc5217SJeff Kirsher 1607adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 1608adfc5217SJeff Kirsher 1609adfc5217SJeff Kirsher return 0; 1610adfc5217SJeff Kirsher } 1611adfc5217SJeff Kirsher 1612adfc5217SJeff Kirsher static int 1613adfc5217SJeff Kirsher bnx2_reset_phy(struct bnx2 *bp) 1614adfc5217SJeff Kirsher { 1615adfc5217SJeff Kirsher int i; 1616adfc5217SJeff Kirsher u32 reg; 1617adfc5217SJeff Kirsher 1618adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET); 1619adfc5217SJeff Kirsher 1620adfc5217SJeff Kirsher #define PHY_RESET_MAX_WAIT 100 1621adfc5217SJeff Kirsher for (i = 0; i < PHY_RESET_MAX_WAIT; i++) { 1622adfc5217SJeff Kirsher udelay(10); 1623adfc5217SJeff Kirsher 1624adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, ®); 1625adfc5217SJeff Kirsher if (!(reg & BMCR_RESET)) { 1626adfc5217SJeff Kirsher udelay(20); 1627adfc5217SJeff Kirsher break; 1628adfc5217SJeff Kirsher } 1629adfc5217SJeff Kirsher } 1630adfc5217SJeff Kirsher if (i == PHY_RESET_MAX_WAIT) { 1631adfc5217SJeff Kirsher return -EBUSY; 1632adfc5217SJeff Kirsher } 1633adfc5217SJeff Kirsher return 0; 1634adfc5217SJeff Kirsher } 1635adfc5217SJeff Kirsher 1636adfc5217SJeff Kirsher static u32 1637adfc5217SJeff Kirsher bnx2_phy_get_pause_adv(struct bnx2 *bp) 1638adfc5217SJeff Kirsher { 1639adfc5217SJeff Kirsher u32 adv = 0; 1640adfc5217SJeff Kirsher 1641adfc5217SJeff Kirsher if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) == 1642adfc5217SJeff Kirsher (FLOW_CTRL_RX | FLOW_CTRL_TX)) { 1643adfc5217SJeff Kirsher 1644adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1645adfc5217SJeff Kirsher adv = ADVERTISE_1000XPAUSE; 1646adfc5217SJeff Kirsher } 1647adfc5217SJeff Kirsher else { 1648adfc5217SJeff Kirsher adv = ADVERTISE_PAUSE_CAP; 1649adfc5217SJeff Kirsher } 1650adfc5217SJeff Kirsher } 1651adfc5217SJeff Kirsher else if (bp->req_flow_ctrl & FLOW_CTRL_TX) { 1652adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1653adfc5217SJeff Kirsher adv = ADVERTISE_1000XPSE_ASYM; 1654adfc5217SJeff Kirsher } 1655adfc5217SJeff Kirsher else { 1656adfc5217SJeff Kirsher adv = ADVERTISE_PAUSE_ASYM; 1657adfc5217SJeff Kirsher } 1658adfc5217SJeff Kirsher } 1659adfc5217SJeff Kirsher else if (bp->req_flow_ctrl & FLOW_CTRL_RX) { 1660adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1661adfc5217SJeff Kirsher adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; 1662adfc5217SJeff Kirsher } 1663adfc5217SJeff Kirsher else { 1664adfc5217SJeff Kirsher adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; 1665adfc5217SJeff Kirsher } 1666adfc5217SJeff Kirsher } 1667adfc5217SJeff Kirsher return adv; 1668adfc5217SJeff Kirsher } 1669adfc5217SJeff Kirsher 1670adfc5217SJeff Kirsher static int bnx2_fw_sync(struct bnx2 *, u32, int, int); 1671adfc5217SJeff Kirsher 1672adfc5217SJeff Kirsher static int 1673adfc5217SJeff Kirsher bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) 1674adfc5217SJeff Kirsher __releases(&bp->phy_lock) 1675adfc5217SJeff Kirsher __acquires(&bp->phy_lock) 1676adfc5217SJeff Kirsher { 1677adfc5217SJeff Kirsher u32 speed_arg = 0, pause_adv; 1678adfc5217SJeff Kirsher 1679adfc5217SJeff Kirsher pause_adv = bnx2_phy_get_pause_adv(bp); 1680adfc5217SJeff Kirsher 1681adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) { 1682adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG; 1683adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_10baseT_Half) 1684adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF; 1685adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_10baseT_Full) 1686adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL; 1687adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_100baseT_Half) 1688adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF; 1689adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_100baseT_Full) 1690adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL; 1691adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_1000baseT_Full) 1692adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL; 1693adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_2500baseX_Full) 1694adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; 1695adfc5217SJeff Kirsher } else { 1696adfc5217SJeff Kirsher if (bp->req_line_speed == SPEED_2500) 1697adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; 1698adfc5217SJeff Kirsher else if (bp->req_line_speed == SPEED_1000) 1699adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL; 1700adfc5217SJeff Kirsher else if (bp->req_line_speed == SPEED_100) { 1701adfc5217SJeff Kirsher if (bp->req_duplex == DUPLEX_FULL) 1702adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL; 1703adfc5217SJeff Kirsher else 1704adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF; 1705adfc5217SJeff Kirsher } else if (bp->req_line_speed == SPEED_10) { 1706adfc5217SJeff Kirsher if (bp->req_duplex == DUPLEX_FULL) 1707adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL; 1708adfc5217SJeff Kirsher else 1709adfc5217SJeff Kirsher speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF; 1710adfc5217SJeff Kirsher } 1711adfc5217SJeff Kirsher } 1712adfc5217SJeff Kirsher 1713adfc5217SJeff Kirsher if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP)) 1714adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE; 1715adfc5217SJeff Kirsher if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_PAUSE_ASYM)) 1716adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE; 1717adfc5217SJeff Kirsher 1718adfc5217SJeff Kirsher if (port == PORT_TP) 1719adfc5217SJeff Kirsher speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE | 1720adfc5217SJeff Kirsher BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED; 1721adfc5217SJeff Kirsher 1722adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg); 1723adfc5217SJeff Kirsher 1724adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 1725adfc5217SJeff Kirsher bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 1, 0); 1726adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 1727adfc5217SJeff Kirsher 1728adfc5217SJeff Kirsher return 0; 1729adfc5217SJeff Kirsher } 1730adfc5217SJeff Kirsher 1731adfc5217SJeff Kirsher static int 1732adfc5217SJeff Kirsher bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port) 1733adfc5217SJeff Kirsher __releases(&bp->phy_lock) 1734adfc5217SJeff Kirsher __acquires(&bp->phy_lock) 1735adfc5217SJeff Kirsher { 1736adfc5217SJeff Kirsher u32 adv, bmcr; 1737adfc5217SJeff Kirsher u32 new_adv = 0; 1738adfc5217SJeff Kirsher 1739adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 1740adfc5217SJeff Kirsher return bnx2_setup_remote_phy(bp, port); 1741adfc5217SJeff Kirsher 1742adfc5217SJeff Kirsher if (!(bp->autoneg & AUTONEG_SPEED)) { 1743adfc5217SJeff Kirsher u32 new_bmcr; 1744adfc5217SJeff Kirsher int force_link_down = 0; 1745adfc5217SJeff Kirsher 1746adfc5217SJeff Kirsher if (bp->req_line_speed == SPEED_2500) { 1747adfc5217SJeff Kirsher if (!bnx2_test_and_enable_2g5(bp)) 1748adfc5217SJeff Kirsher force_link_down = 1; 1749adfc5217SJeff Kirsher } else if (bp->req_line_speed == SPEED_1000) { 1750adfc5217SJeff Kirsher if (bnx2_test_and_disable_2g5(bp)) 1751adfc5217SJeff Kirsher force_link_down = 1; 1752adfc5217SJeff Kirsher } 1753adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &adv); 1754adfc5217SJeff Kirsher adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); 1755adfc5217SJeff Kirsher 1756adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1757adfc5217SJeff Kirsher new_bmcr = bmcr & ~BMCR_ANENABLE; 1758adfc5217SJeff Kirsher new_bmcr |= BMCR_SPEED1000; 1759adfc5217SJeff Kirsher 1760adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 1761adfc5217SJeff Kirsher if (bp->req_line_speed == SPEED_2500) 1762adfc5217SJeff Kirsher bnx2_enable_forced_2g5(bp); 1763adfc5217SJeff Kirsher else if (bp->req_line_speed == SPEED_1000) { 1764adfc5217SJeff Kirsher bnx2_disable_forced_2g5(bp); 1765adfc5217SJeff Kirsher new_bmcr &= ~0x2000; 1766adfc5217SJeff Kirsher } 1767adfc5217SJeff Kirsher 1768adfc5217SJeff Kirsher } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { 1769adfc5217SJeff Kirsher if (bp->req_line_speed == SPEED_2500) 1770adfc5217SJeff Kirsher new_bmcr |= BCM5708S_BMCR_FORCE_2500; 1771adfc5217SJeff Kirsher else 1772adfc5217SJeff Kirsher new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500; 1773adfc5217SJeff Kirsher } 1774adfc5217SJeff Kirsher 1775adfc5217SJeff Kirsher if (bp->req_duplex == DUPLEX_FULL) { 1776adfc5217SJeff Kirsher adv |= ADVERTISE_1000XFULL; 1777adfc5217SJeff Kirsher new_bmcr |= BMCR_FULLDPLX; 1778adfc5217SJeff Kirsher } 1779adfc5217SJeff Kirsher else { 1780adfc5217SJeff Kirsher adv |= ADVERTISE_1000XHALF; 1781adfc5217SJeff Kirsher new_bmcr &= ~BMCR_FULLDPLX; 1782adfc5217SJeff Kirsher } 1783adfc5217SJeff Kirsher if ((new_bmcr != bmcr) || (force_link_down)) { 1784adfc5217SJeff Kirsher /* Force a link down visible on the other side */ 1785adfc5217SJeff Kirsher if (bp->link_up) { 1786adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_adv, adv & 1787adfc5217SJeff Kirsher ~(ADVERTISE_1000XFULL | 1788adfc5217SJeff Kirsher ADVERTISE_1000XHALF)); 1789adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr | 1790adfc5217SJeff Kirsher BMCR_ANRESTART | BMCR_ANENABLE); 1791adfc5217SJeff Kirsher 1792adfc5217SJeff Kirsher bp->link_up = 0; 1793adfc5217SJeff Kirsher netif_carrier_off(bp->dev); 1794adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); 1795adfc5217SJeff Kirsher bnx2_report_link(bp); 1796adfc5217SJeff Kirsher } 1797adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_adv, adv); 1798adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); 1799adfc5217SJeff Kirsher } else { 1800adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 1801adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 1802adfc5217SJeff Kirsher } 1803adfc5217SJeff Kirsher return 0; 1804adfc5217SJeff Kirsher } 1805adfc5217SJeff Kirsher 1806adfc5217SJeff Kirsher bnx2_test_and_enable_2g5(bp); 1807adfc5217SJeff Kirsher 1808adfc5217SJeff Kirsher if (bp->advertising & ADVERTISED_1000baseT_Full) 1809adfc5217SJeff Kirsher new_adv |= ADVERTISE_1000XFULL; 1810adfc5217SJeff Kirsher 1811adfc5217SJeff Kirsher new_adv |= bnx2_phy_get_pause_adv(bp); 1812adfc5217SJeff Kirsher 1813adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &adv); 1814adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 1815adfc5217SJeff Kirsher 1816adfc5217SJeff Kirsher bp->serdes_an_pending = 0; 1817adfc5217SJeff Kirsher if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { 1818adfc5217SJeff Kirsher /* Force a link down visible on the other side */ 1819adfc5217SJeff Kirsher if (bp->link_up) { 1820adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); 1821adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 1822adfc5217SJeff Kirsher msleep(20); 1823adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 1824adfc5217SJeff Kirsher } 1825adfc5217SJeff Kirsher 1826adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_adv, new_adv); 1827adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | 1828adfc5217SJeff Kirsher BMCR_ANENABLE); 1829adfc5217SJeff Kirsher /* Speed up link-up time when the link partner 1830adfc5217SJeff Kirsher * does not autonegotiate which is very common 1831adfc5217SJeff Kirsher * in blade servers. Some blade servers use 1832adfc5217SJeff Kirsher * IPMI for kerboard input and it's important 1833adfc5217SJeff Kirsher * to minimize link disruptions. Autoneg. involves 1834adfc5217SJeff Kirsher * exchanging base pages plus 3 next pages and 1835adfc5217SJeff Kirsher * normally completes in about 120 msec. 1836adfc5217SJeff Kirsher */ 1837adfc5217SJeff Kirsher bp->current_interval = BNX2_SERDES_AN_TIMEOUT; 1838adfc5217SJeff Kirsher bp->serdes_an_pending = 1; 1839adfc5217SJeff Kirsher mod_timer(&bp->timer, jiffies + bp->current_interval); 1840adfc5217SJeff Kirsher } else { 1841adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 1842adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 1843adfc5217SJeff Kirsher } 1844adfc5217SJeff Kirsher 1845adfc5217SJeff Kirsher return 0; 1846adfc5217SJeff Kirsher } 1847adfc5217SJeff Kirsher 1848adfc5217SJeff Kirsher #define ETHTOOL_ALL_FIBRE_SPEED \ 1849adfc5217SJeff Kirsher (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) ? \ 1850adfc5217SJeff Kirsher (ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\ 1851adfc5217SJeff Kirsher (ADVERTISED_1000baseT_Full) 1852adfc5217SJeff Kirsher 1853adfc5217SJeff Kirsher #define ETHTOOL_ALL_COPPER_SPEED \ 1854adfc5217SJeff Kirsher (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ 1855adfc5217SJeff Kirsher ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ 1856adfc5217SJeff Kirsher ADVERTISED_1000baseT_Full) 1857adfc5217SJeff Kirsher 1858adfc5217SJeff Kirsher #define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \ 1859adfc5217SJeff Kirsher ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA) 1860adfc5217SJeff Kirsher 1861adfc5217SJeff Kirsher #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) 1862adfc5217SJeff Kirsher 1863adfc5217SJeff Kirsher static void 1864adfc5217SJeff Kirsher bnx2_set_default_remote_link(struct bnx2 *bp) 1865adfc5217SJeff Kirsher { 1866adfc5217SJeff Kirsher u32 link; 1867adfc5217SJeff Kirsher 1868adfc5217SJeff Kirsher if (bp->phy_port == PORT_TP) 1869adfc5217SJeff Kirsher link = bnx2_shmem_rd(bp, BNX2_RPHY_COPPER_LINK); 1870adfc5217SJeff Kirsher else 1871adfc5217SJeff Kirsher link = bnx2_shmem_rd(bp, BNX2_RPHY_SERDES_LINK); 1872adfc5217SJeff Kirsher 1873adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) { 1874adfc5217SJeff Kirsher bp->req_line_speed = 0; 1875adfc5217SJeff Kirsher bp->autoneg |= AUTONEG_SPEED; 1876adfc5217SJeff Kirsher bp->advertising = ADVERTISED_Autoneg; 1877adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) 1878adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_10baseT_Half; 1879adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL) 1880adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_10baseT_Full; 1881adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) 1882adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_100baseT_Half; 1883adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL) 1884adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_100baseT_Full; 1885adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) 1886adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_1000baseT_Full; 1887adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) 1888adfc5217SJeff Kirsher bp->advertising |= ADVERTISED_2500baseX_Full; 1889adfc5217SJeff Kirsher } else { 1890adfc5217SJeff Kirsher bp->autoneg = 0; 1891adfc5217SJeff Kirsher bp->advertising = 0; 1892adfc5217SJeff Kirsher bp->req_duplex = DUPLEX_FULL; 1893adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_10) { 1894adfc5217SJeff Kirsher bp->req_line_speed = SPEED_10; 1895adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) 1896adfc5217SJeff Kirsher bp->req_duplex = DUPLEX_HALF; 1897adfc5217SJeff Kirsher } 1898adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_100) { 1899adfc5217SJeff Kirsher bp->req_line_speed = SPEED_100; 1900adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) 1901adfc5217SJeff Kirsher bp->req_duplex = DUPLEX_HALF; 1902adfc5217SJeff Kirsher } 1903adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) 1904adfc5217SJeff Kirsher bp->req_line_speed = SPEED_1000; 1905adfc5217SJeff Kirsher if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) 1906adfc5217SJeff Kirsher bp->req_line_speed = SPEED_2500; 1907adfc5217SJeff Kirsher } 1908adfc5217SJeff Kirsher } 1909adfc5217SJeff Kirsher 1910adfc5217SJeff Kirsher static void 1911adfc5217SJeff Kirsher bnx2_set_default_link(struct bnx2 *bp) 1912adfc5217SJeff Kirsher { 1913adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) { 1914adfc5217SJeff Kirsher bnx2_set_default_remote_link(bp); 1915adfc5217SJeff Kirsher return; 1916adfc5217SJeff Kirsher } 1917adfc5217SJeff Kirsher 1918adfc5217SJeff Kirsher bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; 1919adfc5217SJeff Kirsher bp->req_line_speed = 0; 1920adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 1921adfc5217SJeff Kirsher u32 reg; 1922adfc5217SJeff Kirsher 1923adfc5217SJeff Kirsher bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; 1924adfc5217SJeff Kirsher 1925adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG); 1926adfc5217SJeff Kirsher reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; 1927adfc5217SJeff Kirsher if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { 1928adfc5217SJeff Kirsher bp->autoneg = 0; 1929adfc5217SJeff Kirsher bp->req_line_speed = bp->line_speed = SPEED_1000; 1930adfc5217SJeff Kirsher bp->req_duplex = DUPLEX_FULL; 1931adfc5217SJeff Kirsher } 1932adfc5217SJeff Kirsher } else 1933adfc5217SJeff Kirsher bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; 1934adfc5217SJeff Kirsher } 1935adfc5217SJeff Kirsher 1936adfc5217SJeff Kirsher static void 1937adfc5217SJeff Kirsher bnx2_send_heart_beat(struct bnx2 *bp) 1938adfc5217SJeff Kirsher { 1939adfc5217SJeff Kirsher u32 msg; 1940adfc5217SJeff Kirsher u32 addr; 1941adfc5217SJeff Kirsher 1942adfc5217SJeff Kirsher spin_lock(&bp->indirect_lock); 1943adfc5217SJeff Kirsher msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK); 1944adfc5217SJeff Kirsher addr = bp->shmem_base + BNX2_DRV_PULSE_MB; 1945adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); 1946adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); 1947adfc5217SJeff Kirsher spin_unlock(&bp->indirect_lock); 1948adfc5217SJeff Kirsher } 1949adfc5217SJeff Kirsher 1950adfc5217SJeff Kirsher static void 1951adfc5217SJeff Kirsher bnx2_remote_phy_event(struct bnx2 *bp) 1952adfc5217SJeff Kirsher { 1953adfc5217SJeff Kirsher u32 msg; 1954adfc5217SJeff Kirsher u8 link_up = bp->link_up; 1955adfc5217SJeff Kirsher u8 old_port; 1956adfc5217SJeff Kirsher 1957adfc5217SJeff Kirsher msg = bnx2_shmem_rd(bp, BNX2_LINK_STATUS); 1958adfc5217SJeff Kirsher 1959adfc5217SJeff Kirsher if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED) 1960adfc5217SJeff Kirsher bnx2_send_heart_beat(bp); 1961adfc5217SJeff Kirsher 1962adfc5217SJeff Kirsher msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED; 1963adfc5217SJeff Kirsher 1964adfc5217SJeff Kirsher if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN) 1965adfc5217SJeff Kirsher bp->link_up = 0; 1966adfc5217SJeff Kirsher else { 1967adfc5217SJeff Kirsher u32 speed; 1968adfc5217SJeff Kirsher 1969adfc5217SJeff Kirsher bp->link_up = 1; 1970adfc5217SJeff Kirsher speed = msg & BNX2_LINK_STATUS_SPEED_MASK; 1971adfc5217SJeff Kirsher bp->duplex = DUPLEX_FULL; 1972adfc5217SJeff Kirsher switch (speed) { 1973adfc5217SJeff Kirsher case BNX2_LINK_STATUS_10HALF: 1974adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1975adfc5217SJeff Kirsher case BNX2_LINK_STATUS_10FULL: 1976adfc5217SJeff Kirsher bp->line_speed = SPEED_10; 1977adfc5217SJeff Kirsher break; 1978adfc5217SJeff Kirsher case BNX2_LINK_STATUS_100HALF: 1979adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1980adfc5217SJeff Kirsher case BNX2_LINK_STATUS_100BASE_T4: 1981adfc5217SJeff Kirsher case BNX2_LINK_STATUS_100FULL: 1982adfc5217SJeff Kirsher bp->line_speed = SPEED_100; 1983adfc5217SJeff Kirsher break; 1984adfc5217SJeff Kirsher case BNX2_LINK_STATUS_1000HALF: 1985adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1986adfc5217SJeff Kirsher case BNX2_LINK_STATUS_1000FULL: 1987adfc5217SJeff Kirsher bp->line_speed = SPEED_1000; 1988adfc5217SJeff Kirsher break; 1989adfc5217SJeff Kirsher case BNX2_LINK_STATUS_2500HALF: 1990adfc5217SJeff Kirsher bp->duplex = DUPLEX_HALF; 1991adfc5217SJeff Kirsher case BNX2_LINK_STATUS_2500FULL: 1992adfc5217SJeff Kirsher bp->line_speed = SPEED_2500; 1993adfc5217SJeff Kirsher break; 1994adfc5217SJeff Kirsher default: 1995adfc5217SJeff Kirsher bp->line_speed = 0; 1996adfc5217SJeff Kirsher break; 1997adfc5217SJeff Kirsher } 1998adfc5217SJeff Kirsher 1999adfc5217SJeff Kirsher bp->flow_ctrl = 0; 2000adfc5217SJeff Kirsher if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != 2001adfc5217SJeff Kirsher (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { 2002adfc5217SJeff Kirsher if (bp->duplex == DUPLEX_FULL) 2003adfc5217SJeff Kirsher bp->flow_ctrl = bp->req_flow_ctrl; 2004adfc5217SJeff Kirsher } else { 2005adfc5217SJeff Kirsher if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED) 2006adfc5217SJeff Kirsher bp->flow_ctrl |= FLOW_CTRL_TX; 2007adfc5217SJeff Kirsher if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED) 2008adfc5217SJeff Kirsher bp->flow_ctrl |= FLOW_CTRL_RX; 2009adfc5217SJeff Kirsher } 2010adfc5217SJeff Kirsher 2011adfc5217SJeff Kirsher old_port = bp->phy_port; 2012adfc5217SJeff Kirsher if (msg & BNX2_LINK_STATUS_SERDES_LINK) 2013adfc5217SJeff Kirsher bp->phy_port = PORT_FIBRE; 2014adfc5217SJeff Kirsher else 2015adfc5217SJeff Kirsher bp->phy_port = PORT_TP; 2016adfc5217SJeff Kirsher 2017adfc5217SJeff Kirsher if (old_port != bp->phy_port) 2018adfc5217SJeff Kirsher bnx2_set_default_link(bp); 2019adfc5217SJeff Kirsher 2020adfc5217SJeff Kirsher } 2021adfc5217SJeff Kirsher if (bp->link_up != link_up) 2022adfc5217SJeff Kirsher bnx2_report_link(bp); 2023adfc5217SJeff Kirsher 2024adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 2025adfc5217SJeff Kirsher } 2026adfc5217SJeff Kirsher 2027adfc5217SJeff Kirsher static int 2028adfc5217SJeff Kirsher bnx2_set_remote_link(struct bnx2 *bp) 2029adfc5217SJeff Kirsher { 2030adfc5217SJeff Kirsher u32 evt_code; 2031adfc5217SJeff Kirsher 2032adfc5217SJeff Kirsher evt_code = bnx2_shmem_rd(bp, BNX2_FW_EVT_CODE_MB); 2033adfc5217SJeff Kirsher switch (evt_code) { 2034adfc5217SJeff Kirsher case BNX2_FW_EVT_CODE_LINK_EVENT: 2035adfc5217SJeff Kirsher bnx2_remote_phy_event(bp); 2036adfc5217SJeff Kirsher break; 2037adfc5217SJeff Kirsher case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT: 2038adfc5217SJeff Kirsher default: 2039adfc5217SJeff Kirsher bnx2_send_heart_beat(bp); 2040adfc5217SJeff Kirsher break; 2041adfc5217SJeff Kirsher } 2042adfc5217SJeff Kirsher return 0; 2043adfc5217SJeff Kirsher } 2044adfc5217SJeff Kirsher 2045adfc5217SJeff Kirsher static int 2046adfc5217SJeff Kirsher bnx2_setup_copper_phy(struct bnx2 *bp) 2047adfc5217SJeff Kirsher __releases(&bp->phy_lock) 2048adfc5217SJeff Kirsher __acquires(&bp->phy_lock) 2049adfc5217SJeff Kirsher { 2050adfc5217SJeff Kirsher u32 bmcr; 2051adfc5217SJeff Kirsher u32 new_bmcr; 2052adfc5217SJeff Kirsher 2053adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 2054adfc5217SJeff Kirsher 2055adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) { 2056adfc5217SJeff Kirsher u32 adv_reg, adv1000_reg; 205737f07023SMatt Carlson u32 new_adv = 0; 205837f07023SMatt Carlson u32 new_adv1000 = 0; 2059adfc5217SJeff Kirsher 2060adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_adv, &adv_reg); 2061adfc5217SJeff Kirsher adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP | 2062adfc5217SJeff Kirsher ADVERTISE_PAUSE_ASYM); 2063adfc5217SJeff Kirsher 2064adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg); 2065adfc5217SJeff Kirsher adv1000_reg &= PHY_ALL_1000_SPEED; 2066adfc5217SJeff Kirsher 206737f07023SMatt Carlson new_adv = ethtool_adv_to_mii_adv_t(bp->advertising); 206837f07023SMatt Carlson new_adv |= ADVERTISE_CSMA; 206937f07023SMatt Carlson new_adv |= bnx2_phy_get_pause_adv(bp); 2070adfc5217SJeff Kirsher 207137f07023SMatt Carlson new_adv1000 |= ethtool_adv_to_mii_ctrl1000_t(bp->advertising); 207228011cf1SMatt Carlson 207337f07023SMatt Carlson if ((adv1000_reg != new_adv1000) || 207437f07023SMatt Carlson (adv_reg != new_adv) || 2075adfc5217SJeff Kirsher ((bmcr & BMCR_ANENABLE) == 0)) { 2076adfc5217SJeff Kirsher 207737f07023SMatt Carlson bnx2_write_phy(bp, bp->mii_adv, new_adv); 207837f07023SMatt Carlson bnx2_write_phy(bp, MII_CTRL1000, new_adv1000); 2079adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART | 2080adfc5217SJeff Kirsher BMCR_ANENABLE); 2081adfc5217SJeff Kirsher } 2082adfc5217SJeff Kirsher else if (bp->link_up) { 2083adfc5217SJeff Kirsher /* Flow ctrl may have changed from auto to forced */ 2084adfc5217SJeff Kirsher /* or vice-versa. */ 2085adfc5217SJeff Kirsher 2086adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 2087adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 2088adfc5217SJeff Kirsher } 2089adfc5217SJeff Kirsher return 0; 2090adfc5217SJeff Kirsher } 2091adfc5217SJeff Kirsher 2092adfc5217SJeff Kirsher new_bmcr = 0; 2093adfc5217SJeff Kirsher if (bp->req_line_speed == SPEED_100) { 2094adfc5217SJeff Kirsher new_bmcr |= BMCR_SPEED100; 2095adfc5217SJeff Kirsher } 2096adfc5217SJeff Kirsher if (bp->req_duplex == DUPLEX_FULL) { 2097adfc5217SJeff Kirsher new_bmcr |= BMCR_FULLDPLX; 2098adfc5217SJeff Kirsher } 2099adfc5217SJeff Kirsher if (new_bmcr != bmcr) { 2100adfc5217SJeff Kirsher u32 bmsr; 2101adfc5217SJeff Kirsher 2102adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 2103adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 2104adfc5217SJeff Kirsher 2105adfc5217SJeff Kirsher if (bmsr & BMSR_LSTATUS) { 2106adfc5217SJeff Kirsher /* Force link down */ 2107adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); 2108adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 2109adfc5217SJeff Kirsher msleep(50); 2110adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 2111adfc5217SJeff Kirsher 2112adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 2113adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr, &bmsr); 2114adfc5217SJeff Kirsher } 2115adfc5217SJeff Kirsher 2116adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr); 2117adfc5217SJeff Kirsher 2118adfc5217SJeff Kirsher /* Normally, the new speed is setup after the link has 2119adfc5217SJeff Kirsher * gone down and up again. In some cases, link will not go 2120adfc5217SJeff Kirsher * down so we need to set up the new speed here. 2121adfc5217SJeff Kirsher */ 2122adfc5217SJeff Kirsher if (bmsr & BMSR_LSTATUS) { 2123adfc5217SJeff Kirsher bp->line_speed = bp->req_line_speed; 2124adfc5217SJeff Kirsher bp->duplex = bp->req_duplex; 2125adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 2126adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 2127adfc5217SJeff Kirsher } 2128adfc5217SJeff Kirsher } else { 2129adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(bp); 2130adfc5217SJeff Kirsher bnx2_set_mac_link(bp); 2131adfc5217SJeff Kirsher } 2132adfc5217SJeff Kirsher return 0; 2133adfc5217SJeff Kirsher } 2134adfc5217SJeff Kirsher 2135adfc5217SJeff Kirsher static int 2136adfc5217SJeff Kirsher bnx2_setup_phy(struct bnx2 *bp, u8 port) 2137adfc5217SJeff Kirsher __releases(&bp->phy_lock) 2138adfc5217SJeff Kirsher __acquires(&bp->phy_lock) 2139adfc5217SJeff Kirsher { 2140adfc5217SJeff Kirsher if (bp->loopback == MAC_LOOPBACK) 2141adfc5217SJeff Kirsher return 0; 2142adfc5217SJeff Kirsher 2143adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 2144adfc5217SJeff Kirsher return bnx2_setup_serdes_phy(bp, port); 2145adfc5217SJeff Kirsher } 2146adfc5217SJeff Kirsher else { 2147adfc5217SJeff Kirsher return bnx2_setup_copper_phy(bp); 2148adfc5217SJeff Kirsher } 2149adfc5217SJeff Kirsher } 2150adfc5217SJeff Kirsher 2151adfc5217SJeff Kirsher static int 2152adfc5217SJeff Kirsher bnx2_init_5709s_phy(struct bnx2 *bp, int reset_phy) 2153adfc5217SJeff Kirsher { 2154adfc5217SJeff Kirsher u32 val; 2155adfc5217SJeff Kirsher 2156adfc5217SJeff Kirsher bp->mii_bmcr = MII_BMCR + 0x10; 2157adfc5217SJeff Kirsher bp->mii_bmsr = MII_BMSR + 0x10; 2158adfc5217SJeff Kirsher bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1; 2159adfc5217SJeff Kirsher bp->mii_adv = MII_ADVERTISE + 0x10; 2160adfc5217SJeff Kirsher bp->mii_lpa = MII_LPA + 0x10; 2161adfc5217SJeff Kirsher bp->mii_up1 = MII_BNX2_OVER1G_UP1; 2162adfc5217SJeff Kirsher 2163adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER); 2164adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD); 2165adfc5217SJeff Kirsher 2166adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 2167adfc5217SJeff Kirsher if (reset_phy) 2168adfc5217SJeff Kirsher bnx2_reset_phy(bp); 2169adfc5217SJeff Kirsher 2170adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG); 2171adfc5217SJeff Kirsher 2172adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val); 2173adfc5217SJeff Kirsher val &= ~MII_BNX2_SD_1000XCTL1_AUTODET; 2174adfc5217SJeff Kirsher val |= MII_BNX2_SD_1000XCTL1_FIBER; 2175adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val); 2176adfc5217SJeff Kirsher 2177adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); 2178adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val); 2179adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) 2180adfc5217SJeff Kirsher val |= BCM5708S_UP1_2G5; 2181adfc5217SJeff Kirsher else 2182adfc5217SJeff Kirsher val &= ~BCM5708S_UP1_2G5; 2183adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val); 2184adfc5217SJeff Kirsher 2185adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG); 2186adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val); 2187adfc5217SJeff Kirsher val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM; 2188adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val); 2189adfc5217SJeff Kirsher 2190adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0); 2191adfc5217SJeff Kirsher 2192adfc5217SJeff Kirsher val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN | 2193adfc5217SJeff Kirsher MII_BNX2_CL73_BAM_NP_AFT_BP_EN; 2194adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val); 2195adfc5217SJeff Kirsher 2196adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); 2197adfc5217SJeff Kirsher 2198adfc5217SJeff Kirsher return 0; 2199adfc5217SJeff Kirsher } 2200adfc5217SJeff Kirsher 2201adfc5217SJeff Kirsher static int 2202adfc5217SJeff Kirsher bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy) 2203adfc5217SJeff Kirsher { 2204adfc5217SJeff Kirsher u32 val; 2205adfc5217SJeff Kirsher 2206adfc5217SJeff Kirsher if (reset_phy) 2207adfc5217SJeff Kirsher bnx2_reset_phy(bp); 2208adfc5217SJeff Kirsher 2209adfc5217SJeff Kirsher bp->mii_up1 = BCM5708S_UP1; 2210adfc5217SJeff Kirsher 2211adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); 2212adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); 2213adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); 2214adfc5217SJeff Kirsher 2215adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val); 2216adfc5217SJeff Kirsher val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN; 2217adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val); 2218adfc5217SJeff Kirsher 2219adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val); 2220adfc5217SJeff Kirsher val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN; 2221adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val); 2222adfc5217SJeff Kirsher 2223adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) { 2224adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_UP1, &val); 2225adfc5217SJeff Kirsher val |= BCM5708S_UP1_2G5; 2226adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_UP1, val); 2227adfc5217SJeff Kirsher } 2228adfc5217SJeff Kirsher 2229adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || 2230adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_B0) || 2231adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_B1)) { 2232adfc5217SJeff Kirsher /* increase tx signal amplitude */ 2233adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, 2234adfc5217SJeff Kirsher BCM5708S_BLK_ADDR_TX_MISC); 2235adfc5217SJeff Kirsher bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val); 2236adfc5217SJeff Kirsher val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM; 2237adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val); 2238adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); 2239adfc5217SJeff Kirsher } 2240adfc5217SJeff Kirsher 2241adfc5217SJeff Kirsher val = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG) & 2242adfc5217SJeff Kirsher BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; 2243adfc5217SJeff Kirsher 2244adfc5217SJeff Kirsher if (val) { 2245adfc5217SJeff Kirsher u32 is_backplane; 2246adfc5217SJeff Kirsher 2247adfc5217SJeff Kirsher is_backplane = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG); 2248adfc5217SJeff Kirsher if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { 2249adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, 2250adfc5217SJeff Kirsher BCM5708S_BLK_ADDR_TX_MISC); 2251adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val); 2252adfc5217SJeff Kirsher bnx2_write_phy(bp, BCM5708S_BLK_ADDR, 2253adfc5217SJeff Kirsher BCM5708S_BLK_ADDR_DIG); 2254adfc5217SJeff Kirsher } 2255adfc5217SJeff Kirsher } 2256adfc5217SJeff Kirsher return 0; 2257adfc5217SJeff Kirsher } 2258adfc5217SJeff Kirsher 2259adfc5217SJeff Kirsher static int 2260adfc5217SJeff Kirsher bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy) 2261adfc5217SJeff Kirsher { 2262adfc5217SJeff Kirsher if (reset_phy) 2263adfc5217SJeff Kirsher bnx2_reset_phy(bp); 2264adfc5217SJeff Kirsher 2265adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT; 2266adfc5217SJeff Kirsher 2267adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706) 2268adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300); 2269adfc5217SJeff Kirsher 2270adfc5217SJeff Kirsher if (bp->dev->mtu > 1500) { 2271adfc5217SJeff Kirsher u32 val; 2272adfc5217SJeff Kirsher 2273adfc5217SJeff Kirsher /* Set extended packet length bit */ 2274adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x7); 2275adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x18, &val); 2276adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, (val & 0xfff8) | 0x4000); 2277adfc5217SJeff Kirsher 2278adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x1c, 0x6c00); 2279adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x1c, &val); 2280adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x1c, (val & 0x3ff) | 0xec02); 2281adfc5217SJeff Kirsher } 2282adfc5217SJeff Kirsher else { 2283adfc5217SJeff Kirsher u32 val; 2284adfc5217SJeff Kirsher 2285adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x7); 2286adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x18, &val); 2287adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, val & ~0x4007); 2288adfc5217SJeff Kirsher 2289adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x1c, 0x6c00); 2290adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x1c, &val); 2291adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00); 2292adfc5217SJeff Kirsher } 2293adfc5217SJeff Kirsher 2294adfc5217SJeff Kirsher return 0; 2295adfc5217SJeff Kirsher } 2296adfc5217SJeff Kirsher 2297adfc5217SJeff Kirsher static int 2298adfc5217SJeff Kirsher bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy) 2299adfc5217SJeff Kirsher { 2300adfc5217SJeff Kirsher u32 val; 2301adfc5217SJeff Kirsher 2302adfc5217SJeff Kirsher if (reset_phy) 2303adfc5217SJeff Kirsher bnx2_reset_phy(bp); 2304adfc5217SJeff Kirsher 2305adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_CRC_FIX) { 2306adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x0c00); 2307adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x17, 0x000a); 2308adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x15, 0x310b); 2309adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x17, 0x201f); 2310adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x15, 0x9506); 2311adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x17, 0x401f); 2312adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x15, 0x14e2); 2313adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x0400); 2314adfc5217SJeff Kirsher } 2315adfc5217SJeff Kirsher 2316adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_DIS_EARLY_DAC) { 2317adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, 2318adfc5217SJeff Kirsher MII_BNX2_DSP_EXPAND_REG | 0x8); 2319adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val); 2320adfc5217SJeff Kirsher val &= ~(1 << 8); 2321adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val); 2322adfc5217SJeff Kirsher } 2323adfc5217SJeff Kirsher 2324adfc5217SJeff Kirsher if (bp->dev->mtu > 1500) { 2325adfc5217SJeff Kirsher /* Set extended packet length bit */ 2326adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x7); 2327adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x18, &val); 2328adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, val | 0x4000); 2329adfc5217SJeff Kirsher 2330adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x10, &val); 2331adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x10, val | 0x1); 2332adfc5217SJeff Kirsher } 2333adfc5217SJeff Kirsher else { 2334adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x7); 2335adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x18, &val); 2336adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, val & ~0x4007); 2337adfc5217SJeff Kirsher 2338adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x10, &val); 2339adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x10, val & ~0x1); 2340adfc5217SJeff Kirsher } 2341adfc5217SJeff Kirsher 2342adfc5217SJeff Kirsher /* ethernet@wirespeed */ 2343adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, 0x7007); 2344adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x18, &val); 2345adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4)); 2346adfc5217SJeff Kirsher return 0; 2347adfc5217SJeff Kirsher } 2348adfc5217SJeff Kirsher 2349adfc5217SJeff Kirsher 2350adfc5217SJeff Kirsher static int 2351adfc5217SJeff Kirsher bnx2_init_phy(struct bnx2 *bp, int reset_phy) 2352adfc5217SJeff Kirsher __releases(&bp->phy_lock) 2353adfc5217SJeff Kirsher __acquires(&bp->phy_lock) 2354adfc5217SJeff Kirsher { 2355adfc5217SJeff Kirsher u32 val; 2356adfc5217SJeff Kirsher int rc = 0; 2357adfc5217SJeff Kirsher 2358adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_INT_MODE_MASK; 2359adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_INT_MODE_LINK_READY; 2360adfc5217SJeff Kirsher 2361adfc5217SJeff Kirsher bp->mii_bmcr = MII_BMCR; 2362adfc5217SJeff Kirsher bp->mii_bmsr = MII_BMSR; 2363adfc5217SJeff Kirsher bp->mii_bmsr1 = MII_BMSR; 2364adfc5217SJeff Kirsher bp->mii_adv = MII_ADVERTISE; 2365adfc5217SJeff Kirsher bp->mii_lpa = MII_LPA; 2366adfc5217SJeff Kirsher 2367adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); 2368adfc5217SJeff Kirsher 2369adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 2370adfc5217SJeff Kirsher goto setup_phy; 2371adfc5217SJeff Kirsher 2372adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_PHYSID1, &val); 2373adfc5217SJeff Kirsher bp->phy_id = val << 16; 2374adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_PHYSID2, &val); 2375adfc5217SJeff Kirsher bp->phy_id |= val & 0xffff; 2376adfc5217SJeff Kirsher 2377adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 2378adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706) 2379adfc5217SJeff Kirsher rc = bnx2_init_5706s_phy(bp, reset_phy); 2380adfc5217SJeff Kirsher else if (CHIP_NUM(bp) == CHIP_NUM_5708) 2381adfc5217SJeff Kirsher rc = bnx2_init_5708s_phy(bp, reset_phy); 2382adfc5217SJeff Kirsher else if (CHIP_NUM(bp) == CHIP_NUM_5709) 2383adfc5217SJeff Kirsher rc = bnx2_init_5709s_phy(bp, reset_phy); 2384adfc5217SJeff Kirsher } 2385adfc5217SJeff Kirsher else { 2386adfc5217SJeff Kirsher rc = bnx2_init_copper_phy(bp, reset_phy); 2387adfc5217SJeff Kirsher } 2388adfc5217SJeff Kirsher 2389adfc5217SJeff Kirsher setup_phy: 2390adfc5217SJeff Kirsher if (!rc) 2391adfc5217SJeff Kirsher rc = bnx2_setup_phy(bp, bp->phy_port); 2392adfc5217SJeff Kirsher 2393adfc5217SJeff Kirsher return rc; 2394adfc5217SJeff Kirsher } 2395adfc5217SJeff Kirsher 2396adfc5217SJeff Kirsher static int 2397adfc5217SJeff Kirsher bnx2_set_mac_loopback(struct bnx2 *bp) 2398adfc5217SJeff Kirsher { 2399adfc5217SJeff Kirsher u32 mac_mode; 2400adfc5217SJeff Kirsher 2401adfc5217SJeff Kirsher mac_mode = REG_RD(bp, BNX2_EMAC_MODE); 2402adfc5217SJeff Kirsher mac_mode &= ~BNX2_EMAC_MODE_PORT; 2403adfc5217SJeff Kirsher mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK; 2404adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MODE, mac_mode); 2405adfc5217SJeff Kirsher bp->link_up = 1; 2406adfc5217SJeff Kirsher return 0; 2407adfc5217SJeff Kirsher } 2408adfc5217SJeff Kirsher 2409adfc5217SJeff Kirsher static int bnx2_test_link(struct bnx2 *); 2410adfc5217SJeff Kirsher 2411adfc5217SJeff Kirsher static int 2412adfc5217SJeff Kirsher bnx2_set_phy_loopback(struct bnx2 *bp) 2413adfc5217SJeff Kirsher { 2414adfc5217SJeff Kirsher u32 mac_mode; 2415adfc5217SJeff Kirsher int rc, i; 2416adfc5217SJeff Kirsher 2417adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 2418adfc5217SJeff Kirsher rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX | 2419adfc5217SJeff Kirsher BMCR_SPEED1000); 2420adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 2421adfc5217SJeff Kirsher if (rc) 2422adfc5217SJeff Kirsher return rc; 2423adfc5217SJeff Kirsher 2424adfc5217SJeff Kirsher for (i = 0; i < 10; i++) { 2425adfc5217SJeff Kirsher if (bnx2_test_link(bp) == 0) 2426adfc5217SJeff Kirsher break; 2427adfc5217SJeff Kirsher msleep(100); 2428adfc5217SJeff Kirsher } 2429adfc5217SJeff Kirsher 2430adfc5217SJeff Kirsher mac_mode = REG_RD(bp, BNX2_EMAC_MODE); 2431adfc5217SJeff Kirsher mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | 2432adfc5217SJeff Kirsher BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | 2433adfc5217SJeff Kirsher BNX2_EMAC_MODE_25G_MODE); 2434adfc5217SJeff Kirsher 2435adfc5217SJeff Kirsher mac_mode |= BNX2_EMAC_MODE_PORT_GMII; 2436adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MODE, mac_mode); 2437adfc5217SJeff Kirsher bp->link_up = 1; 2438adfc5217SJeff Kirsher return 0; 2439adfc5217SJeff Kirsher } 2440adfc5217SJeff Kirsher 2441adfc5217SJeff Kirsher static void 2442adfc5217SJeff Kirsher bnx2_dump_mcp_state(struct bnx2 *bp) 2443adfc5217SJeff Kirsher { 2444adfc5217SJeff Kirsher struct net_device *dev = bp->dev; 2445adfc5217SJeff Kirsher u32 mcp_p0, mcp_p1; 2446adfc5217SJeff Kirsher 2447adfc5217SJeff Kirsher netdev_err(dev, "<--- start MCP states dump --->\n"); 2448adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 2449adfc5217SJeff Kirsher mcp_p0 = BNX2_MCP_STATE_P0; 2450adfc5217SJeff Kirsher mcp_p1 = BNX2_MCP_STATE_P1; 2451adfc5217SJeff Kirsher } else { 2452adfc5217SJeff Kirsher mcp_p0 = BNX2_MCP_STATE_P0_5708; 2453adfc5217SJeff Kirsher mcp_p1 = BNX2_MCP_STATE_P1_5708; 2454adfc5217SJeff Kirsher } 2455adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n", 2456adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1)); 2457adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n", 2458adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE), 2459adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE), 2460adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK)); 2461adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n", 2462adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER), 2463adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER), 2464adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION)); 2465adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: shmem states:\n"); 2466adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]", 2467adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_DRV_MB), 2468adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_FW_MB), 2469adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_LINK_STATUS)); 2470adfc5217SJeff Kirsher pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB)); 2471adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]", 2472adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE), 2473adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE)); 2474adfc5217SJeff Kirsher pr_cont(" condition[%08x]\n", 2475adfc5217SJeff Kirsher bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION)); 2476adfc5217SJeff Kirsher DP_SHMEM_LINE(bp, 0x3cc); 2477adfc5217SJeff Kirsher DP_SHMEM_LINE(bp, 0x3dc); 2478adfc5217SJeff Kirsher DP_SHMEM_LINE(bp, 0x3ec); 2479adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc)); 2480adfc5217SJeff Kirsher netdev_err(dev, "<--- end MCP states dump --->\n"); 2481adfc5217SJeff Kirsher } 2482adfc5217SJeff Kirsher 2483adfc5217SJeff Kirsher static int 2484adfc5217SJeff Kirsher bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent) 2485adfc5217SJeff Kirsher { 2486adfc5217SJeff Kirsher int i; 2487adfc5217SJeff Kirsher u32 val; 2488adfc5217SJeff Kirsher 2489adfc5217SJeff Kirsher bp->fw_wr_seq++; 2490adfc5217SJeff Kirsher msg_data |= bp->fw_wr_seq; 2491adfc5217SJeff Kirsher 2492adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); 2493adfc5217SJeff Kirsher 2494adfc5217SJeff Kirsher if (!ack) 2495adfc5217SJeff Kirsher return 0; 2496adfc5217SJeff Kirsher 2497adfc5217SJeff Kirsher /* wait for an acknowledgement. */ 2498adfc5217SJeff Kirsher for (i = 0; i < (BNX2_FW_ACK_TIME_OUT_MS / 10); i++) { 2499adfc5217SJeff Kirsher msleep(10); 2500adfc5217SJeff Kirsher 2501adfc5217SJeff Kirsher val = bnx2_shmem_rd(bp, BNX2_FW_MB); 2502adfc5217SJeff Kirsher 2503adfc5217SJeff Kirsher if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) 2504adfc5217SJeff Kirsher break; 2505adfc5217SJeff Kirsher } 2506adfc5217SJeff Kirsher if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0) 2507adfc5217SJeff Kirsher return 0; 2508adfc5217SJeff Kirsher 2509adfc5217SJeff Kirsher /* If we timed out, inform the firmware that this is the case. */ 2510adfc5217SJeff Kirsher if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) { 2511adfc5217SJeff Kirsher msg_data &= ~BNX2_DRV_MSG_CODE; 2512adfc5217SJeff Kirsher msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; 2513adfc5217SJeff Kirsher 2514adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); 2515adfc5217SJeff Kirsher if (!silent) { 2516adfc5217SJeff Kirsher pr_err("fw sync timeout, reset code = %x\n", msg_data); 2517adfc5217SJeff Kirsher bnx2_dump_mcp_state(bp); 2518adfc5217SJeff Kirsher } 2519adfc5217SJeff Kirsher 2520adfc5217SJeff Kirsher return -EBUSY; 2521adfc5217SJeff Kirsher } 2522adfc5217SJeff Kirsher 2523adfc5217SJeff Kirsher if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK) 2524adfc5217SJeff Kirsher return -EIO; 2525adfc5217SJeff Kirsher 2526adfc5217SJeff Kirsher return 0; 2527adfc5217SJeff Kirsher } 2528adfc5217SJeff Kirsher 2529adfc5217SJeff Kirsher static int 2530adfc5217SJeff Kirsher bnx2_init_5709_context(struct bnx2 *bp) 2531adfc5217SJeff Kirsher { 2532adfc5217SJeff Kirsher int i, ret = 0; 2533adfc5217SJeff Kirsher u32 val; 2534adfc5217SJeff Kirsher 2535adfc5217SJeff Kirsher val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12); 2536adfc5217SJeff Kirsher val |= (BCM_PAGE_BITS - 8) << 16; 2537adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_COMMAND, val); 2538adfc5217SJeff Kirsher for (i = 0; i < 10; i++) { 2539adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_CTX_COMMAND); 2540adfc5217SJeff Kirsher if (!(val & BNX2_CTX_COMMAND_MEM_INIT)) 2541adfc5217SJeff Kirsher break; 2542adfc5217SJeff Kirsher udelay(2); 2543adfc5217SJeff Kirsher } 2544adfc5217SJeff Kirsher if (val & BNX2_CTX_COMMAND_MEM_INIT) 2545adfc5217SJeff Kirsher return -EBUSY; 2546adfc5217SJeff Kirsher 2547adfc5217SJeff Kirsher for (i = 0; i < bp->ctx_pages; i++) { 2548adfc5217SJeff Kirsher int j; 2549adfc5217SJeff Kirsher 2550adfc5217SJeff Kirsher if (bp->ctx_blk[i]) 2551adfc5217SJeff Kirsher memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE); 2552adfc5217SJeff Kirsher else 2553adfc5217SJeff Kirsher return -ENOMEM; 2554adfc5217SJeff Kirsher 2555adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0, 2556adfc5217SJeff Kirsher (bp->ctx_blk_mapping[i] & 0xffffffff) | 2557adfc5217SJeff Kirsher BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID); 2558adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1, 2559adfc5217SJeff Kirsher (u64) bp->ctx_blk_mapping[i] >> 32); 2560adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i | 2561adfc5217SJeff Kirsher BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ); 2562adfc5217SJeff Kirsher for (j = 0; j < 10; j++) { 2563adfc5217SJeff Kirsher 2564adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL); 2565adfc5217SJeff Kirsher if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ)) 2566adfc5217SJeff Kirsher break; 2567adfc5217SJeff Kirsher udelay(5); 2568adfc5217SJeff Kirsher } 2569adfc5217SJeff Kirsher if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) { 2570adfc5217SJeff Kirsher ret = -EBUSY; 2571adfc5217SJeff Kirsher break; 2572adfc5217SJeff Kirsher } 2573adfc5217SJeff Kirsher } 2574adfc5217SJeff Kirsher return ret; 2575adfc5217SJeff Kirsher } 2576adfc5217SJeff Kirsher 2577adfc5217SJeff Kirsher static void 2578adfc5217SJeff Kirsher bnx2_init_context(struct bnx2 *bp) 2579adfc5217SJeff Kirsher { 2580adfc5217SJeff Kirsher u32 vcid; 2581adfc5217SJeff Kirsher 2582adfc5217SJeff Kirsher vcid = 96; 2583adfc5217SJeff Kirsher while (vcid) { 2584adfc5217SJeff Kirsher u32 vcid_addr, pcid_addr, offset; 2585adfc5217SJeff Kirsher int i; 2586adfc5217SJeff Kirsher 2587adfc5217SJeff Kirsher vcid--; 2588adfc5217SJeff Kirsher 2589adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A0) { 2590adfc5217SJeff Kirsher u32 new_vcid; 2591adfc5217SJeff Kirsher 2592adfc5217SJeff Kirsher vcid_addr = GET_PCID_ADDR(vcid); 2593adfc5217SJeff Kirsher if (vcid & 0x8) { 2594adfc5217SJeff Kirsher new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7); 2595adfc5217SJeff Kirsher } 2596adfc5217SJeff Kirsher else { 2597adfc5217SJeff Kirsher new_vcid = vcid; 2598adfc5217SJeff Kirsher } 2599adfc5217SJeff Kirsher pcid_addr = GET_PCID_ADDR(new_vcid); 2600adfc5217SJeff Kirsher } 2601adfc5217SJeff Kirsher else { 2602adfc5217SJeff Kirsher vcid_addr = GET_CID_ADDR(vcid); 2603adfc5217SJeff Kirsher pcid_addr = vcid_addr; 2604adfc5217SJeff Kirsher } 2605adfc5217SJeff Kirsher 2606adfc5217SJeff Kirsher for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) { 2607adfc5217SJeff Kirsher vcid_addr += (i << PHY_CTX_SHIFT); 2608adfc5217SJeff Kirsher pcid_addr += (i << PHY_CTX_SHIFT); 2609adfc5217SJeff Kirsher 2610adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); 2611adfc5217SJeff Kirsher REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); 2612adfc5217SJeff Kirsher 2613adfc5217SJeff Kirsher /* Zero out the context. */ 2614adfc5217SJeff Kirsher for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) 2615adfc5217SJeff Kirsher bnx2_ctx_wr(bp, vcid_addr, offset, 0); 2616adfc5217SJeff Kirsher } 2617adfc5217SJeff Kirsher } 2618adfc5217SJeff Kirsher } 2619adfc5217SJeff Kirsher 2620adfc5217SJeff Kirsher static int 2621adfc5217SJeff Kirsher bnx2_alloc_bad_rbuf(struct bnx2 *bp) 2622adfc5217SJeff Kirsher { 2623adfc5217SJeff Kirsher u16 *good_mbuf; 2624adfc5217SJeff Kirsher u32 good_mbuf_cnt; 2625adfc5217SJeff Kirsher u32 val; 2626adfc5217SJeff Kirsher 2627adfc5217SJeff Kirsher good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); 2628e404decbSJoe Perches if (good_mbuf == NULL) 2629adfc5217SJeff Kirsher return -ENOMEM; 2630adfc5217SJeff Kirsher 2631adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 2632adfc5217SJeff Kirsher BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); 2633adfc5217SJeff Kirsher 2634adfc5217SJeff Kirsher good_mbuf_cnt = 0; 2635adfc5217SJeff Kirsher 2636adfc5217SJeff Kirsher /* Allocate a bunch of mbufs and save the good ones in an array. */ 2637adfc5217SJeff Kirsher val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1); 2638adfc5217SJeff Kirsher while (val & BNX2_RBUF_STATUS1_FREE_COUNT) { 2639adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RBUF_COMMAND, 2640adfc5217SJeff Kirsher BNX2_RBUF_COMMAND_ALLOC_REQ); 2641adfc5217SJeff Kirsher 2642adfc5217SJeff Kirsher val = bnx2_reg_rd_ind(bp, BNX2_RBUF_FW_BUF_ALLOC); 2643adfc5217SJeff Kirsher 2644adfc5217SJeff Kirsher val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE; 2645adfc5217SJeff Kirsher 2646adfc5217SJeff Kirsher /* The addresses with Bit 9 set are bad memory blocks. */ 2647adfc5217SJeff Kirsher if (!(val & (1 << 9))) { 2648adfc5217SJeff Kirsher good_mbuf[good_mbuf_cnt] = (u16) val; 2649adfc5217SJeff Kirsher good_mbuf_cnt++; 2650adfc5217SJeff Kirsher } 2651adfc5217SJeff Kirsher 2652adfc5217SJeff Kirsher val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1); 2653adfc5217SJeff Kirsher } 2654adfc5217SJeff Kirsher 2655adfc5217SJeff Kirsher /* Free the good ones back to the mbuf pool thus discarding 2656adfc5217SJeff Kirsher * all the bad ones. */ 2657adfc5217SJeff Kirsher while (good_mbuf_cnt) { 2658adfc5217SJeff Kirsher good_mbuf_cnt--; 2659adfc5217SJeff Kirsher 2660adfc5217SJeff Kirsher val = good_mbuf[good_mbuf_cnt]; 2661adfc5217SJeff Kirsher val = (val << 9) | val | 1; 2662adfc5217SJeff Kirsher 2663adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RBUF_FW_BUF_FREE, val); 2664adfc5217SJeff Kirsher } 2665adfc5217SJeff Kirsher kfree(good_mbuf); 2666adfc5217SJeff Kirsher return 0; 2667adfc5217SJeff Kirsher } 2668adfc5217SJeff Kirsher 2669adfc5217SJeff Kirsher static void 2670adfc5217SJeff Kirsher bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos) 2671adfc5217SJeff Kirsher { 2672adfc5217SJeff Kirsher u32 val; 2673adfc5217SJeff Kirsher 2674adfc5217SJeff Kirsher val = (mac_addr[0] << 8) | mac_addr[1]; 2675adfc5217SJeff Kirsher 2676adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val); 2677adfc5217SJeff Kirsher 2678adfc5217SJeff Kirsher val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | 2679adfc5217SJeff Kirsher (mac_addr[4] << 8) | mac_addr[5]; 2680adfc5217SJeff Kirsher 2681adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val); 2682adfc5217SJeff Kirsher } 2683adfc5217SJeff Kirsher 2684adfc5217SJeff Kirsher static inline int 2685adfc5217SJeff Kirsher bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp) 2686adfc5217SJeff Kirsher { 2687adfc5217SJeff Kirsher dma_addr_t mapping; 2688adfc5217SJeff Kirsher struct sw_pg *rx_pg = &rxr->rx_pg_ring[index]; 2689adfc5217SJeff Kirsher struct rx_bd *rxbd = 2690adfc5217SJeff Kirsher &rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)]; 2691adfc5217SJeff Kirsher struct page *page = alloc_page(gfp); 2692adfc5217SJeff Kirsher 2693adfc5217SJeff Kirsher if (!page) 2694adfc5217SJeff Kirsher return -ENOMEM; 2695adfc5217SJeff Kirsher mapping = dma_map_page(&bp->pdev->dev, page, 0, PAGE_SIZE, 2696adfc5217SJeff Kirsher PCI_DMA_FROMDEVICE); 2697adfc5217SJeff Kirsher if (dma_mapping_error(&bp->pdev->dev, mapping)) { 2698adfc5217SJeff Kirsher __free_page(page); 2699adfc5217SJeff Kirsher return -EIO; 2700adfc5217SJeff Kirsher } 2701adfc5217SJeff Kirsher 2702adfc5217SJeff Kirsher rx_pg->page = page; 2703adfc5217SJeff Kirsher dma_unmap_addr_set(rx_pg, mapping, mapping); 2704adfc5217SJeff Kirsher rxbd->rx_bd_haddr_hi = (u64) mapping >> 32; 2705adfc5217SJeff Kirsher rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff; 2706adfc5217SJeff Kirsher return 0; 2707adfc5217SJeff Kirsher } 2708adfc5217SJeff Kirsher 2709adfc5217SJeff Kirsher static void 2710adfc5217SJeff Kirsher bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index) 2711adfc5217SJeff Kirsher { 2712adfc5217SJeff Kirsher struct sw_pg *rx_pg = &rxr->rx_pg_ring[index]; 2713adfc5217SJeff Kirsher struct page *page = rx_pg->page; 2714adfc5217SJeff Kirsher 2715adfc5217SJeff Kirsher if (!page) 2716adfc5217SJeff Kirsher return; 2717adfc5217SJeff Kirsher 2718adfc5217SJeff Kirsher dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(rx_pg, mapping), 2719adfc5217SJeff Kirsher PAGE_SIZE, PCI_DMA_FROMDEVICE); 2720adfc5217SJeff Kirsher 2721adfc5217SJeff Kirsher __free_page(page); 2722adfc5217SJeff Kirsher rx_pg->page = NULL; 2723adfc5217SJeff Kirsher } 2724adfc5217SJeff Kirsher 2725adfc5217SJeff Kirsher static inline int 2726dd2bc8e9SEric Dumazet bnx2_alloc_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp) 2727adfc5217SJeff Kirsher { 2728dd2bc8e9SEric Dumazet u8 *data; 2729adfc5217SJeff Kirsher struct sw_bd *rx_buf = &rxr->rx_buf_ring[index]; 2730adfc5217SJeff Kirsher dma_addr_t mapping; 2731adfc5217SJeff Kirsher struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; 2732adfc5217SJeff Kirsher 2733dd2bc8e9SEric Dumazet data = kmalloc(bp->rx_buf_size, gfp); 2734dd2bc8e9SEric Dumazet if (!data) 2735adfc5217SJeff Kirsher return -ENOMEM; 2736adfc5217SJeff Kirsher 2737dd2bc8e9SEric Dumazet mapping = dma_map_single(&bp->pdev->dev, 2738dd2bc8e9SEric Dumazet get_l2_fhdr(data), 2739dd2bc8e9SEric Dumazet bp->rx_buf_use_size, 2740adfc5217SJeff Kirsher PCI_DMA_FROMDEVICE); 2741adfc5217SJeff Kirsher if (dma_mapping_error(&bp->pdev->dev, mapping)) { 2742dd2bc8e9SEric Dumazet kfree(data); 2743adfc5217SJeff Kirsher return -EIO; 2744adfc5217SJeff Kirsher } 2745adfc5217SJeff Kirsher 2746dd2bc8e9SEric Dumazet rx_buf->data = data; 2747adfc5217SJeff Kirsher dma_unmap_addr_set(rx_buf, mapping, mapping); 2748adfc5217SJeff Kirsher 2749adfc5217SJeff Kirsher rxbd->rx_bd_haddr_hi = (u64) mapping >> 32; 2750adfc5217SJeff Kirsher rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff; 2751adfc5217SJeff Kirsher 2752adfc5217SJeff Kirsher rxr->rx_prod_bseq += bp->rx_buf_use_size; 2753adfc5217SJeff Kirsher 2754adfc5217SJeff Kirsher return 0; 2755adfc5217SJeff Kirsher } 2756adfc5217SJeff Kirsher 2757adfc5217SJeff Kirsher static int 2758adfc5217SJeff Kirsher bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event) 2759adfc5217SJeff Kirsher { 2760adfc5217SJeff Kirsher struct status_block *sblk = bnapi->status_blk.msi; 2761adfc5217SJeff Kirsher u32 new_link_state, old_link_state; 2762adfc5217SJeff Kirsher int is_set = 1; 2763adfc5217SJeff Kirsher 2764adfc5217SJeff Kirsher new_link_state = sblk->status_attn_bits & event; 2765adfc5217SJeff Kirsher old_link_state = sblk->status_attn_bits_ack & event; 2766adfc5217SJeff Kirsher if (new_link_state != old_link_state) { 2767adfc5217SJeff Kirsher if (new_link_state) 2768adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event); 2769adfc5217SJeff Kirsher else 2770adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event); 2771adfc5217SJeff Kirsher } else 2772adfc5217SJeff Kirsher is_set = 0; 2773adfc5217SJeff Kirsher 2774adfc5217SJeff Kirsher return is_set; 2775adfc5217SJeff Kirsher } 2776adfc5217SJeff Kirsher 2777adfc5217SJeff Kirsher static void 2778adfc5217SJeff Kirsher bnx2_phy_int(struct bnx2 *bp, struct bnx2_napi *bnapi) 2779adfc5217SJeff Kirsher { 2780adfc5217SJeff Kirsher spin_lock(&bp->phy_lock); 2781adfc5217SJeff Kirsher 2782adfc5217SJeff Kirsher if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_LINK_STATE)) 2783adfc5217SJeff Kirsher bnx2_set_link(bp); 2784adfc5217SJeff Kirsher if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_TIMER_ABORT)) 2785adfc5217SJeff Kirsher bnx2_set_remote_link(bp); 2786adfc5217SJeff Kirsher 2787adfc5217SJeff Kirsher spin_unlock(&bp->phy_lock); 2788adfc5217SJeff Kirsher 2789adfc5217SJeff Kirsher } 2790adfc5217SJeff Kirsher 2791adfc5217SJeff Kirsher static inline u16 2792adfc5217SJeff Kirsher bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi) 2793adfc5217SJeff Kirsher { 2794adfc5217SJeff Kirsher u16 cons; 2795adfc5217SJeff Kirsher 2796adfc5217SJeff Kirsher /* Tell compiler that status block fields can change. */ 2797adfc5217SJeff Kirsher barrier(); 2798adfc5217SJeff Kirsher cons = *bnapi->hw_tx_cons_ptr; 2799adfc5217SJeff Kirsher barrier(); 2800adfc5217SJeff Kirsher if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT)) 2801adfc5217SJeff Kirsher cons++; 2802adfc5217SJeff Kirsher return cons; 2803adfc5217SJeff Kirsher } 2804adfc5217SJeff Kirsher 2805adfc5217SJeff Kirsher static int 2806adfc5217SJeff Kirsher bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) 2807adfc5217SJeff Kirsher { 2808adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 2809adfc5217SJeff Kirsher u16 hw_cons, sw_cons, sw_ring_cons; 2810adfc5217SJeff Kirsher int tx_pkt = 0, index; 2811e9831909SEric Dumazet unsigned int tx_bytes = 0; 2812adfc5217SJeff Kirsher struct netdev_queue *txq; 2813adfc5217SJeff Kirsher 2814adfc5217SJeff Kirsher index = (bnapi - bp->bnx2_napi); 2815adfc5217SJeff Kirsher txq = netdev_get_tx_queue(bp->dev, index); 2816adfc5217SJeff Kirsher 2817adfc5217SJeff Kirsher hw_cons = bnx2_get_hw_tx_cons(bnapi); 2818adfc5217SJeff Kirsher sw_cons = txr->tx_cons; 2819adfc5217SJeff Kirsher 2820adfc5217SJeff Kirsher while (sw_cons != hw_cons) { 2821adfc5217SJeff Kirsher struct sw_tx_bd *tx_buf; 2822adfc5217SJeff Kirsher struct sk_buff *skb; 2823adfc5217SJeff Kirsher int i, last; 2824adfc5217SJeff Kirsher 2825adfc5217SJeff Kirsher sw_ring_cons = TX_RING_IDX(sw_cons); 2826adfc5217SJeff Kirsher 2827adfc5217SJeff Kirsher tx_buf = &txr->tx_buf_ring[sw_ring_cons]; 2828adfc5217SJeff Kirsher skb = tx_buf->skb; 2829adfc5217SJeff Kirsher 2830adfc5217SJeff Kirsher /* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */ 2831adfc5217SJeff Kirsher prefetch(&skb->end); 2832adfc5217SJeff Kirsher 2833adfc5217SJeff Kirsher /* partial BD completions possible with TSO packets */ 2834adfc5217SJeff Kirsher if (tx_buf->is_gso) { 2835adfc5217SJeff Kirsher u16 last_idx, last_ring_idx; 2836adfc5217SJeff Kirsher 2837adfc5217SJeff Kirsher last_idx = sw_cons + tx_buf->nr_frags + 1; 2838adfc5217SJeff Kirsher last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1; 2839adfc5217SJeff Kirsher if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) { 2840adfc5217SJeff Kirsher last_idx++; 2841adfc5217SJeff Kirsher } 2842adfc5217SJeff Kirsher if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) { 2843adfc5217SJeff Kirsher break; 2844adfc5217SJeff Kirsher } 2845adfc5217SJeff Kirsher } 2846adfc5217SJeff Kirsher 2847adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), 2848adfc5217SJeff Kirsher skb_headlen(skb), PCI_DMA_TODEVICE); 2849adfc5217SJeff Kirsher 2850adfc5217SJeff Kirsher tx_buf->skb = NULL; 2851adfc5217SJeff Kirsher last = tx_buf->nr_frags; 2852adfc5217SJeff Kirsher 2853adfc5217SJeff Kirsher for (i = 0; i < last; i++) { 2854adfc5217SJeff Kirsher sw_cons = NEXT_TX_BD(sw_cons); 2855adfc5217SJeff Kirsher 2856adfc5217SJeff Kirsher dma_unmap_page(&bp->pdev->dev, 2857adfc5217SJeff Kirsher dma_unmap_addr( 2858adfc5217SJeff Kirsher &txr->tx_buf_ring[TX_RING_IDX(sw_cons)], 2859adfc5217SJeff Kirsher mapping), 28609e903e08SEric Dumazet skb_frag_size(&skb_shinfo(skb)->frags[i]), 2861adfc5217SJeff Kirsher PCI_DMA_TODEVICE); 2862adfc5217SJeff Kirsher } 2863adfc5217SJeff Kirsher 2864adfc5217SJeff Kirsher sw_cons = NEXT_TX_BD(sw_cons); 2865adfc5217SJeff Kirsher 2866e9831909SEric Dumazet tx_bytes += skb->len; 2867adfc5217SJeff Kirsher dev_kfree_skb(skb); 2868adfc5217SJeff Kirsher tx_pkt++; 2869adfc5217SJeff Kirsher if (tx_pkt == budget) 2870adfc5217SJeff Kirsher break; 2871adfc5217SJeff Kirsher 2872adfc5217SJeff Kirsher if (hw_cons == sw_cons) 2873adfc5217SJeff Kirsher hw_cons = bnx2_get_hw_tx_cons(bnapi); 2874adfc5217SJeff Kirsher } 2875adfc5217SJeff Kirsher 2876e9831909SEric Dumazet netdev_tx_completed_queue(txq, tx_pkt, tx_bytes); 2877adfc5217SJeff Kirsher txr->hw_tx_cons = hw_cons; 2878adfc5217SJeff Kirsher txr->tx_cons = sw_cons; 2879adfc5217SJeff Kirsher 2880adfc5217SJeff Kirsher /* Need to make the tx_cons update visible to bnx2_start_xmit() 2881adfc5217SJeff Kirsher * before checking for netif_tx_queue_stopped(). Without the 2882adfc5217SJeff Kirsher * memory barrier, there is a small possibility that bnx2_start_xmit() 2883adfc5217SJeff Kirsher * will miss it and cause the queue to be stopped forever. 2884adfc5217SJeff Kirsher */ 2885adfc5217SJeff Kirsher smp_mb(); 2886adfc5217SJeff Kirsher 2887adfc5217SJeff Kirsher if (unlikely(netif_tx_queue_stopped(txq)) && 2888adfc5217SJeff Kirsher (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) { 2889adfc5217SJeff Kirsher __netif_tx_lock(txq, smp_processor_id()); 2890adfc5217SJeff Kirsher if ((netif_tx_queue_stopped(txq)) && 2891adfc5217SJeff Kirsher (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) 2892adfc5217SJeff Kirsher netif_tx_wake_queue(txq); 2893adfc5217SJeff Kirsher __netif_tx_unlock(txq); 2894adfc5217SJeff Kirsher } 2895adfc5217SJeff Kirsher 2896adfc5217SJeff Kirsher return tx_pkt; 2897adfc5217SJeff Kirsher } 2898adfc5217SJeff Kirsher 2899adfc5217SJeff Kirsher static void 2900adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, 2901adfc5217SJeff Kirsher struct sk_buff *skb, int count) 2902adfc5217SJeff Kirsher { 2903adfc5217SJeff Kirsher struct sw_pg *cons_rx_pg, *prod_rx_pg; 2904adfc5217SJeff Kirsher struct rx_bd *cons_bd, *prod_bd; 2905adfc5217SJeff Kirsher int i; 2906adfc5217SJeff Kirsher u16 hw_prod, prod; 2907adfc5217SJeff Kirsher u16 cons = rxr->rx_pg_cons; 2908adfc5217SJeff Kirsher 2909adfc5217SJeff Kirsher cons_rx_pg = &rxr->rx_pg_ring[cons]; 2910adfc5217SJeff Kirsher 2911adfc5217SJeff Kirsher /* The caller was unable to allocate a new page to replace the 2912adfc5217SJeff Kirsher * last one in the frags array, so we need to recycle that page 2913adfc5217SJeff Kirsher * and then free the skb. 2914adfc5217SJeff Kirsher */ 2915adfc5217SJeff Kirsher if (skb) { 2916adfc5217SJeff Kirsher struct page *page; 2917adfc5217SJeff Kirsher struct skb_shared_info *shinfo; 2918adfc5217SJeff Kirsher 2919adfc5217SJeff Kirsher shinfo = skb_shinfo(skb); 2920adfc5217SJeff Kirsher shinfo->nr_frags--; 2921b7b6a688SIan Campbell page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]); 2922b7b6a688SIan Campbell __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL); 2923adfc5217SJeff Kirsher 2924adfc5217SJeff Kirsher cons_rx_pg->page = page; 2925adfc5217SJeff Kirsher dev_kfree_skb(skb); 2926adfc5217SJeff Kirsher } 2927adfc5217SJeff Kirsher 2928adfc5217SJeff Kirsher hw_prod = rxr->rx_pg_prod; 2929adfc5217SJeff Kirsher 2930adfc5217SJeff Kirsher for (i = 0; i < count; i++) { 2931adfc5217SJeff Kirsher prod = RX_PG_RING_IDX(hw_prod); 2932adfc5217SJeff Kirsher 2933adfc5217SJeff Kirsher prod_rx_pg = &rxr->rx_pg_ring[prod]; 2934adfc5217SJeff Kirsher cons_rx_pg = &rxr->rx_pg_ring[cons]; 2935adfc5217SJeff Kirsher cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)]; 2936adfc5217SJeff Kirsher prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; 2937adfc5217SJeff Kirsher 2938adfc5217SJeff Kirsher if (prod != cons) { 2939adfc5217SJeff Kirsher prod_rx_pg->page = cons_rx_pg->page; 2940adfc5217SJeff Kirsher cons_rx_pg->page = NULL; 2941adfc5217SJeff Kirsher dma_unmap_addr_set(prod_rx_pg, mapping, 2942adfc5217SJeff Kirsher dma_unmap_addr(cons_rx_pg, mapping)); 2943adfc5217SJeff Kirsher 2944adfc5217SJeff Kirsher prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi; 2945adfc5217SJeff Kirsher prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; 2946adfc5217SJeff Kirsher 2947adfc5217SJeff Kirsher } 2948adfc5217SJeff Kirsher cons = RX_PG_RING_IDX(NEXT_RX_BD(cons)); 2949adfc5217SJeff Kirsher hw_prod = NEXT_RX_BD(hw_prod); 2950adfc5217SJeff Kirsher } 2951adfc5217SJeff Kirsher rxr->rx_pg_prod = hw_prod; 2952adfc5217SJeff Kirsher rxr->rx_pg_cons = cons; 2953adfc5217SJeff Kirsher } 2954adfc5217SJeff Kirsher 2955adfc5217SJeff Kirsher static inline void 2956dd2bc8e9SEric Dumazet bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, 2957dd2bc8e9SEric Dumazet u8 *data, u16 cons, u16 prod) 2958adfc5217SJeff Kirsher { 2959adfc5217SJeff Kirsher struct sw_bd *cons_rx_buf, *prod_rx_buf; 2960adfc5217SJeff Kirsher struct rx_bd *cons_bd, *prod_bd; 2961adfc5217SJeff Kirsher 2962adfc5217SJeff Kirsher cons_rx_buf = &rxr->rx_buf_ring[cons]; 2963adfc5217SJeff Kirsher prod_rx_buf = &rxr->rx_buf_ring[prod]; 2964adfc5217SJeff Kirsher 2965adfc5217SJeff Kirsher dma_sync_single_for_device(&bp->pdev->dev, 2966adfc5217SJeff Kirsher dma_unmap_addr(cons_rx_buf, mapping), 2967adfc5217SJeff Kirsher BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE); 2968adfc5217SJeff Kirsher 2969adfc5217SJeff Kirsher rxr->rx_prod_bseq += bp->rx_buf_use_size; 2970adfc5217SJeff Kirsher 2971dd2bc8e9SEric Dumazet prod_rx_buf->data = data; 2972adfc5217SJeff Kirsher 2973adfc5217SJeff Kirsher if (cons == prod) 2974adfc5217SJeff Kirsher return; 2975adfc5217SJeff Kirsher 2976adfc5217SJeff Kirsher dma_unmap_addr_set(prod_rx_buf, mapping, 2977adfc5217SJeff Kirsher dma_unmap_addr(cons_rx_buf, mapping)); 2978adfc5217SJeff Kirsher 2979adfc5217SJeff Kirsher cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)]; 2980adfc5217SJeff Kirsher prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; 2981adfc5217SJeff Kirsher prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi; 2982adfc5217SJeff Kirsher prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; 2983adfc5217SJeff Kirsher } 2984adfc5217SJeff Kirsher 2985dd2bc8e9SEric Dumazet static struct sk_buff * 2986dd2bc8e9SEric Dumazet bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u8 *data, 2987adfc5217SJeff Kirsher unsigned int len, unsigned int hdr_len, dma_addr_t dma_addr, 2988adfc5217SJeff Kirsher u32 ring_idx) 2989adfc5217SJeff Kirsher { 2990adfc5217SJeff Kirsher int err; 2991adfc5217SJeff Kirsher u16 prod = ring_idx & 0xffff; 2992dd2bc8e9SEric Dumazet struct sk_buff *skb; 2993adfc5217SJeff Kirsher 2994dd2bc8e9SEric Dumazet err = bnx2_alloc_rx_data(bp, rxr, prod, GFP_ATOMIC); 2995adfc5217SJeff Kirsher if (unlikely(err)) { 2996dd2bc8e9SEric Dumazet bnx2_reuse_rx_data(bp, rxr, data, (u16) (ring_idx >> 16), prod); 2997dd2bc8e9SEric Dumazet error: 2998adfc5217SJeff Kirsher if (hdr_len) { 2999adfc5217SJeff Kirsher unsigned int raw_len = len + 4; 3000adfc5217SJeff Kirsher int pages = PAGE_ALIGN(raw_len - hdr_len) >> PAGE_SHIFT; 3001adfc5217SJeff Kirsher 3002adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages); 3003adfc5217SJeff Kirsher } 3004dd2bc8e9SEric Dumazet return NULL; 3005adfc5217SJeff Kirsher } 3006adfc5217SJeff Kirsher 3007adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size, 3008adfc5217SJeff Kirsher PCI_DMA_FROMDEVICE); 3009dd2bc8e9SEric Dumazet skb = build_skb(data); 3010dd2bc8e9SEric Dumazet if (!skb) { 3011dd2bc8e9SEric Dumazet kfree(data); 3012dd2bc8e9SEric Dumazet goto error; 3013dd2bc8e9SEric Dumazet } 3014dd2bc8e9SEric Dumazet skb_reserve(skb, ((u8 *)get_l2_fhdr(data) - data) + BNX2_RX_OFFSET); 3015adfc5217SJeff Kirsher if (hdr_len == 0) { 3016adfc5217SJeff Kirsher skb_put(skb, len); 3017dd2bc8e9SEric Dumazet return skb; 3018adfc5217SJeff Kirsher } else { 3019adfc5217SJeff Kirsher unsigned int i, frag_len, frag_size, pages; 3020adfc5217SJeff Kirsher struct sw_pg *rx_pg; 3021adfc5217SJeff Kirsher u16 pg_cons = rxr->rx_pg_cons; 3022adfc5217SJeff Kirsher u16 pg_prod = rxr->rx_pg_prod; 3023adfc5217SJeff Kirsher 3024adfc5217SJeff Kirsher frag_size = len + 4 - hdr_len; 3025adfc5217SJeff Kirsher pages = PAGE_ALIGN(frag_size) >> PAGE_SHIFT; 3026adfc5217SJeff Kirsher skb_put(skb, hdr_len); 3027adfc5217SJeff Kirsher 3028adfc5217SJeff Kirsher for (i = 0; i < pages; i++) { 3029adfc5217SJeff Kirsher dma_addr_t mapping_old; 3030adfc5217SJeff Kirsher 3031adfc5217SJeff Kirsher frag_len = min(frag_size, (unsigned int) PAGE_SIZE); 3032adfc5217SJeff Kirsher if (unlikely(frag_len <= 4)) { 3033adfc5217SJeff Kirsher unsigned int tail = 4 - frag_len; 3034adfc5217SJeff Kirsher 3035adfc5217SJeff Kirsher rxr->rx_pg_cons = pg_cons; 3036adfc5217SJeff Kirsher rxr->rx_pg_prod = pg_prod; 3037adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(bp, rxr, NULL, 3038adfc5217SJeff Kirsher pages - i); 3039adfc5217SJeff Kirsher skb->len -= tail; 3040adfc5217SJeff Kirsher if (i == 0) { 3041adfc5217SJeff Kirsher skb->tail -= tail; 3042adfc5217SJeff Kirsher } else { 3043adfc5217SJeff Kirsher skb_frag_t *frag = 3044adfc5217SJeff Kirsher &skb_shinfo(skb)->frags[i - 1]; 30459e903e08SEric Dumazet skb_frag_size_sub(frag, tail); 3046adfc5217SJeff Kirsher skb->data_len -= tail; 3047adfc5217SJeff Kirsher } 3048dd2bc8e9SEric Dumazet return skb; 3049adfc5217SJeff Kirsher } 3050adfc5217SJeff Kirsher rx_pg = &rxr->rx_pg_ring[pg_cons]; 3051adfc5217SJeff Kirsher 3052adfc5217SJeff Kirsher /* Don't unmap yet. If we're unable to allocate a new 3053adfc5217SJeff Kirsher * page, we need to recycle the page and the DMA addr. 3054adfc5217SJeff Kirsher */ 3055adfc5217SJeff Kirsher mapping_old = dma_unmap_addr(rx_pg, mapping); 3056adfc5217SJeff Kirsher if (i == pages - 1) 3057adfc5217SJeff Kirsher frag_len -= 4; 3058adfc5217SJeff Kirsher 3059adfc5217SJeff Kirsher skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len); 3060adfc5217SJeff Kirsher rx_pg->page = NULL; 3061adfc5217SJeff Kirsher 3062adfc5217SJeff Kirsher err = bnx2_alloc_rx_page(bp, rxr, 3063adfc5217SJeff Kirsher RX_PG_RING_IDX(pg_prod), 3064adfc5217SJeff Kirsher GFP_ATOMIC); 3065adfc5217SJeff Kirsher if (unlikely(err)) { 3066adfc5217SJeff Kirsher rxr->rx_pg_cons = pg_cons; 3067adfc5217SJeff Kirsher rxr->rx_pg_prod = pg_prod; 3068adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(bp, rxr, skb, 3069adfc5217SJeff Kirsher pages - i); 3070dd2bc8e9SEric Dumazet return NULL; 3071adfc5217SJeff Kirsher } 3072adfc5217SJeff Kirsher 3073adfc5217SJeff Kirsher dma_unmap_page(&bp->pdev->dev, mapping_old, 3074adfc5217SJeff Kirsher PAGE_SIZE, PCI_DMA_FROMDEVICE); 3075adfc5217SJeff Kirsher 3076adfc5217SJeff Kirsher frag_size -= frag_len; 3077adfc5217SJeff Kirsher skb->data_len += frag_len; 3078a1f4e8bcSEric Dumazet skb->truesize += PAGE_SIZE; 3079adfc5217SJeff Kirsher skb->len += frag_len; 3080adfc5217SJeff Kirsher 3081adfc5217SJeff Kirsher pg_prod = NEXT_RX_BD(pg_prod); 3082adfc5217SJeff Kirsher pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons)); 3083adfc5217SJeff Kirsher } 3084adfc5217SJeff Kirsher rxr->rx_pg_prod = pg_prod; 3085adfc5217SJeff Kirsher rxr->rx_pg_cons = pg_cons; 3086adfc5217SJeff Kirsher } 3087dd2bc8e9SEric Dumazet return skb; 3088adfc5217SJeff Kirsher } 3089adfc5217SJeff Kirsher 3090adfc5217SJeff Kirsher static inline u16 3091adfc5217SJeff Kirsher bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi) 3092adfc5217SJeff Kirsher { 3093adfc5217SJeff Kirsher u16 cons; 3094adfc5217SJeff Kirsher 3095adfc5217SJeff Kirsher /* Tell compiler that status block fields can change. */ 3096adfc5217SJeff Kirsher barrier(); 3097adfc5217SJeff Kirsher cons = *bnapi->hw_rx_cons_ptr; 3098adfc5217SJeff Kirsher barrier(); 3099adfc5217SJeff Kirsher if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) 3100adfc5217SJeff Kirsher cons++; 3101adfc5217SJeff Kirsher return cons; 3102adfc5217SJeff Kirsher } 3103adfc5217SJeff Kirsher 3104adfc5217SJeff Kirsher static int 3105adfc5217SJeff Kirsher bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) 3106adfc5217SJeff Kirsher { 3107adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 3108adfc5217SJeff Kirsher u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; 3109adfc5217SJeff Kirsher struct l2_fhdr *rx_hdr; 3110adfc5217SJeff Kirsher int rx_pkt = 0, pg_ring_used = 0; 3111adfc5217SJeff Kirsher 3112adfc5217SJeff Kirsher hw_cons = bnx2_get_hw_rx_cons(bnapi); 3113adfc5217SJeff Kirsher sw_cons = rxr->rx_cons; 3114adfc5217SJeff Kirsher sw_prod = rxr->rx_prod; 3115adfc5217SJeff Kirsher 3116adfc5217SJeff Kirsher /* Memory barrier necessary as speculative reads of the rx 3117adfc5217SJeff Kirsher * buffer can be ahead of the index in the status block 3118adfc5217SJeff Kirsher */ 3119adfc5217SJeff Kirsher rmb(); 3120adfc5217SJeff Kirsher while (sw_cons != hw_cons) { 3121adfc5217SJeff Kirsher unsigned int len, hdr_len; 3122adfc5217SJeff Kirsher u32 status; 3123adfc5217SJeff Kirsher struct sw_bd *rx_buf, *next_rx_buf; 3124adfc5217SJeff Kirsher struct sk_buff *skb; 3125adfc5217SJeff Kirsher dma_addr_t dma_addr; 3126dd2bc8e9SEric Dumazet u8 *data; 3127adfc5217SJeff Kirsher 3128adfc5217SJeff Kirsher sw_ring_cons = RX_RING_IDX(sw_cons); 3129adfc5217SJeff Kirsher sw_ring_prod = RX_RING_IDX(sw_prod); 3130adfc5217SJeff Kirsher 3131adfc5217SJeff Kirsher rx_buf = &rxr->rx_buf_ring[sw_ring_cons]; 3132dd2bc8e9SEric Dumazet data = rx_buf->data; 3133dd2bc8e9SEric Dumazet rx_buf->data = NULL; 3134adfc5217SJeff Kirsher 3135dd2bc8e9SEric Dumazet rx_hdr = get_l2_fhdr(data); 3136dd2bc8e9SEric Dumazet prefetch(rx_hdr); 3137adfc5217SJeff Kirsher 3138adfc5217SJeff Kirsher dma_addr = dma_unmap_addr(rx_buf, mapping); 3139adfc5217SJeff Kirsher 3140adfc5217SJeff Kirsher dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, 3141adfc5217SJeff Kirsher BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, 3142adfc5217SJeff Kirsher PCI_DMA_FROMDEVICE); 3143adfc5217SJeff Kirsher 3144dd2bc8e9SEric Dumazet next_rx_buf = 3145dd2bc8e9SEric Dumazet &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))]; 3146dd2bc8e9SEric Dumazet prefetch(get_l2_fhdr(next_rx_buf->data)); 3147dd2bc8e9SEric Dumazet 3148adfc5217SJeff Kirsher len = rx_hdr->l2_fhdr_pkt_len; 3149adfc5217SJeff Kirsher status = rx_hdr->l2_fhdr_status; 3150adfc5217SJeff Kirsher 3151adfc5217SJeff Kirsher hdr_len = 0; 3152adfc5217SJeff Kirsher if (status & L2_FHDR_STATUS_SPLIT) { 3153adfc5217SJeff Kirsher hdr_len = rx_hdr->l2_fhdr_ip_xsum; 3154adfc5217SJeff Kirsher pg_ring_used = 1; 3155adfc5217SJeff Kirsher } else if (len > bp->rx_jumbo_thresh) { 3156adfc5217SJeff Kirsher hdr_len = bp->rx_jumbo_thresh; 3157adfc5217SJeff Kirsher pg_ring_used = 1; 3158adfc5217SJeff Kirsher } 3159adfc5217SJeff Kirsher 3160adfc5217SJeff Kirsher if (unlikely(status & (L2_FHDR_ERRORS_BAD_CRC | 3161adfc5217SJeff Kirsher L2_FHDR_ERRORS_PHY_DECODE | 3162adfc5217SJeff Kirsher L2_FHDR_ERRORS_ALIGNMENT | 3163adfc5217SJeff Kirsher L2_FHDR_ERRORS_TOO_SHORT | 3164adfc5217SJeff Kirsher L2_FHDR_ERRORS_GIANT_FRAME))) { 3165adfc5217SJeff Kirsher 3166dd2bc8e9SEric Dumazet bnx2_reuse_rx_data(bp, rxr, data, sw_ring_cons, 3167adfc5217SJeff Kirsher sw_ring_prod); 3168adfc5217SJeff Kirsher if (pg_ring_used) { 3169adfc5217SJeff Kirsher int pages; 3170adfc5217SJeff Kirsher 3171adfc5217SJeff Kirsher pages = PAGE_ALIGN(len - hdr_len) >> PAGE_SHIFT; 3172adfc5217SJeff Kirsher 3173adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages); 3174adfc5217SJeff Kirsher } 3175adfc5217SJeff Kirsher goto next_rx; 3176adfc5217SJeff Kirsher } 3177adfc5217SJeff Kirsher 3178adfc5217SJeff Kirsher len -= 4; 3179adfc5217SJeff Kirsher 3180adfc5217SJeff Kirsher if (len <= bp->rx_copy_thresh) { 3181dd2bc8e9SEric Dumazet skb = netdev_alloc_skb(bp->dev, len + 6); 3182dd2bc8e9SEric Dumazet if (skb == NULL) { 3183dd2bc8e9SEric Dumazet bnx2_reuse_rx_data(bp, rxr, data, sw_ring_cons, 3184adfc5217SJeff Kirsher sw_ring_prod); 3185adfc5217SJeff Kirsher goto next_rx; 3186adfc5217SJeff Kirsher } 3187adfc5217SJeff Kirsher 3188adfc5217SJeff Kirsher /* aligned copy */ 3189dd2bc8e9SEric Dumazet memcpy(skb->data, 3190dd2bc8e9SEric Dumazet (u8 *)rx_hdr + BNX2_RX_OFFSET - 6, 3191dd2bc8e9SEric Dumazet len + 6); 3192dd2bc8e9SEric Dumazet skb_reserve(skb, 6); 3193dd2bc8e9SEric Dumazet skb_put(skb, len); 3194adfc5217SJeff Kirsher 3195dd2bc8e9SEric Dumazet bnx2_reuse_rx_data(bp, rxr, data, 3196adfc5217SJeff Kirsher sw_ring_cons, sw_ring_prod); 3197adfc5217SJeff Kirsher 3198dd2bc8e9SEric Dumazet } else { 3199dd2bc8e9SEric Dumazet skb = bnx2_rx_skb(bp, rxr, data, len, hdr_len, dma_addr, 3200dd2bc8e9SEric Dumazet (sw_ring_cons << 16) | sw_ring_prod); 3201dd2bc8e9SEric Dumazet if (!skb) 3202adfc5217SJeff Kirsher goto next_rx; 3203dd2bc8e9SEric Dumazet } 3204adfc5217SJeff Kirsher if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && 3205adfc5217SJeff Kirsher !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) 3206adfc5217SJeff Kirsher __vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag); 3207adfc5217SJeff Kirsher 3208adfc5217SJeff Kirsher skb->protocol = eth_type_trans(skb, bp->dev); 3209adfc5217SJeff Kirsher 3210adfc5217SJeff Kirsher if ((len > (bp->dev->mtu + ETH_HLEN)) && 3211adfc5217SJeff Kirsher (ntohs(skb->protocol) != 0x8100)) { 3212adfc5217SJeff Kirsher 3213adfc5217SJeff Kirsher dev_kfree_skb(skb); 3214adfc5217SJeff Kirsher goto next_rx; 3215adfc5217SJeff Kirsher 3216adfc5217SJeff Kirsher } 3217adfc5217SJeff Kirsher 3218adfc5217SJeff Kirsher skb_checksum_none_assert(skb); 3219adfc5217SJeff Kirsher if ((bp->dev->features & NETIF_F_RXCSUM) && 3220adfc5217SJeff Kirsher (status & (L2_FHDR_STATUS_TCP_SEGMENT | 3221adfc5217SJeff Kirsher L2_FHDR_STATUS_UDP_DATAGRAM))) { 3222adfc5217SJeff Kirsher 3223adfc5217SJeff Kirsher if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM | 3224adfc5217SJeff Kirsher L2_FHDR_ERRORS_UDP_XSUM)) == 0)) 3225adfc5217SJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 3226adfc5217SJeff Kirsher } 3227adfc5217SJeff Kirsher if ((bp->dev->features & NETIF_F_RXHASH) && 3228adfc5217SJeff Kirsher ((status & L2_FHDR_STATUS_USE_RXHASH) == 3229adfc5217SJeff Kirsher L2_FHDR_STATUS_USE_RXHASH)) 3230adfc5217SJeff Kirsher skb->rxhash = rx_hdr->l2_fhdr_hash; 3231adfc5217SJeff Kirsher 3232adfc5217SJeff Kirsher skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]); 3233adfc5217SJeff Kirsher napi_gro_receive(&bnapi->napi, skb); 3234adfc5217SJeff Kirsher rx_pkt++; 3235adfc5217SJeff Kirsher 3236adfc5217SJeff Kirsher next_rx: 3237adfc5217SJeff Kirsher sw_cons = NEXT_RX_BD(sw_cons); 3238adfc5217SJeff Kirsher sw_prod = NEXT_RX_BD(sw_prod); 3239adfc5217SJeff Kirsher 3240adfc5217SJeff Kirsher if ((rx_pkt == budget)) 3241adfc5217SJeff Kirsher break; 3242adfc5217SJeff Kirsher 3243adfc5217SJeff Kirsher /* Refresh hw_cons to see if there is new work */ 3244adfc5217SJeff Kirsher if (sw_cons == hw_cons) { 3245adfc5217SJeff Kirsher hw_cons = bnx2_get_hw_rx_cons(bnapi); 3246adfc5217SJeff Kirsher rmb(); 3247adfc5217SJeff Kirsher } 3248adfc5217SJeff Kirsher } 3249adfc5217SJeff Kirsher rxr->rx_cons = sw_cons; 3250adfc5217SJeff Kirsher rxr->rx_prod = sw_prod; 3251adfc5217SJeff Kirsher 3252adfc5217SJeff Kirsher if (pg_ring_used) 3253adfc5217SJeff Kirsher REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); 3254adfc5217SJeff Kirsher 3255adfc5217SJeff Kirsher REG_WR16(bp, rxr->rx_bidx_addr, sw_prod); 3256adfc5217SJeff Kirsher 3257adfc5217SJeff Kirsher REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); 3258adfc5217SJeff Kirsher 3259adfc5217SJeff Kirsher mmiowb(); 3260adfc5217SJeff Kirsher 3261adfc5217SJeff Kirsher return rx_pkt; 3262adfc5217SJeff Kirsher 3263adfc5217SJeff Kirsher } 3264adfc5217SJeff Kirsher 3265adfc5217SJeff Kirsher /* MSI ISR - The only difference between this and the INTx ISR 3266adfc5217SJeff Kirsher * is that the MSI interrupt is always serviced. 3267adfc5217SJeff Kirsher */ 3268adfc5217SJeff Kirsher static irqreturn_t 3269adfc5217SJeff Kirsher bnx2_msi(int irq, void *dev_instance) 3270adfc5217SJeff Kirsher { 3271adfc5217SJeff Kirsher struct bnx2_napi *bnapi = dev_instance; 3272adfc5217SJeff Kirsher struct bnx2 *bp = bnapi->bp; 3273adfc5217SJeff Kirsher 3274adfc5217SJeff Kirsher prefetch(bnapi->status_blk.msi); 3275adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3276adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 3277adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_MASK_INT); 3278adfc5217SJeff Kirsher 3279adfc5217SJeff Kirsher /* Return here if interrupt is disabled. */ 3280adfc5217SJeff Kirsher if (unlikely(atomic_read(&bp->intr_sem) != 0)) 3281adfc5217SJeff Kirsher return IRQ_HANDLED; 3282adfc5217SJeff Kirsher 3283adfc5217SJeff Kirsher napi_schedule(&bnapi->napi); 3284adfc5217SJeff Kirsher 3285adfc5217SJeff Kirsher return IRQ_HANDLED; 3286adfc5217SJeff Kirsher } 3287adfc5217SJeff Kirsher 3288adfc5217SJeff Kirsher static irqreturn_t 3289adfc5217SJeff Kirsher bnx2_msi_1shot(int irq, void *dev_instance) 3290adfc5217SJeff Kirsher { 3291adfc5217SJeff Kirsher struct bnx2_napi *bnapi = dev_instance; 3292adfc5217SJeff Kirsher struct bnx2 *bp = bnapi->bp; 3293adfc5217SJeff Kirsher 3294adfc5217SJeff Kirsher prefetch(bnapi->status_blk.msi); 3295adfc5217SJeff Kirsher 3296adfc5217SJeff Kirsher /* Return here if interrupt is disabled. */ 3297adfc5217SJeff Kirsher if (unlikely(atomic_read(&bp->intr_sem) != 0)) 3298adfc5217SJeff Kirsher return IRQ_HANDLED; 3299adfc5217SJeff Kirsher 3300adfc5217SJeff Kirsher napi_schedule(&bnapi->napi); 3301adfc5217SJeff Kirsher 3302adfc5217SJeff Kirsher return IRQ_HANDLED; 3303adfc5217SJeff Kirsher } 3304adfc5217SJeff Kirsher 3305adfc5217SJeff Kirsher static irqreturn_t 3306adfc5217SJeff Kirsher bnx2_interrupt(int irq, void *dev_instance) 3307adfc5217SJeff Kirsher { 3308adfc5217SJeff Kirsher struct bnx2_napi *bnapi = dev_instance; 3309adfc5217SJeff Kirsher struct bnx2 *bp = bnapi->bp; 3310adfc5217SJeff Kirsher struct status_block *sblk = bnapi->status_blk.msi; 3311adfc5217SJeff Kirsher 3312adfc5217SJeff Kirsher /* When using INTx, it is possible for the interrupt to arrive 3313adfc5217SJeff Kirsher * at the CPU before the status block posted prior to the 3314adfc5217SJeff Kirsher * interrupt. Reading a register will flush the status block. 3315adfc5217SJeff Kirsher * When using MSI, the MSI message will always complete after 3316adfc5217SJeff Kirsher * the status block write. 3317adfc5217SJeff Kirsher */ 3318adfc5217SJeff Kirsher if ((sblk->status_idx == bnapi->last_status_idx) && 3319adfc5217SJeff Kirsher (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & 3320adfc5217SJeff Kirsher BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) 3321adfc5217SJeff Kirsher return IRQ_NONE; 3322adfc5217SJeff Kirsher 3323adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3324adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | 3325adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_MASK_INT); 3326adfc5217SJeff Kirsher 3327adfc5217SJeff Kirsher /* Read back to deassert IRQ immediately to avoid too many 3328adfc5217SJeff Kirsher * spurious interrupts. 3329adfc5217SJeff Kirsher */ 3330adfc5217SJeff Kirsher REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); 3331adfc5217SJeff Kirsher 3332adfc5217SJeff Kirsher /* Return here if interrupt is shared and is disabled. */ 3333adfc5217SJeff Kirsher if (unlikely(atomic_read(&bp->intr_sem) != 0)) 3334adfc5217SJeff Kirsher return IRQ_HANDLED; 3335adfc5217SJeff Kirsher 3336adfc5217SJeff Kirsher if (napi_schedule_prep(&bnapi->napi)) { 3337adfc5217SJeff Kirsher bnapi->last_status_idx = sblk->status_idx; 3338adfc5217SJeff Kirsher __napi_schedule(&bnapi->napi); 3339adfc5217SJeff Kirsher } 3340adfc5217SJeff Kirsher 3341adfc5217SJeff Kirsher return IRQ_HANDLED; 3342adfc5217SJeff Kirsher } 3343adfc5217SJeff Kirsher 3344adfc5217SJeff Kirsher static inline int 3345adfc5217SJeff Kirsher bnx2_has_fast_work(struct bnx2_napi *bnapi) 3346adfc5217SJeff Kirsher { 3347adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 3348adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 3349adfc5217SJeff Kirsher 3350adfc5217SJeff Kirsher if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) || 3351adfc5217SJeff Kirsher (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)) 3352adfc5217SJeff Kirsher return 1; 3353adfc5217SJeff Kirsher return 0; 3354adfc5217SJeff Kirsher } 3355adfc5217SJeff Kirsher 3356adfc5217SJeff Kirsher #define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \ 3357adfc5217SJeff Kirsher STATUS_ATTN_BITS_TIMER_ABORT) 3358adfc5217SJeff Kirsher 3359adfc5217SJeff Kirsher static inline int 3360adfc5217SJeff Kirsher bnx2_has_work(struct bnx2_napi *bnapi) 3361adfc5217SJeff Kirsher { 3362adfc5217SJeff Kirsher struct status_block *sblk = bnapi->status_blk.msi; 3363adfc5217SJeff Kirsher 3364adfc5217SJeff Kirsher if (bnx2_has_fast_work(bnapi)) 3365adfc5217SJeff Kirsher return 1; 3366adfc5217SJeff Kirsher 3367adfc5217SJeff Kirsher #ifdef BCM_CNIC 3368adfc5217SJeff Kirsher if (bnapi->cnic_present && (bnapi->cnic_tag != sblk->status_idx)) 3369adfc5217SJeff Kirsher return 1; 3370adfc5217SJeff Kirsher #endif 3371adfc5217SJeff Kirsher 3372adfc5217SJeff Kirsher if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) != 3373adfc5217SJeff Kirsher (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS)) 3374adfc5217SJeff Kirsher return 1; 3375adfc5217SJeff Kirsher 3376adfc5217SJeff Kirsher return 0; 3377adfc5217SJeff Kirsher } 3378adfc5217SJeff Kirsher 3379adfc5217SJeff Kirsher static void 3380adfc5217SJeff Kirsher bnx2_chk_missed_msi(struct bnx2 *bp) 3381adfc5217SJeff Kirsher { 3382adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; 3383adfc5217SJeff Kirsher u32 msi_ctrl; 3384adfc5217SJeff Kirsher 3385adfc5217SJeff Kirsher if (bnx2_has_work(bnapi)) { 3386adfc5217SJeff Kirsher msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL); 3387adfc5217SJeff Kirsher if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE)) 3388adfc5217SJeff Kirsher return; 3389adfc5217SJeff Kirsher 3390adfc5217SJeff Kirsher if (bnapi->last_status_idx == bp->idle_chk_status_idx) { 3391adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl & 3392adfc5217SJeff Kirsher ~BNX2_PCICFG_MSI_CONTROL_ENABLE); 3393adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl); 3394adfc5217SJeff Kirsher bnx2_msi(bp->irq_tbl[0].vector, bnapi); 3395adfc5217SJeff Kirsher } 3396adfc5217SJeff Kirsher } 3397adfc5217SJeff Kirsher 3398adfc5217SJeff Kirsher bp->idle_chk_status_idx = bnapi->last_status_idx; 3399adfc5217SJeff Kirsher } 3400adfc5217SJeff Kirsher 3401adfc5217SJeff Kirsher #ifdef BCM_CNIC 3402adfc5217SJeff Kirsher static void bnx2_poll_cnic(struct bnx2 *bp, struct bnx2_napi *bnapi) 3403adfc5217SJeff Kirsher { 3404adfc5217SJeff Kirsher struct cnic_ops *c_ops; 3405adfc5217SJeff Kirsher 3406adfc5217SJeff Kirsher if (!bnapi->cnic_present) 3407adfc5217SJeff Kirsher return; 3408adfc5217SJeff Kirsher 3409adfc5217SJeff Kirsher rcu_read_lock(); 3410adfc5217SJeff Kirsher c_ops = rcu_dereference(bp->cnic_ops); 3411adfc5217SJeff Kirsher if (c_ops) 3412adfc5217SJeff Kirsher bnapi->cnic_tag = c_ops->cnic_handler(bp->cnic_data, 3413adfc5217SJeff Kirsher bnapi->status_blk.msi); 3414adfc5217SJeff Kirsher rcu_read_unlock(); 3415adfc5217SJeff Kirsher } 3416adfc5217SJeff Kirsher #endif 3417adfc5217SJeff Kirsher 3418adfc5217SJeff Kirsher static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) 3419adfc5217SJeff Kirsher { 3420adfc5217SJeff Kirsher struct status_block *sblk = bnapi->status_blk.msi; 3421adfc5217SJeff Kirsher u32 status_attn_bits = sblk->status_attn_bits; 3422adfc5217SJeff Kirsher u32 status_attn_bits_ack = sblk->status_attn_bits_ack; 3423adfc5217SJeff Kirsher 3424adfc5217SJeff Kirsher if ((status_attn_bits & STATUS_ATTN_EVENTS) != 3425adfc5217SJeff Kirsher (status_attn_bits_ack & STATUS_ATTN_EVENTS)) { 3426adfc5217SJeff Kirsher 3427adfc5217SJeff Kirsher bnx2_phy_int(bp, bnapi); 3428adfc5217SJeff Kirsher 3429adfc5217SJeff Kirsher /* This is needed to take care of transient status 3430adfc5217SJeff Kirsher * during link changes. 3431adfc5217SJeff Kirsher */ 3432adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, 3433adfc5217SJeff Kirsher bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 3434adfc5217SJeff Kirsher REG_RD(bp, BNX2_HC_COMMAND); 3435adfc5217SJeff Kirsher } 3436adfc5217SJeff Kirsher } 3437adfc5217SJeff Kirsher 3438adfc5217SJeff Kirsher static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi, 3439adfc5217SJeff Kirsher int work_done, int budget) 3440adfc5217SJeff Kirsher { 3441adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 3442adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 3443adfc5217SJeff Kirsher 3444adfc5217SJeff Kirsher if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons) 3445adfc5217SJeff Kirsher bnx2_tx_int(bp, bnapi, 0); 3446adfc5217SJeff Kirsher 3447adfc5217SJeff Kirsher if (bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) 3448adfc5217SJeff Kirsher work_done += bnx2_rx_int(bp, bnapi, budget - work_done); 3449adfc5217SJeff Kirsher 3450adfc5217SJeff Kirsher return work_done; 3451adfc5217SJeff Kirsher } 3452adfc5217SJeff Kirsher 3453adfc5217SJeff Kirsher static int bnx2_poll_msix(struct napi_struct *napi, int budget) 3454adfc5217SJeff Kirsher { 3455adfc5217SJeff Kirsher struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); 3456adfc5217SJeff Kirsher struct bnx2 *bp = bnapi->bp; 3457adfc5217SJeff Kirsher int work_done = 0; 3458adfc5217SJeff Kirsher struct status_block_msix *sblk = bnapi->status_blk.msix; 3459adfc5217SJeff Kirsher 3460adfc5217SJeff Kirsher while (1) { 3461adfc5217SJeff Kirsher work_done = bnx2_poll_work(bp, bnapi, work_done, budget); 3462adfc5217SJeff Kirsher if (unlikely(work_done >= budget)) 3463adfc5217SJeff Kirsher break; 3464adfc5217SJeff Kirsher 3465adfc5217SJeff Kirsher bnapi->last_status_idx = sblk->status_idx; 3466adfc5217SJeff Kirsher /* status idx must be read before checking for more work. */ 3467adfc5217SJeff Kirsher rmb(); 3468adfc5217SJeff Kirsher if (likely(!bnx2_has_fast_work(bnapi))) { 3469adfc5217SJeff Kirsher 3470adfc5217SJeff Kirsher napi_complete(napi); 3471adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | 3472adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 3473adfc5217SJeff Kirsher bnapi->last_status_idx); 3474adfc5217SJeff Kirsher break; 3475adfc5217SJeff Kirsher } 3476adfc5217SJeff Kirsher } 3477adfc5217SJeff Kirsher return work_done; 3478adfc5217SJeff Kirsher } 3479adfc5217SJeff Kirsher 3480adfc5217SJeff Kirsher static int bnx2_poll(struct napi_struct *napi, int budget) 3481adfc5217SJeff Kirsher { 3482adfc5217SJeff Kirsher struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi); 3483adfc5217SJeff Kirsher struct bnx2 *bp = bnapi->bp; 3484adfc5217SJeff Kirsher int work_done = 0; 3485adfc5217SJeff Kirsher struct status_block *sblk = bnapi->status_blk.msi; 3486adfc5217SJeff Kirsher 3487adfc5217SJeff Kirsher while (1) { 3488adfc5217SJeff Kirsher bnx2_poll_link(bp, bnapi); 3489adfc5217SJeff Kirsher 3490adfc5217SJeff Kirsher work_done = bnx2_poll_work(bp, bnapi, work_done, budget); 3491adfc5217SJeff Kirsher 3492adfc5217SJeff Kirsher #ifdef BCM_CNIC 3493adfc5217SJeff Kirsher bnx2_poll_cnic(bp, bnapi); 3494adfc5217SJeff Kirsher #endif 3495adfc5217SJeff Kirsher 3496adfc5217SJeff Kirsher /* bnapi->last_status_idx is used below to tell the hw how 3497adfc5217SJeff Kirsher * much work has been processed, so we must read it before 3498adfc5217SJeff Kirsher * checking for more work. 3499adfc5217SJeff Kirsher */ 3500adfc5217SJeff Kirsher bnapi->last_status_idx = sblk->status_idx; 3501adfc5217SJeff Kirsher 3502adfc5217SJeff Kirsher if (unlikely(work_done >= budget)) 3503adfc5217SJeff Kirsher break; 3504adfc5217SJeff Kirsher 3505adfc5217SJeff Kirsher rmb(); 3506adfc5217SJeff Kirsher if (likely(!bnx2_has_work(bnapi))) { 3507adfc5217SJeff Kirsher napi_complete(napi); 3508adfc5217SJeff Kirsher if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) { 3509adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3510adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 3511adfc5217SJeff Kirsher bnapi->last_status_idx); 3512adfc5217SJeff Kirsher break; 3513adfc5217SJeff Kirsher } 3514adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3515adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 3516adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_MASK_INT | 3517adfc5217SJeff Kirsher bnapi->last_status_idx); 3518adfc5217SJeff Kirsher 3519adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 3520adfc5217SJeff Kirsher BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 3521adfc5217SJeff Kirsher bnapi->last_status_idx); 3522adfc5217SJeff Kirsher break; 3523adfc5217SJeff Kirsher } 3524adfc5217SJeff Kirsher } 3525adfc5217SJeff Kirsher 3526adfc5217SJeff Kirsher return work_done; 3527adfc5217SJeff Kirsher } 3528adfc5217SJeff Kirsher 3529adfc5217SJeff Kirsher /* Called with rtnl_lock from vlan functions and also netif_tx_lock 3530adfc5217SJeff Kirsher * from set_multicast. 3531adfc5217SJeff Kirsher */ 3532adfc5217SJeff Kirsher static void 3533adfc5217SJeff Kirsher bnx2_set_rx_mode(struct net_device *dev) 3534adfc5217SJeff Kirsher { 3535adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 3536adfc5217SJeff Kirsher u32 rx_mode, sort_mode; 3537adfc5217SJeff Kirsher struct netdev_hw_addr *ha; 3538adfc5217SJeff Kirsher int i; 3539adfc5217SJeff Kirsher 3540adfc5217SJeff Kirsher if (!netif_running(dev)) 3541adfc5217SJeff Kirsher return; 3542adfc5217SJeff Kirsher 3543adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 3544adfc5217SJeff Kirsher 3545adfc5217SJeff Kirsher rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS | 3546adfc5217SJeff Kirsher BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG); 3547adfc5217SJeff Kirsher sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN; 3548adfc5217SJeff Kirsher if (!(dev->features & NETIF_F_HW_VLAN_RX) && 3549adfc5217SJeff Kirsher (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) 3550adfc5217SJeff Kirsher rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; 3551adfc5217SJeff Kirsher if (dev->flags & IFF_PROMISC) { 3552adfc5217SJeff Kirsher /* Promiscuous mode. */ 3553adfc5217SJeff Kirsher rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; 3554adfc5217SJeff Kirsher sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN | 3555adfc5217SJeff Kirsher BNX2_RPM_SORT_USER0_PROM_VLAN; 3556adfc5217SJeff Kirsher } 3557adfc5217SJeff Kirsher else if (dev->flags & IFF_ALLMULTI) { 3558adfc5217SJeff Kirsher for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 3559adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), 3560adfc5217SJeff Kirsher 0xffffffff); 3561adfc5217SJeff Kirsher } 3562adfc5217SJeff Kirsher sort_mode |= BNX2_RPM_SORT_USER0_MC_EN; 3563adfc5217SJeff Kirsher } 3564adfc5217SJeff Kirsher else { 3565adfc5217SJeff Kirsher /* Accept one or more multicast(s). */ 3566adfc5217SJeff Kirsher u32 mc_filter[NUM_MC_HASH_REGISTERS]; 3567adfc5217SJeff Kirsher u32 regidx; 3568adfc5217SJeff Kirsher u32 bit; 3569adfc5217SJeff Kirsher u32 crc; 3570adfc5217SJeff Kirsher 3571adfc5217SJeff Kirsher memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS); 3572adfc5217SJeff Kirsher 3573adfc5217SJeff Kirsher netdev_for_each_mc_addr(ha, dev) { 3574adfc5217SJeff Kirsher crc = ether_crc_le(ETH_ALEN, ha->addr); 3575adfc5217SJeff Kirsher bit = crc & 0xff; 3576adfc5217SJeff Kirsher regidx = (bit & 0xe0) >> 5; 3577adfc5217SJeff Kirsher bit &= 0x1f; 3578adfc5217SJeff Kirsher mc_filter[regidx] |= (1 << bit); 3579adfc5217SJeff Kirsher } 3580adfc5217SJeff Kirsher 3581adfc5217SJeff Kirsher for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 3582adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), 3583adfc5217SJeff Kirsher mc_filter[i]); 3584adfc5217SJeff Kirsher } 3585adfc5217SJeff Kirsher 3586adfc5217SJeff Kirsher sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN; 3587adfc5217SJeff Kirsher } 3588adfc5217SJeff Kirsher 3589adfc5217SJeff Kirsher if (netdev_uc_count(dev) > BNX2_MAX_UNICAST_ADDRESSES) { 3590adfc5217SJeff Kirsher rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; 3591adfc5217SJeff Kirsher sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN | 3592adfc5217SJeff Kirsher BNX2_RPM_SORT_USER0_PROM_VLAN; 3593adfc5217SJeff Kirsher } else if (!(dev->flags & IFF_PROMISC)) { 3594adfc5217SJeff Kirsher /* Add all entries into to the match filter list */ 3595adfc5217SJeff Kirsher i = 0; 3596adfc5217SJeff Kirsher netdev_for_each_uc_addr(ha, dev) { 3597adfc5217SJeff Kirsher bnx2_set_mac_addr(bp, ha->addr, 3598adfc5217SJeff Kirsher i + BNX2_START_UNICAST_ADDRESS_INDEX); 3599adfc5217SJeff Kirsher sort_mode |= (1 << 3600adfc5217SJeff Kirsher (i + BNX2_START_UNICAST_ADDRESS_INDEX)); 3601adfc5217SJeff Kirsher i++; 3602adfc5217SJeff Kirsher } 3603adfc5217SJeff Kirsher 3604adfc5217SJeff Kirsher } 3605adfc5217SJeff Kirsher 3606adfc5217SJeff Kirsher if (rx_mode != bp->rx_mode) { 3607adfc5217SJeff Kirsher bp->rx_mode = rx_mode; 3608adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode); 3609adfc5217SJeff Kirsher } 3610adfc5217SJeff Kirsher 3611adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); 3612adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode); 3613adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA); 3614adfc5217SJeff Kirsher 3615adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 3616adfc5217SJeff Kirsher } 3617adfc5217SJeff Kirsher 36187880b72eSfrançois romieu static int 3619adfc5217SJeff Kirsher check_fw_section(const struct firmware *fw, 3620adfc5217SJeff Kirsher const struct bnx2_fw_file_section *section, 3621adfc5217SJeff Kirsher u32 alignment, bool non_empty) 3622adfc5217SJeff Kirsher { 3623adfc5217SJeff Kirsher u32 offset = be32_to_cpu(section->offset); 3624adfc5217SJeff Kirsher u32 len = be32_to_cpu(section->len); 3625adfc5217SJeff Kirsher 3626adfc5217SJeff Kirsher if ((offset == 0 && len != 0) || offset >= fw->size || offset & 3) 3627adfc5217SJeff Kirsher return -EINVAL; 3628adfc5217SJeff Kirsher if ((non_empty && len == 0) || len > fw->size - offset || 3629adfc5217SJeff Kirsher len & (alignment - 1)) 3630adfc5217SJeff Kirsher return -EINVAL; 3631adfc5217SJeff Kirsher return 0; 3632adfc5217SJeff Kirsher } 3633adfc5217SJeff Kirsher 36347880b72eSfrançois romieu static int 3635adfc5217SJeff Kirsher check_mips_fw_entry(const struct firmware *fw, 3636adfc5217SJeff Kirsher const struct bnx2_mips_fw_file_entry *entry) 3637adfc5217SJeff Kirsher { 3638adfc5217SJeff Kirsher if (check_fw_section(fw, &entry->text, 4, true) || 3639adfc5217SJeff Kirsher check_fw_section(fw, &entry->data, 4, false) || 3640adfc5217SJeff Kirsher check_fw_section(fw, &entry->rodata, 4, false)) 3641adfc5217SJeff Kirsher return -EINVAL; 3642adfc5217SJeff Kirsher return 0; 3643adfc5217SJeff Kirsher } 3644adfc5217SJeff Kirsher 36457880b72eSfrançois romieu static void bnx2_release_firmware(struct bnx2 *bp) 36467880b72eSfrançois romieu { 36477880b72eSfrançois romieu if (bp->rv2p_firmware) { 36487880b72eSfrançois romieu release_firmware(bp->mips_firmware); 36497880b72eSfrançois romieu release_firmware(bp->rv2p_firmware); 36507880b72eSfrançois romieu bp->rv2p_firmware = NULL; 36517880b72eSfrançois romieu } 36527880b72eSfrançois romieu } 36537880b72eSfrançois romieu 36547880b72eSfrançois romieu static int bnx2_request_uncached_firmware(struct bnx2 *bp) 3655adfc5217SJeff Kirsher { 3656adfc5217SJeff Kirsher const char *mips_fw_file, *rv2p_fw_file; 3657adfc5217SJeff Kirsher const struct bnx2_mips_fw_file *mips_fw; 3658adfc5217SJeff Kirsher const struct bnx2_rv2p_fw_file *rv2p_fw; 3659adfc5217SJeff Kirsher int rc; 3660adfc5217SJeff Kirsher 3661adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 3662adfc5217SJeff Kirsher mips_fw_file = FW_MIPS_FILE_09; 3663adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5709_A0) || 3664adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5709_A1)) 3665adfc5217SJeff Kirsher rv2p_fw_file = FW_RV2P_FILE_09_Ax; 3666adfc5217SJeff Kirsher else 3667adfc5217SJeff Kirsher rv2p_fw_file = FW_RV2P_FILE_09; 3668adfc5217SJeff Kirsher } else { 3669adfc5217SJeff Kirsher mips_fw_file = FW_MIPS_FILE_06; 3670adfc5217SJeff Kirsher rv2p_fw_file = FW_RV2P_FILE_06; 3671adfc5217SJeff Kirsher } 3672adfc5217SJeff Kirsher 3673adfc5217SJeff Kirsher rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev); 3674adfc5217SJeff Kirsher if (rc) { 3675adfc5217SJeff Kirsher pr_err("Can't load firmware file \"%s\"\n", mips_fw_file); 36767880b72eSfrançois romieu goto out; 3677adfc5217SJeff Kirsher } 3678adfc5217SJeff Kirsher 3679adfc5217SJeff Kirsher rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev); 3680adfc5217SJeff Kirsher if (rc) { 3681adfc5217SJeff Kirsher pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file); 36827880b72eSfrançois romieu goto err_release_mips_firmware; 3683adfc5217SJeff Kirsher } 3684adfc5217SJeff Kirsher mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data; 3685adfc5217SJeff Kirsher rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data; 3686adfc5217SJeff Kirsher if (bp->mips_firmware->size < sizeof(*mips_fw) || 3687adfc5217SJeff Kirsher check_mips_fw_entry(bp->mips_firmware, &mips_fw->com) || 3688adfc5217SJeff Kirsher check_mips_fw_entry(bp->mips_firmware, &mips_fw->cp) || 3689adfc5217SJeff Kirsher check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) || 3690adfc5217SJeff Kirsher check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) || 3691adfc5217SJeff Kirsher check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) { 3692adfc5217SJeff Kirsher pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file); 36937880b72eSfrançois romieu rc = -EINVAL; 36947880b72eSfrançois romieu goto err_release_firmware; 3695adfc5217SJeff Kirsher } 3696adfc5217SJeff Kirsher if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) || 3697adfc5217SJeff Kirsher check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) || 3698adfc5217SJeff Kirsher check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) { 3699adfc5217SJeff Kirsher pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file); 37007880b72eSfrançois romieu rc = -EINVAL; 37017880b72eSfrançois romieu goto err_release_firmware; 37027880b72eSfrançois romieu } 37037880b72eSfrançois romieu out: 37047880b72eSfrançois romieu return rc; 37057880b72eSfrançois romieu 37067880b72eSfrançois romieu err_release_firmware: 37077880b72eSfrançois romieu release_firmware(bp->rv2p_firmware); 37087880b72eSfrançois romieu bp->rv2p_firmware = NULL; 37097880b72eSfrançois romieu err_release_mips_firmware: 37107880b72eSfrançois romieu release_firmware(bp->mips_firmware); 37117880b72eSfrançois romieu goto out; 3712adfc5217SJeff Kirsher } 3713adfc5217SJeff Kirsher 37147880b72eSfrançois romieu static int bnx2_request_firmware(struct bnx2 *bp) 37157880b72eSfrançois romieu { 37167880b72eSfrançois romieu return bp->rv2p_firmware ? 0 : bnx2_request_uncached_firmware(bp); 3717adfc5217SJeff Kirsher } 3718adfc5217SJeff Kirsher 3719adfc5217SJeff Kirsher static u32 3720adfc5217SJeff Kirsher rv2p_fw_fixup(u32 rv2p_proc, int idx, u32 loc, u32 rv2p_code) 3721adfc5217SJeff Kirsher { 3722adfc5217SJeff Kirsher switch (idx) { 3723adfc5217SJeff Kirsher case RV2P_P1_FIXUP_PAGE_SIZE_IDX: 3724adfc5217SJeff Kirsher rv2p_code &= ~RV2P_BD_PAGE_SIZE_MSK; 3725adfc5217SJeff Kirsher rv2p_code |= RV2P_BD_PAGE_SIZE; 3726adfc5217SJeff Kirsher break; 3727adfc5217SJeff Kirsher } 3728adfc5217SJeff Kirsher return rv2p_code; 3729adfc5217SJeff Kirsher } 3730adfc5217SJeff Kirsher 3731adfc5217SJeff Kirsher static int 3732adfc5217SJeff Kirsher load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc, 3733adfc5217SJeff Kirsher const struct bnx2_rv2p_fw_file_entry *fw_entry) 3734adfc5217SJeff Kirsher { 3735adfc5217SJeff Kirsher u32 rv2p_code_len, file_offset; 3736adfc5217SJeff Kirsher __be32 *rv2p_code; 3737adfc5217SJeff Kirsher int i; 3738adfc5217SJeff Kirsher u32 val, cmd, addr; 3739adfc5217SJeff Kirsher 3740adfc5217SJeff Kirsher rv2p_code_len = be32_to_cpu(fw_entry->rv2p.len); 3741adfc5217SJeff Kirsher file_offset = be32_to_cpu(fw_entry->rv2p.offset); 3742adfc5217SJeff Kirsher 3743adfc5217SJeff Kirsher rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset); 3744adfc5217SJeff Kirsher 3745adfc5217SJeff Kirsher if (rv2p_proc == RV2P_PROC1) { 3746adfc5217SJeff Kirsher cmd = BNX2_RV2P_PROC1_ADDR_CMD_RDWR; 3747adfc5217SJeff Kirsher addr = BNX2_RV2P_PROC1_ADDR_CMD; 3748adfc5217SJeff Kirsher } else { 3749adfc5217SJeff Kirsher cmd = BNX2_RV2P_PROC2_ADDR_CMD_RDWR; 3750adfc5217SJeff Kirsher addr = BNX2_RV2P_PROC2_ADDR_CMD; 3751adfc5217SJeff Kirsher } 3752adfc5217SJeff Kirsher 3753adfc5217SJeff Kirsher for (i = 0; i < rv2p_code_len; i += 8) { 3754adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code)); 3755adfc5217SJeff Kirsher rv2p_code++; 3756adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code)); 3757adfc5217SJeff Kirsher rv2p_code++; 3758adfc5217SJeff Kirsher 3759adfc5217SJeff Kirsher val = (i / 8) | cmd; 3760adfc5217SJeff Kirsher REG_WR(bp, addr, val); 3761adfc5217SJeff Kirsher } 3762adfc5217SJeff Kirsher 3763adfc5217SJeff Kirsher rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset); 3764adfc5217SJeff Kirsher for (i = 0; i < 8; i++) { 3765adfc5217SJeff Kirsher u32 loc, code; 3766adfc5217SJeff Kirsher 3767adfc5217SJeff Kirsher loc = be32_to_cpu(fw_entry->fixup[i]); 3768adfc5217SJeff Kirsher if (loc && ((loc * 4) < rv2p_code_len)) { 3769adfc5217SJeff Kirsher code = be32_to_cpu(*(rv2p_code + loc - 1)); 3770adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code); 3771adfc5217SJeff Kirsher code = be32_to_cpu(*(rv2p_code + loc)); 3772adfc5217SJeff Kirsher code = rv2p_fw_fixup(rv2p_proc, i, loc, code); 3773adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_INSTR_LOW, code); 3774adfc5217SJeff Kirsher 3775adfc5217SJeff Kirsher val = (loc / 2) | cmd; 3776adfc5217SJeff Kirsher REG_WR(bp, addr, val); 3777adfc5217SJeff Kirsher } 3778adfc5217SJeff Kirsher } 3779adfc5217SJeff Kirsher 3780adfc5217SJeff Kirsher /* Reset the processor, un-stall is done later. */ 3781adfc5217SJeff Kirsher if (rv2p_proc == RV2P_PROC1) { 3782adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET); 3783adfc5217SJeff Kirsher } 3784adfc5217SJeff Kirsher else { 3785adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET); 3786adfc5217SJeff Kirsher } 3787adfc5217SJeff Kirsher 3788adfc5217SJeff Kirsher return 0; 3789adfc5217SJeff Kirsher } 3790adfc5217SJeff Kirsher 3791adfc5217SJeff Kirsher static int 3792adfc5217SJeff Kirsher load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg, 3793adfc5217SJeff Kirsher const struct bnx2_mips_fw_file_entry *fw_entry) 3794adfc5217SJeff Kirsher { 3795adfc5217SJeff Kirsher u32 addr, len, file_offset; 3796adfc5217SJeff Kirsher __be32 *data; 3797adfc5217SJeff Kirsher u32 offset; 3798adfc5217SJeff Kirsher u32 val; 3799adfc5217SJeff Kirsher 3800adfc5217SJeff Kirsher /* Halt the CPU. */ 3801adfc5217SJeff Kirsher val = bnx2_reg_rd_ind(bp, cpu_reg->mode); 3802adfc5217SJeff Kirsher val |= cpu_reg->mode_value_halt; 3803adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->mode, val); 3804adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear); 3805adfc5217SJeff Kirsher 3806adfc5217SJeff Kirsher /* Load the Text area. */ 3807adfc5217SJeff Kirsher addr = be32_to_cpu(fw_entry->text.addr); 3808adfc5217SJeff Kirsher len = be32_to_cpu(fw_entry->text.len); 3809adfc5217SJeff Kirsher file_offset = be32_to_cpu(fw_entry->text.offset); 3810adfc5217SJeff Kirsher data = (__be32 *)(bp->mips_firmware->data + file_offset); 3811adfc5217SJeff Kirsher 3812adfc5217SJeff Kirsher offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); 3813adfc5217SJeff Kirsher if (len) { 3814adfc5217SJeff Kirsher int j; 3815adfc5217SJeff Kirsher 3816adfc5217SJeff Kirsher for (j = 0; j < (len / 4); j++, offset += 4) 3817adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); 3818adfc5217SJeff Kirsher } 3819adfc5217SJeff Kirsher 3820adfc5217SJeff Kirsher /* Load the Data area. */ 3821adfc5217SJeff Kirsher addr = be32_to_cpu(fw_entry->data.addr); 3822adfc5217SJeff Kirsher len = be32_to_cpu(fw_entry->data.len); 3823adfc5217SJeff Kirsher file_offset = be32_to_cpu(fw_entry->data.offset); 3824adfc5217SJeff Kirsher data = (__be32 *)(bp->mips_firmware->data + file_offset); 3825adfc5217SJeff Kirsher 3826adfc5217SJeff Kirsher offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); 3827adfc5217SJeff Kirsher if (len) { 3828adfc5217SJeff Kirsher int j; 3829adfc5217SJeff Kirsher 3830adfc5217SJeff Kirsher for (j = 0; j < (len / 4); j++, offset += 4) 3831adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); 3832adfc5217SJeff Kirsher } 3833adfc5217SJeff Kirsher 3834adfc5217SJeff Kirsher /* Load the Read-Only area. */ 3835adfc5217SJeff Kirsher addr = be32_to_cpu(fw_entry->rodata.addr); 3836adfc5217SJeff Kirsher len = be32_to_cpu(fw_entry->rodata.len); 3837adfc5217SJeff Kirsher file_offset = be32_to_cpu(fw_entry->rodata.offset); 3838adfc5217SJeff Kirsher data = (__be32 *)(bp->mips_firmware->data + file_offset); 3839adfc5217SJeff Kirsher 3840adfc5217SJeff Kirsher offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base); 3841adfc5217SJeff Kirsher if (len) { 3842adfc5217SJeff Kirsher int j; 3843adfc5217SJeff Kirsher 3844adfc5217SJeff Kirsher for (j = 0; j < (len / 4); j++, offset += 4) 3845adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j])); 3846adfc5217SJeff Kirsher } 3847adfc5217SJeff Kirsher 3848adfc5217SJeff Kirsher /* Clear the pre-fetch instruction. */ 3849adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->inst, 0); 3850adfc5217SJeff Kirsher 3851adfc5217SJeff Kirsher val = be32_to_cpu(fw_entry->start_addr); 3852adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->pc, val); 3853adfc5217SJeff Kirsher 3854adfc5217SJeff Kirsher /* Start the CPU. */ 3855adfc5217SJeff Kirsher val = bnx2_reg_rd_ind(bp, cpu_reg->mode); 3856adfc5217SJeff Kirsher val &= ~cpu_reg->mode_value_halt; 3857adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear); 3858adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, cpu_reg->mode, val); 3859adfc5217SJeff Kirsher 3860adfc5217SJeff Kirsher return 0; 3861adfc5217SJeff Kirsher } 3862adfc5217SJeff Kirsher 3863adfc5217SJeff Kirsher static int 3864adfc5217SJeff Kirsher bnx2_init_cpus(struct bnx2 *bp) 3865adfc5217SJeff Kirsher { 3866adfc5217SJeff Kirsher const struct bnx2_mips_fw_file *mips_fw = 3867adfc5217SJeff Kirsher (const struct bnx2_mips_fw_file *) bp->mips_firmware->data; 3868adfc5217SJeff Kirsher const struct bnx2_rv2p_fw_file *rv2p_fw = 3869adfc5217SJeff Kirsher (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data; 3870adfc5217SJeff Kirsher int rc; 3871adfc5217SJeff Kirsher 3872adfc5217SJeff Kirsher /* Initialize the RV2P processor. */ 3873adfc5217SJeff Kirsher load_rv2p_fw(bp, RV2P_PROC1, &rv2p_fw->proc1); 3874adfc5217SJeff Kirsher load_rv2p_fw(bp, RV2P_PROC2, &rv2p_fw->proc2); 3875adfc5217SJeff Kirsher 3876adfc5217SJeff Kirsher /* Initialize the RX Processor. */ 3877adfc5217SJeff Kirsher rc = load_cpu_fw(bp, &cpu_reg_rxp, &mips_fw->rxp); 3878adfc5217SJeff Kirsher if (rc) 3879adfc5217SJeff Kirsher goto init_cpu_err; 3880adfc5217SJeff Kirsher 3881adfc5217SJeff Kirsher /* Initialize the TX Processor. */ 3882adfc5217SJeff Kirsher rc = load_cpu_fw(bp, &cpu_reg_txp, &mips_fw->txp); 3883adfc5217SJeff Kirsher if (rc) 3884adfc5217SJeff Kirsher goto init_cpu_err; 3885adfc5217SJeff Kirsher 3886adfc5217SJeff Kirsher /* Initialize the TX Patch-up Processor. */ 3887adfc5217SJeff Kirsher rc = load_cpu_fw(bp, &cpu_reg_tpat, &mips_fw->tpat); 3888adfc5217SJeff Kirsher if (rc) 3889adfc5217SJeff Kirsher goto init_cpu_err; 3890adfc5217SJeff Kirsher 3891adfc5217SJeff Kirsher /* Initialize the Completion Processor. */ 3892adfc5217SJeff Kirsher rc = load_cpu_fw(bp, &cpu_reg_com, &mips_fw->com); 3893adfc5217SJeff Kirsher if (rc) 3894adfc5217SJeff Kirsher goto init_cpu_err; 3895adfc5217SJeff Kirsher 3896adfc5217SJeff Kirsher /* Initialize the Command Processor. */ 3897adfc5217SJeff Kirsher rc = load_cpu_fw(bp, &cpu_reg_cp, &mips_fw->cp); 3898adfc5217SJeff Kirsher 3899adfc5217SJeff Kirsher init_cpu_err: 3900adfc5217SJeff Kirsher return rc; 3901adfc5217SJeff Kirsher } 3902adfc5217SJeff Kirsher 3903adfc5217SJeff Kirsher static int 3904adfc5217SJeff Kirsher bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) 3905adfc5217SJeff Kirsher { 3906adfc5217SJeff Kirsher u16 pmcsr; 3907adfc5217SJeff Kirsher 3908adfc5217SJeff Kirsher pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); 3909adfc5217SJeff Kirsher 3910adfc5217SJeff Kirsher switch (state) { 3911adfc5217SJeff Kirsher case PCI_D0: { 3912adfc5217SJeff Kirsher u32 val; 3913adfc5217SJeff Kirsher 3914adfc5217SJeff Kirsher pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, 3915adfc5217SJeff Kirsher (pmcsr & ~PCI_PM_CTRL_STATE_MASK) | 3916adfc5217SJeff Kirsher PCI_PM_CTRL_PME_STATUS); 3917adfc5217SJeff Kirsher 3918adfc5217SJeff Kirsher if (pmcsr & PCI_PM_CTRL_STATE_MASK) 3919adfc5217SJeff Kirsher /* delay required during transition out of D3hot */ 3920adfc5217SJeff Kirsher msleep(20); 3921adfc5217SJeff Kirsher 3922adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_EMAC_MODE); 3923adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD; 3924adfc5217SJeff Kirsher val &= ~BNX2_EMAC_MODE_MPKT; 3925adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MODE, val); 3926adfc5217SJeff Kirsher 3927adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_RPM_CONFIG); 3928adfc5217SJeff Kirsher val &= ~BNX2_RPM_CONFIG_ACPI_ENA; 3929adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_CONFIG, val); 3930adfc5217SJeff Kirsher break; 3931adfc5217SJeff Kirsher } 3932adfc5217SJeff Kirsher case PCI_D3hot: { 3933adfc5217SJeff Kirsher int i; 3934adfc5217SJeff Kirsher u32 val, wol_msg; 3935adfc5217SJeff Kirsher 3936adfc5217SJeff Kirsher if (bp->wol) { 3937adfc5217SJeff Kirsher u32 advertising; 3938adfc5217SJeff Kirsher u8 autoneg; 3939adfc5217SJeff Kirsher 3940adfc5217SJeff Kirsher autoneg = bp->autoneg; 3941adfc5217SJeff Kirsher advertising = bp->advertising; 3942adfc5217SJeff Kirsher 3943adfc5217SJeff Kirsher if (bp->phy_port == PORT_TP) { 3944adfc5217SJeff Kirsher bp->autoneg = AUTONEG_SPEED; 3945adfc5217SJeff Kirsher bp->advertising = ADVERTISED_10baseT_Half | 3946adfc5217SJeff Kirsher ADVERTISED_10baseT_Full | 3947adfc5217SJeff Kirsher ADVERTISED_100baseT_Half | 3948adfc5217SJeff Kirsher ADVERTISED_100baseT_Full | 3949adfc5217SJeff Kirsher ADVERTISED_Autoneg; 3950adfc5217SJeff Kirsher } 3951adfc5217SJeff Kirsher 3952adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 3953adfc5217SJeff Kirsher bnx2_setup_phy(bp, bp->phy_port); 3954adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 3955adfc5217SJeff Kirsher 3956adfc5217SJeff Kirsher bp->autoneg = autoneg; 3957adfc5217SJeff Kirsher bp->advertising = advertising; 3958adfc5217SJeff Kirsher 3959adfc5217SJeff Kirsher bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0); 3960adfc5217SJeff Kirsher 3961adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_EMAC_MODE); 3962adfc5217SJeff Kirsher 3963adfc5217SJeff Kirsher /* Enable port mode. */ 3964adfc5217SJeff Kirsher val &= ~BNX2_EMAC_MODE_PORT; 3965adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_MPKT_RCVD | 3966adfc5217SJeff Kirsher BNX2_EMAC_MODE_ACPI_RCVD | 3967adfc5217SJeff Kirsher BNX2_EMAC_MODE_MPKT; 3968adfc5217SJeff Kirsher if (bp->phy_port == PORT_TP) 3969adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_MII; 3970adfc5217SJeff Kirsher else { 3971adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_PORT_GMII; 3972adfc5217SJeff Kirsher if (bp->line_speed == SPEED_2500) 3973adfc5217SJeff Kirsher val |= BNX2_EMAC_MODE_25G_MODE; 3974adfc5217SJeff Kirsher } 3975adfc5217SJeff Kirsher 3976adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MODE, val); 3977adfc5217SJeff Kirsher 3978adfc5217SJeff Kirsher /* receive all multicast */ 3979adfc5217SJeff Kirsher for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { 3980adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), 3981adfc5217SJeff Kirsher 0xffffffff); 3982adfc5217SJeff Kirsher } 3983adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_RX_MODE, 3984adfc5217SJeff Kirsher BNX2_EMAC_RX_MODE_SORT_MODE); 3985adfc5217SJeff Kirsher 3986adfc5217SJeff Kirsher val = 1 | BNX2_RPM_SORT_USER0_BC_EN | 3987adfc5217SJeff Kirsher BNX2_RPM_SORT_USER0_MC_EN; 3988adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); 3989adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, val); 3990adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_SORT_USER0, val | 3991adfc5217SJeff Kirsher BNX2_RPM_SORT_USER0_ENA); 3992adfc5217SJeff Kirsher 3993adfc5217SJeff Kirsher /* Need to enable EMAC and RPM for WOL. */ 3994adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 3995adfc5217SJeff Kirsher BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | 3996adfc5217SJeff Kirsher BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | 3997adfc5217SJeff Kirsher BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE); 3998adfc5217SJeff Kirsher 3999adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_RPM_CONFIG); 4000adfc5217SJeff Kirsher val &= ~BNX2_RPM_CONFIG_ACPI_ENA; 4001adfc5217SJeff Kirsher REG_WR(bp, BNX2_RPM_CONFIG, val); 4002adfc5217SJeff Kirsher 4003adfc5217SJeff Kirsher wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL; 4004adfc5217SJeff Kirsher } 4005adfc5217SJeff Kirsher else { 4006adfc5217SJeff Kirsher wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; 4007adfc5217SJeff Kirsher } 4008adfc5217SJeff Kirsher 4009adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_NO_WOL)) 4010adfc5217SJeff Kirsher bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 4011adfc5217SJeff Kirsher 1, 0); 4012adfc5217SJeff Kirsher 4013adfc5217SJeff Kirsher pmcsr &= ~PCI_PM_CTRL_STATE_MASK; 4014adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || 4015adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5706_A1)) { 4016adfc5217SJeff Kirsher 4017adfc5217SJeff Kirsher if (bp->wol) 4018adfc5217SJeff Kirsher pmcsr |= 3; 4019adfc5217SJeff Kirsher } 4020adfc5217SJeff Kirsher else { 4021adfc5217SJeff Kirsher pmcsr |= 3; 4022adfc5217SJeff Kirsher } 4023adfc5217SJeff Kirsher if (bp->wol) { 4024adfc5217SJeff Kirsher pmcsr |= PCI_PM_CTRL_PME_ENABLE; 4025adfc5217SJeff Kirsher } 4026adfc5217SJeff Kirsher pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, 4027adfc5217SJeff Kirsher pmcsr); 4028adfc5217SJeff Kirsher 4029adfc5217SJeff Kirsher /* No more memory access after this point until 4030adfc5217SJeff Kirsher * device is brought back to D0. 4031adfc5217SJeff Kirsher */ 4032adfc5217SJeff Kirsher udelay(50); 4033adfc5217SJeff Kirsher break; 4034adfc5217SJeff Kirsher } 4035adfc5217SJeff Kirsher default: 4036adfc5217SJeff Kirsher return -EINVAL; 4037adfc5217SJeff Kirsher } 4038adfc5217SJeff Kirsher return 0; 4039adfc5217SJeff Kirsher } 4040adfc5217SJeff Kirsher 4041adfc5217SJeff Kirsher static int 4042adfc5217SJeff Kirsher bnx2_acquire_nvram_lock(struct bnx2 *bp) 4043adfc5217SJeff Kirsher { 4044adfc5217SJeff Kirsher u32 val; 4045adfc5217SJeff Kirsher int j; 4046adfc5217SJeff Kirsher 4047adfc5217SJeff Kirsher /* Request access to the flash interface. */ 4048adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2); 4049adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4050adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_SW_ARB); 4051adfc5217SJeff Kirsher if (val & BNX2_NVM_SW_ARB_ARB_ARB2) 4052adfc5217SJeff Kirsher break; 4053adfc5217SJeff Kirsher 4054adfc5217SJeff Kirsher udelay(5); 4055adfc5217SJeff Kirsher } 4056adfc5217SJeff Kirsher 4057adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4058adfc5217SJeff Kirsher return -EBUSY; 4059adfc5217SJeff Kirsher 4060adfc5217SJeff Kirsher return 0; 4061adfc5217SJeff Kirsher } 4062adfc5217SJeff Kirsher 4063adfc5217SJeff Kirsher static int 4064adfc5217SJeff Kirsher bnx2_release_nvram_lock(struct bnx2 *bp) 4065adfc5217SJeff Kirsher { 4066adfc5217SJeff Kirsher int j; 4067adfc5217SJeff Kirsher u32 val; 4068adfc5217SJeff Kirsher 4069adfc5217SJeff Kirsher /* Relinquish nvram interface. */ 4070adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2); 4071adfc5217SJeff Kirsher 4072adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4073adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_SW_ARB); 4074adfc5217SJeff Kirsher if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2)) 4075adfc5217SJeff Kirsher break; 4076adfc5217SJeff Kirsher 4077adfc5217SJeff Kirsher udelay(5); 4078adfc5217SJeff Kirsher } 4079adfc5217SJeff Kirsher 4080adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4081adfc5217SJeff Kirsher return -EBUSY; 4082adfc5217SJeff Kirsher 4083adfc5217SJeff Kirsher return 0; 4084adfc5217SJeff Kirsher } 4085adfc5217SJeff Kirsher 4086adfc5217SJeff Kirsher 4087adfc5217SJeff Kirsher static int 4088adfc5217SJeff Kirsher bnx2_enable_nvram_write(struct bnx2 *bp) 4089adfc5217SJeff Kirsher { 4090adfc5217SJeff Kirsher u32 val; 4091adfc5217SJeff Kirsher 4092adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_CFG); 4093adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI); 4094adfc5217SJeff Kirsher 4095adfc5217SJeff Kirsher if (bp->flash_info->flags & BNX2_NV_WREN) { 4096adfc5217SJeff Kirsher int j; 4097adfc5217SJeff Kirsher 4098adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); 4099adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, 4100adfc5217SJeff Kirsher BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT); 4101adfc5217SJeff Kirsher 4102adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4103adfc5217SJeff Kirsher udelay(5); 4104adfc5217SJeff Kirsher 4105adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_COMMAND); 4106adfc5217SJeff Kirsher if (val & BNX2_NVM_COMMAND_DONE) 4107adfc5217SJeff Kirsher break; 4108adfc5217SJeff Kirsher } 4109adfc5217SJeff Kirsher 4110adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4111adfc5217SJeff Kirsher return -EBUSY; 4112adfc5217SJeff Kirsher } 4113adfc5217SJeff Kirsher return 0; 4114adfc5217SJeff Kirsher } 4115adfc5217SJeff Kirsher 4116adfc5217SJeff Kirsher static void 4117adfc5217SJeff Kirsher bnx2_disable_nvram_write(struct bnx2 *bp) 4118adfc5217SJeff Kirsher { 4119adfc5217SJeff Kirsher u32 val; 4120adfc5217SJeff Kirsher 4121adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_CFG); 4122adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN); 4123adfc5217SJeff Kirsher } 4124adfc5217SJeff Kirsher 4125adfc5217SJeff Kirsher 4126adfc5217SJeff Kirsher static void 4127adfc5217SJeff Kirsher bnx2_enable_nvram_access(struct bnx2 *bp) 4128adfc5217SJeff Kirsher { 4129adfc5217SJeff Kirsher u32 val; 4130adfc5217SJeff Kirsher 4131adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); 4132adfc5217SJeff Kirsher /* Enable both bits, even on read. */ 4133adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, 4134adfc5217SJeff Kirsher val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN); 4135adfc5217SJeff Kirsher } 4136adfc5217SJeff Kirsher 4137adfc5217SJeff Kirsher static void 4138adfc5217SJeff Kirsher bnx2_disable_nvram_access(struct bnx2 *bp) 4139adfc5217SJeff Kirsher { 4140adfc5217SJeff Kirsher u32 val; 4141adfc5217SJeff Kirsher 4142adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); 4143adfc5217SJeff Kirsher /* Disable both bits, even after read. */ 4144adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, 4145adfc5217SJeff Kirsher val & ~(BNX2_NVM_ACCESS_ENABLE_EN | 4146adfc5217SJeff Kirsher BNX2_NVM_ACCESS_ENABLE_WR_EN)); 4147adfc5217SJeff Kirsher } 4148adfc5217SJeff Kirsher 4149adfc5217SJeff Kirsher static int 4150adfc5217SJeff Kirsher bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset) 4151adfc5217SJeff Kirsher { 4152adfc5217SJeff Kirsher u32 cmd; 4153adfc5217SJeff Kirsher int j; 4154adfc5217SJeff Kirsher 4155adfc5217SJeff Kirsher if (bp->flash_info->flags & BNX2_NV_BUFFERED) 4156adfc5217SJeff Kirsher /* Buffered flash, no erase needed */ 4157adfc5217SJeff Kirsher return 0; 4158adfc5217SJeff Kirsher 4159adfc5217SJeff Kirsher /* Build an erase command */ 4160adfc5217SJeff Kirsher cmd = BNX2_NVM_COMMAND_ERASE | BNX2_NVM_COMMAND_WR | 4161adfc5217SJeff Kirsher BNX2_NVM_COMMAND_DOIT; 4162adfc5217SJeff Kirsher 4163adfc5217SJeff Kirsher /* Need to clear DONE bit separately. */ 4164adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); 4165adfc5217SJeff Kirsher 4166adfc5217SJeff Kirsher /* Address of the NVRAM to read from. */ 4167adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); 4168adfc5217SJeff Kirsher 4169adfc5217SJeff Kirsher /* Issue an erase command. */ 4170adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, cmd); 4171adfc5217SJeff Kirsher 4172adfc5217SJeff Kirsher /* Wait for completion. */ 4173adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4174adfc5217SJeff Kirsher u32 val; 4175adfc5217SJeff Kirsher 4176adfc5217SJeff Kirsher udelay(5); 4177adfc5217SJeff Kirsher 4178adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_COMMAND); 4179adfc5217SJeff Kirsher if (val & BNX2_NVM_COMMAND_DONE) 4180adfc5217SJeff Kirsher break; 4181adfc5217SJeff Kirsher } 4182adfc5217SJeff Kirsher 4183adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4184adfc5217SJeff Kirsher return -EBUSY; 4185adfc5217SJeff Kirsher 4186adfc5217SJeff Kirsher return 0; 4187adfc5217SJeff Kirsher } 4188adfc5217SJeff Kirsher 4189adfc5217SJeff Kirsher static int 4190adfc5217SJeff Kirsher bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags) 4191adfc5217SJeff Kirsher { 4192adfc5217SJeff Kirsher u32 cmd; 4193adfc5217SJeff Kirsher int j; 4194adfc5217SJeff Kirsher 4195adfc5217SJeff Kirsher /* Build the command word. */ 4196adfc5217SJeff Kirsher cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags; 4197adfc5217SJeff Kirsher 4198adfc5217SJeff Kirsher /* Calculate an offset of a buffered flash, not needed for 5709. */ 4199adfc5217SJeff Kirsher if (bp->flash_info->flags & BNX2_NV_TRANSLATE) { 4200adfc5217SJeff Kirsher offset = ((offset / bp->flash_info->page_size) << 4201adfc5217SJeff Kirsher bp->flash_info->page_bits) + 4202adfc5217SJeff Kirsher (offset % bp->flash_info->page_size); 4203adfc5217SJeff Kirsher } 4204adfc5217SJeff Kirsher 4205adfc5217SJeff Kirsher /* Need to clear DONE bit separately. */ 4206adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); 4207adfc5217SJeff Kirsher 4208adfc5217SJeff Kirsher /* Address of the NVRAM to read from. */ 4209adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); 4210adfc5217SJeff Kirsher 4211adfc5217SJeff Kirsher /* Issue a read command. */ 4212adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, cmd); 4213adfc5217SJeff Kirsher 4214adfc5217SJeff Kirsher /* Wait for completion. */ 4215adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4216adfc5217SJeff Kirsher u32 val; 4217adfc5217SJeff Kirsher 4218adfc5217SJeff Kirsher udelay(5); 4219adfc5217SJeff Kirsher 4220adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_COMMAND); 4221adfc5217SJeff Kirsher if (val & BNX2_NVM_COMMAND_DONE) { 4222adfc5217SJeff Kirsher __be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ)); 4223adfc5217SJeff Kirsher memcpy(ret_val, &v, 4); 4224adfc5217SJeff Kirsher break; 4225adfc5217SJeff Kirsher } 4226adfc5217SJeff Kirsher } 4227adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4228adfc5217SJeff Kirsher return -EBUSY; 4229adfc5217SJeff Kirsher 4230adfc5217SJeff Kirsher return 0; 4231adfc5217SJeff Kirsher } 4232adfc5217SJeff Kirsher 4233adfc5217SJeff Kirsher 4234adfc5217SJeff Kirsher static int 4235adfc5217SJeff Kirsher bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags) 4236adfc5217SJeff Kirsher { 4237adfc5217SJeff Kirsher u32 cmd; 4238adfc5217SJeff Kirsher __be32 val32; 4239adfc5217SJeff Kirsher int j; 4240adfc5217SJeff Kirsher 4241adfc5217SJeff Kirsher /* Build the command word. */ 4242adfc5217SJeff Kirsher cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags; 4243adfc5217SJeff Kirsher 4244adfc5217SJeff Kirsher /* Calculate an offset of a buffered flash, not needed for 5709. */ 4245adfc5217SJeff Kirsher if (bp->flash_info->flags & BNX2_NV_TRANSLATE) { 4246adfc5217SJeff Kirsher offset = ((offset / bp->flash_info->page_size) << 4247adfc5217SJeff Kirsher bp->flash_info->page_bits) + 4248adfc5217SJeff Kirsher (offset % bp->flash_info->page_size); 4249adfc5217SJeff Kirsher } 4250adfc5217SJeff Kirsher 4251adfc5217SJeff Kirsher /* Need to clear DONE bit separately. */ 4252adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); 4253adfc5217SJeff Kirsher 4254adfc5217SJeff Kirsher memcpy(&val32, val, 4); 4255adfc5217SJeff Kirsher 4256adfc5217SJeff Kirsher /* Write the data. */ 4257adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32)); 4258adfc5217SJeff Kirsher 4259adfc5217SJeff Kirsher /* Address of the NVRAM to write to. */ 4260adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); 4261adfc5217SJeff Kirsher 4262adfc5217SJeff Kirsher /* Issue the write command. */ 4263adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_COMMAND, cmd); 4264adfc5217SJeff Kirsher 4265adfc5217SJeff Kirsher /* Wait for completion. */ 4266adfc5217SJeff Kirsher for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { 4267adfc5217SJeff Kirsher udelay(5); 4268adfc5217SJeff Kirsher 4269adfc5217SJeff Kirsher if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE) 4270adfc5217SJeff Kirsher break; 4271adfc5217SJeff Kirsher } 4272adfc5217SJeff Kirsher if (j >= NVRAM_TIMEOUT_COUNT) 4273adfc5217SJeff Kirsher return -EBUSY; 4274adfc5217SJeff Kirsher 4275adfc5217SJeff Kirsher return 0; 4276adfc5217SJeff Kirsher } 4277adfc5217SJeff Kirsher 4278adfc5217SJeff Kirsher static int 4279adfc5217SJeff Kirsher bnx2_init_nvram(struct bnx2 *bp) 4280adfc5217SJeff Kirsher { 4281adfc5217SJeff Kirsher u32 val; 4282adfc5217SJeff Kirsher int j, entry_count, rc = 0; 4283adfc5217SJeff Kirsher const struct flash_spec *flash; 4284adfc5217SJeff Kirsher 4285adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 4286adfc5217SJeff Kirsher bp->flash_info = &flash_5709; 4287adfc5217SJeff Kirsher goto get_flash_size; 4288adfc5217SJeff Kirsher } 4289adfc5217SJeff Kirsher 4290adfc5217SJeff Kirsher /* Determine the selected interface. */ 4291adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_NVM_CFG1); 4292adfc5217SJeff Kirsher 4293adfc5217SJeff Kirsher entry_count = ARRAY_SIZE(flash_table); 4294adfc5217SJeff Kirsher 4295adfc5217SJeff Kirsher if (val & 0x40000000) { 4296adfc5217SJeff Kirsher 4297adfc5217SJeff Kirsher /* Flash interface has been reconfigured */ 4298adfc5217SJeff Kirsher for (j = 0, flash = &flash_table[0]; j < entry_count; 4299adfc5217SJeff Kirsher j++, flash++) { 4300adfc5217SJeff Kirsher if ((val & FLASH_BACKUP_STRAP_MASK) == 4301adfc5217SJeff Kirsher (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { 4302adfc5217SJeff Kirsher bp->flash_info = flash; 4303adfc5217SJeff Kirsher break; 4304adfc5217SJeff Kirsher } 4305adfc5217SJeff Kirsher } 4306adfc5217SJeff Kirsher } 4307adfc5217SJeff Kirsher else { 4308adfc5217SJeff Kirsher u32 mask; 4309adfc5217SJeff Kirsher /* Not yet been reconfigured */ 4310adfc5217SJeff Kirsher 4311adfc5217SJeff Kirsher if (val & (1 << 23)) 4312adfc5217SJeff Kirsher mask = FLASH_BACKUP_STRAP_MASK; 4313adfc5217SJeff Kirsher else 4314adfc5217SJeff Kirsher mask = FLASH_STRAP_MASK; 4315adfc5217SJeff Kirsher 4316adfc5217SJeff Kirsher for (j = 0, flash = &flash_table[0]; j < entry_count; 4317adfc5217SJeff Kirsher j++, flash++) { 4318adfc5217SJeff Kirsher 4319adfc5217SJeff Kirsher if ((val & mask) == (flash->strapping & mask)) { 4320adfc5217SJeff Kirsher bp->flash_info = flash; 4321adfc5217SJeff Kirsher 4322adfc5217SJeff Kirsher /* Request access to the flash interface. */ 4323adfc5217SJeff Kirsher if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) 4324adfc5217SJeff Kirsher return rc; 4325adfc5217SJeff Kirsher 4326adfc5217SJeff Kirsher /* Enable access to flash interface */ 4327adfc5217SJeff Kirsher bnx2_enable_nvram_access(bp); 4328adfc5217SJeff Kirsher 4329adfc5217SJeff Kirsher /* Reconfigure the flash interface */ 4330adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_CFG1, flash->config1); 4331adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_CFG2, flash->config2); 4332adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_CFG3, flash->config3); 4333adfc5217SJeff Kirsher REG_WR(bp, BNX2_NVM_WRITE1, flash->write1); 4334adfc5217SJeff Kirsher 4335adfc5217SJeff Kirsher /* Disable access to flash interface */ 4336adfc5217SJeff Kirsher bnx2_disable_nvram_access(bp); 4337adfc5217SJeff Kirsher bnx2_release_nvram_lock(bp); 4338adfc5217SJeff Kirsher 4339adfc5217SJeff Kirsher break; 4340adfc5217SJeff Kirsher } 4341adfc5217SJeff Kirsher } 4342adfc5217SJeff Kirsher } /* if (val & 0x40000000) */ 4343adfc5217SJeff Kirsher 4344adfc5217SJeff Kirsher if (j == entry_count) { 4345adfc5217SJeff Kirsher bp->flash_info = NULL; 4346adfc5217SJeff Kirsher pr_alert("Unknown flash/EEPROM type\n"); 4347adfc5217SJeff Kirsher return -ENODEV; 4348adfc5217SJeff Kirsher } 4349adfc5217SJeff Kirsher 4350adfc5217SJeff Kirsher get_flash_size: 4351adfc5217SJeff Kirsher val = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG2); 4352adfc5217SJeff Kirsher val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK; 4353adfc5217SJeff Kirsher if (val) 4354adfc5217SJeff Kirsher bp->flash_size = val; 4355adfc5217SJeff Kirsher else 4356adfc5217SJeff Kirsher bp->flash_size = bp->flash_info->total_size; 4357adfc5217SJeff Kirsher 4358adfc5217SJeff Kirsher return rc; 4359adfc5217SJeff Kirsher } 4360adfc5217SJeff Kirsher 4361adfc5217SJeff Kirsher static int 4362adfc5217SJeff Kirsher bnx2_nvram_read(struct bnx2 *bp, u32 offset, u8 *ret_buf, 4363adfc5217SJeff Kirsher int buf_size) 4364adfc5217SJeff Kirsher { 4365adfc5217SJeff Kirsher int rc = 0; 4366adfc5217SJeff Kirsher u32 cmd_flags, offset32, len32, extra; 4367adfc5217SJeff Kirsher 4368adfc5217SJeff Kirsher if (buf_size == 0) 4369adfc5217SJeff Kirsher return 0; 4370adfc5217SJeff Kirsher 4371adfc5217SJeff Kirsher /* Request access to the flash interface. */ 4372adfc5217SJeff Kirsher if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) 4373adfc5217SJeff Kirsher return rc; 4374adfc5217SJeff Kirsher 4375adfc5217SJeff Kirsher /* Enable access to flash interface */ 4376adfc5217SJeff Kirsher bnx2_enable_nvram_access(bp); 4377adfc5217SJeff Kirsher 4378adfc5217SJeff Kirsher len32 = buf_size; 4379adfc5217SJeff Kirsher offset32 = offset; 4380adfc5217SJeff Kirsher extra = 0; 4381adfc5217SJeff Kirsher 4382adfc5217SJeff Kirsher cmd_flags = 0; 4383adfc5217SJeff Kirsher 4384adfc5217SJeff Kirsher if (offset32 & 3) { 4385adfc5217SJeff Kirsher u8 buf[4]; 4386adfc5217SJeff Kirsher u32 pre_len; 4387adfc5217SJeff Kirsher 4388adfc5217SJeff Kirsher offset32 &= ~3; 4389adfc5217SJeff Kirsher pre_len = 4 - (offset & 3); 4390adfc5217SJeff Kirsher 4391adfc5217SJeff Kirsher if (pre_len >= len32) { 4392adfc5217SJeff Kirsher pre_len = len32; 4393adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_FIRST | 4394adfc5217SJeff Kirsher BNX2_NVM_COMMAND_LAST; 4395adfc5217SJeff Kirsher } 4396adfc5217SJeff Kirsher else { 4397adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_FIRST; 4398adfc5217SJeff Kirsher } 4399adfc5217SJeff Kirsher 4400adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); 4401adfc5217SJeff Kirsher 4402adfc5217SJeff Kirsher if (rc) 4403adfc5217SJeff Kirsher return rc; 4404adfc5217SJeff Kirsher 4405adfc5217SJeff Kirsher memcpy(ret_buf, buf + (offset & 3), pre_len); 4406adfc5217SJeff Kirsher 4407adfc5217SJeff Kirsher offset32 += 4; 4408adfc5217SJeff Kirsher ret_buf += pre_len; 4409adfc5217SJeff Kirsher len32 -= pre_len; 4410adfc5217SJeff Kirsher } 4411adfc5217SJeff Kirsher if (len32 & 3) { 4412adfc5217SJeff Kirsher extra = 4 - (len32 & 3); 4413adfc5217SJeff Kirsher len32 = (len32 + 4) & ~3; 4414adfc5217SJeff Kirsher } 4415adfc5217SJeff Kirsher 4416adfc5217SJeff Kirsher if (len32 == 4) { 4417adfc5217SJeff Kirsher u8 buf[4]; 4418adfc5217SJeff Kirsher 4419adfc5217SJeff Kirsher if (cmd_flags) 4420adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_LAST; 4421adfc5217SJeff Kirsher else 4422adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_FIRST | 4423adfc5217SJeff Kirsher BNX2_NVM_COMMAND_LAST; 4424adfc5217SJeff Kirsher 4425adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); 4426adfc5217SJeff Kirsher 4427adfc5217SJeff Kirsher memcpy(ret_buf, buf, 4 - extra); 4428adfc5217SJeff Kirsher } 4429adfc5217SJeff Kirsher else if (len32 > 0) { 4430adfc5217SJeff Kirsher u8 buf[4]; 4431adfc5217SJeff Kirsher 4432adfc5217SJeff Kirsher /* Read the first word. */ 4433adfc5217SJeff Kirsher if (cmd_flags) 4434adfc5217SJeff Kirsher cmd_flags = 0; 4435adfc5217SJeff Kirsher else 4436adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_FIRST; 4437adfc5217SJeff Kirsher 4438adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, cmd_flags); 4439adfc5217SJeff Kirsher 4440adfc5217SJeff Kirsher /* Advance to the next dword. */ 4441adfc5217SJeff Kirsher offset32 += 4; 4442adfc5217SJeff Kirsher ret_buf += 4; 4443adfc5217SJeff Kirsher len32 -= 4; 4444adfc5217SJeff Kirsher 4445adfc5217SJeff Kirsher while (len32 > 4 && rc == 0) { 4446adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, 0); 4447adfc5217SJeff Kirsher 4448adfc5217SJeff Kirsher /* Advance to the next dword. */ 4449adfc5217SJeff Kirsher offset32 += 4; 4450adfc5217SJeff Kirsher ret_buf += 4; 4451adfc5217SJeff Kirsher len32 -= 4; 4452adfc5217SJeff Kirsher } 4453adfc5217SJeff Kirsher 4454adfc5217SJeff Kirsher if (rc) 4455adfc5217SJeff Kirsher return rc; 4456adfc5217SJeff Kirsher 4457adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_LAST; 4458adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); 4459adfc5217SJeff Kirsher 4460adfc5217SJeff Kirsher memcpy(ret_buf, buf, 4 - extra); 4461adfc5217SJeff Kirsher } 4462adfc5217SJeff Kirsher 4463adfc5217SJeff Kirsher /* Disable access to flash interface */ 4464adfc5217SJeff Kirsher bnx2_disable_nvram_access(bp); 4465adfc5217SJeff Kirsher 4466adfc5217SJeff Kirsher bnx2_release_nvram_lock(bp); 4467adfc5217SJeff Kirsher 4468adfc5217SJeff Kirsher return rc; 4469adfc5217SJeff Kirsher } 4470adfc5217SJeff Kirsher 4471adfc5217SJeff Kirsher static int 4472adfc5217SJeff Kirsher bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, 4473adfc5217SJeff Kirsher int buf_size) 4474adfc5217SJeff Kirsher { 4475adfc5217SJeff Kirsher u32 written, offset32, len32; 4476adfc5217SJeff Kirsher u8 *buf, start[4], end[4], *align_buf = NULL, *flash_buffer = NULL; 4477adfc5217SJeff Kirsher int rc = 0; 4478adfc5217SJeff Kirsher int align_start, align_end; 4479adfc5217SJeff Kirsher 4480adfc5217SJeff Kirsher buf = data_buf; 4481adfc5217SJeff Kirsher offset32 = offset; 4482adfc5217SJeff Kirsher len32 = buf_size; 4483adfc5217SJeff Kirsher align_start = align_end = 0; 4484adfc5217SJeff Kirsher 4485adfc5217SJeff Kirsher if ((align_start = (offset32 & 3))) { 4486adfc5217SJeff Kirsher offset32 &= ~3; 4487adfc5217SJeff Kirsher len32 += align_start; 4488adfc5217SJeff Kirsher if (len32 < 4) 4489adfc5217SJeff Kirsher len32 = 4; 4490adfc5217SJeff Kirsher if ((rc = bnx2_nvram_read(bp, offset32, start, 4))) 4491adfc5217SJeff Kirsher return rc; 4492adfc5217SJeff Kirsher } 4493adfc5217SJeff Kirsher 4494adfc5217SJeff Kirsher if (len32 & 3) { 4495adfc5217SJeff Kirsher align_end = 4 - (len32 & 3); 4496adfc5217SJeff Kirsher len32 += align_end; 4497adfc5217SJeff Kirsher if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4))) 4498adfc5217SJeff Kirsher return rc; 4499adfc5217SJeff Kirsher } 4500adfc5217SJeff Kirsher 4501adfc5217SJeff Kirsher if (align_start || align_end) { 4502adfc5217SJeff Kirsher align_buf = kmalloc(len32, GFP_KERNEL); 4503adfc5217SJeff Kirsher if (align_buf == NULL) 4504adfc5217SJeff Kirsher return -ENOMEM; 4505adfc5217SJeff Kirsher if (align_start) { 4506adfc5217SJeff Kirsher memcpy(align_buf, start, 4); 4507adfc5217SJeff Kirsher } 4508adfc5217SJeff Kirsher if (align_end) { 4509adfc5217SJeff Kirsher memcpy(align_buf + len32 - 4, end, 4); 4510adfc5217SJeff Kirsher } 4511adfc5217SJeff Kirsher memcpy(align_buf + align_start, data_buf, buf_size); 4512adfc5217SJeff Kirsher buf = align_buf; 4513adfc5217SJeff Kirsher } 4514adfc5217SJeff Kirsher 4515adfc5217SJeff Kirsher if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { 4516adfc5217SJeff Kirsher flash_buffer = kmalloc(264, GFP_KERNEL); 4517adfc5217SJeff Kirsher if (flash_buffer == NULL) { 4518adfc5217SJeff Kirsher rc = -ENOMEM; 4519adfc5217SJeff Kirsher goto nvram_write_end; 4520adfc5217SJeff Kirsher } 4521adfc5217SJeff Kirsher } 4522adfc5217SJeff Kirsher 4523adfc5217SJeff Kirsher written = 0; 4524adfc5217SJeff Kirsher while ((written < len32) && (rc == 0)) { 4525adfc5217SJeff Kirsher u32 page_start, page_end, data_start, data_end; 4526adfc5217SJeff Kirsher u32 addr, cmd_flags; 4527adfc5217SJeff Kirsher int i; 4528adfc5217SJeff Kirsher 4529adfc5217SJeff Kirsher /* Find the page_start addr */ 4530adfc5217SJeff Kirsher page_start = offset32 + written; 4531adfc5217SJeff Kirsher page_start -= (page_start % bp->flash_info->page_size); 4532adfc5217SJeff Kirsher /* Find the page_end addr */ 4533adfc5217SJeff Kirsher page_end = page_start + bp->flash_info->page_size; 4534adfc5217SJeff Kirsher /* Find the data_start addr */ 4535adfc5217SJeff Kirsher data_start = (written == 0) ? offset32 : page_start; 4536adfc5217SJeff Kirsher /* Find the data_end addr */ 4537adfc5217SJeff Kirsher data_end = (page_end > offset32 + len32) ? 4538adfc5217SJeff Kirsher (offset32 + len32) : page_end; 4539adfc5217SJeff Kirsher 4540adfc5217SJeff Kirsher /* Request access to the flash interface. */ 4541adfc5217SJeff Kirsher if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) 4542adfc5217SJeff Kirsher goto nvram_write_end; 4543adfc5217SJeff Kirsher 4544adfc5217SJeff Kirsher /* Enable access to flash interface */ 4545adfc5217SJeff Kirsher bnx2_enable_nvram_access(bp); 4546adfc5217SJeff Kirsher 4547adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_FIRST; 4548adfc5217SJeff Kirsher if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { 4549adfc5217SJeff Kirsher int j; 4550adfc5217SJeff Kirsher 4551adfc5217SJeff Kirsher /* Read the whole page into the buffer 4552adfc5217SJeff Kirsher * (non-buffer flash only) */ 4553adfc5217SJeff Kirsher for (j = 0; j < bp->flash_info->page_size; j += 4) { 4554adfc5217SJeff Kirsher if (j == (bp->flash_info->page_size - 4)) { 4555adfc5217SJeff Kirsher cmd_flags |= BNX2_NVM_COMMAND_LAST; 4556adfc5217SJeff Kirsher } 4557adfc5217SJeff Kirsher rc = bnx2_nvram_read_dword(bp, 4558adfc5217SJeff Kirsher page_start + j, 4559adfc5217SJeff Kirsher &flash_buffer[j], 4560adfc5217SJeff Kirsher cmd_flags); 4561adfc5217SJeff Kirsher 4562adfc5217SJeff Kirsher if (rc) 4563adfc5217SJeff Kirsher goto nvram_write_end; 4564adfc5217SJeff Kirsher 4565adfc5217SJeff Kirsher cmd_flags = 0; 4566adfc5217SJeff Kirsher } 4567adfc5217SJeff Kirsher } 4568adfc5217SJeff Kirsher 4569adfc5217SJeff Kirsher /* Enable writes to flash interface (unlock write-protect) */ 4570adfc5217SJeff Kirsher if ((rc = bnx2_enable_nvram_write(bp)) != 0) 4571adfc5217SJeff Kirsher goto nvram_write_end; 4572adfc5217SJeff Kirsher 4573adfc5217SJeff Kirsher /* Loop to write back the buffer data from page_start to 4574adfc5217SJeff Kirsher * data_start */ 4575adfc5217SJeff Kirsher i = 0; 4576adfc5217SJeff Kirsher if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { 4577adfc5217SJeff Kirsher /* Erase the page */ 4578adfc5217SJeff Kirsher if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) 4579adfc5217SJeff Kirsher goto nvram_write_end; 4580adfc5217SJeff Kirsher 4581adfc5217SJeff Kirsher /* Re-enable the write again for the actual write */ 4582adfc5217SJeff Kirsher bnx2_enable_nvram_write(bp); 4583adfc5217SJeff Kirsher 4584adfc5217SJeff Kirsher for (addr = page_start; addr < data_start; 4585adfc5217SJeff Kirsher addr += 4, i += 4) { 4586adfc5217SJeff Kirsher 4587adfc5217SJeff Kirsher rc = bnx2_nvram_write_dword(bp, addr, 4588adfc5217SJeff Kirsher &flash_buffer[i], cmd_flags); 4589adfc5217SJeff Kirsher 4590adfc5217SJeff Kirsher if (rc != 0) 4591adfc5217SJeff Kirsher goto nvram_write_end; 4592adfc5217SJeff Kirsher 4593adfc5217SJeff Kirsher cmd_flags = 0; 4594adfc5217SJeff Kirsher } 4595adfc5217SJeff Kirsher } 4596adfc5217SJeff Kirsher 4597adfc5217SJeff Kirsher /* Loop to write the new data from data_start to data_end */ 4598adfc5217SJeff Kirsher for (addr = data_start; addr < data_end; addr += 4, i += 4) { 4599adfc5217SJeff Kirsher if ((addr == page_end - 4) || 4600adfc5217SJeff Kirsher ((bp->flash_info->flags & BNX2_NV_BUFFERED) && 4601adfc5217SJeff Kirsher (addr == data_end - 4))) { 4602adfc5217SJeff Kirsher 4603adfc5217SJeff Kirsher cmd_flags |= BNX2_NVM_COMMAND_LAST; 4604adfc5217SJeff Kirsher } 4605adfc5217SJeff Kirsher rc = bnx2_nvram_write_dword(bp, addr, buf, 4606adfc5217SJeff Kirsher cmd_flags); 4607adfc5217SJeff Kirsher 4608adfc5217SJeff Kirsher if (rc != 0) 4609adfc5217SJeff Kirsher goto nvram_write_end; 4610adfc5217SJeff Kirsher 4611adfc5217SJeff Kirsher cmd_flags = 0; 4612adfc5217SJeff Kirsher buf += 4; 4613adfc5217SJeff Kirsher } 4614adfc5217SJeff Kirsher 4615adfc5217SJeff Kirsher /* Loop to write back the buffer data from data_end 4616adfc5217SJeff Kirsher * to page_end */ 4617adfc5217SJeff Kirsher if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { 4618adfc5217SJeff Kirsher for (addr = data_end; addr < page_end; 4619adfc5217SJeff Kirsher addr += 4, i += 4) { 4620adfc5217SJeff Kirsher 4621adfc5217SJeff Kirsher if (addr == page_end-4) { 4622adfc5217SJeff Kirsher cmd_flags = BNX2_NVM_COMMAND_LAST; 4623adfc5217SJeff Kirsher } 4624adfc5217SJeff Kirsher rc = bnx2_nvram_write_dword(bp, addr, 4625adfc5217SJeff Kirsher &flash_buffer[i], cmd_flags); 4626adfc5217SJeff Kirsher 4627adfc5217SJeff Kirsher if (rc != 0) 4628adfc5217SJeff Kirsher goto nvram_write_end; 4629adfc5217SJeff Kirsher 4630adfc5217SJeff Kirsher cmd_flags = 0; 4631adfc5217SJeff Kirsher } 4632adfc5217SJeff Kirsher } 4633adfc5217SJeff Kirsher 4634adfc5217SJeff Kirsher /* Disable writes to flash interface (lock write-protect) */ 4635adfc5217SJeff Kirsher bnx2_disable_nvram_write(bp); 4636adfc5217SJeff Kirsher 4637adfc5217SJeff Kirsher /* Disable access to flash interface */ 4638adfc5217SJeff Kirsher bnx2_disable_nvram_access(bp); 4639adfc5217SJeff Kirsher bnx2_release_nvram_lock(bp); 4640adfc5217SJeff Kirsher 4641adfc5217SJeff Kirsher /* Increment written */ 4642adfc5217SJeff Kirsher written += data_end - data_start; 4643adfc5217SJeff Kirsher } 4644adfc5217SJeff Kirsher 4645adfc5217SJeff Kirsher nvram_write_end: 4646adfc5217SJeff Kirsher kfree(flash_buffer); 4647adfc5217SJeff Kirsher kfree(align_buf); 4648adfc5217SJeff Kirsher return rc; 4649adfc5217SJeff Kirsher } 4650adfc5217SJeff Kirsher 4651adfc5217SJeff Kirsher static void 4652adfc5217SJeff Kirsher bnx2_init_fw_cap(struct bnx2 *bp) 4653adfc5217SJeff Kirsher { 4654adfc5217SJeff Kirsher u32 val, sig = 0; 4655adfc5217SJeff Kirsher 4656adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_REMOTE_PHY_CAP; 4657adfc5217SJeff Kirsher bp->flags &= ~BNX2_FLAG_CAN_KEEP_VLAN; 4658adfc5217SJeff Kirsher 4659adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_ASF_ENABLE)) 4660adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN; 4661adfc5217SJeff Kirsher 4662adfc5217SJeff Kirsher val = bnx2_shmem_rd(bp, BNX2_FW_CAP_MB); 4663adfc5217SJeff Kirsher if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE) 4664adfc5217SJeff Kirsher return; 4665adfc5217SJeff Kirsher 4666adfc5217SJeff Kirsher if ((val & BNX2_FW_CAP_CAN_KEEP_VLAN) == BNX2_FW_CAP_CAN_KEEP_VLAN) { 4667adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN; 4668adfc5217SJeff Kirsher sig |= BNX2_DRV_ACK_CAP_SIGNATURE | BNX2_FW_CAP_CAN_KEEP_VLAN; 4669adfc5217SJeff Kirsher } 4670adfc5217SJeff Kirsher 4671adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && 4672adfc5217SJeff Kirsher (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE)) { 4673adfc5217SJeff Kirsher u32 link; 4674adfc5217SJeff Kirsher 4675adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_REMOTE_PHY_CAP; 4676adfc5217SJeff Kirsher 4677adfc5217SJeff Kirsher link = bnx2_shmem_rd(bp, BNX2_LINK_STATUS); 4678adfc5217SJeff Kirsher if (link & BNX2_LINK_STATUS_SERDES_LINK) 4679adfc5217SJeff Kirsher bp->phy_port = PORT_FIBRE; 4680adfc5217SJeff Kirsher else 4681adfc5217SJeff Kirsher bp->phy_port = PORT_TP; 4682adfc5217SJeff Kirsher 4683adfc5217SJeff Kirsher sig |= BNX2_DRV_ACK_CAP_SIGNATURE | 4684adfc5217SJeff Kirsher BNX2_FW_CAP_REMOTE_PHY_CAPABLE; 4685adfc5217SJeff Kirsher } 4686adfc5217SJeff Kirsher 4687adfc5217SJeff Kirsher if (netif_running(bp->dev) && sig) 4688adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_DRV_ACK_CAP_MB, sig); 4689adfc5217SJeff Kirsher } 4690adfc5217SJeff Kirsher 4691adfc5217SJeff Kirsher static void 4692adfc5217SJeff Kirsher bnx2_setup_msix_tbl(struct bnx2 *bp) 4693adfc5217SJeff Kirsher { 4694adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN); 4695adfc5217SJeff Kirsher 4696adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR); 4697adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR); 4698adfc5217SJeff Kirsher } 4699adfc5217SJeff Kirsher 4700adfc5217SJeff Kirsher static int 4701adfc5217SJeff Kirsher bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) 4702adfc5217SJeff Kirsher { 4703adfc5217SJeff Kirsher u32 val; 4704adfc5217SJeff Kirsher int i, rc = 0; 4705adfc5217SJeff Kirsher u8 old_port; 4706adfc5217SJeff Kirsher 4707adfc5217SJeff Kirsher /* Wait for the current PCI transaction to complete before 4708adfc5217SJeff Kirsher * issuing a reset. */ 4709adfc5217SJeff Kirsher if ((CHIP_NUM(bp) == CHIP_NUM_5706) || 4710adfc5217SJeff Kirsher (CHIP_NUM(bp) == CHIP_NUM_5708)) { 4711adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, 4712adfc5217SJeff Kirsher BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | 4713adfc5217SJeff Kirsher BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | 4714adfc5217SJeff Kirsher BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | 4715adfc5217SJeff Kirsher BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); 4716adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); 4717adfc5217SJeff Kirsher udelay(5); 4718adfc5217SJeff Kirsher } else { /* 5709 */ 4719adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); 4720adfc5217SJeff Kirsher val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; 4721adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); 4722adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); 4723adfc5217SJeff Kirsher 4724adfc5217SJeff Kirsher for (i = 0; i < 100; i++) { 4725adfc5217SJeff Kirsher msleep(1); 4726adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL); 4727adfc5217SJeff Kirsher if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND)) 4728adfc5217SJeff Kirsher break; 4729adfc5217SJeff Kirsher } 4730adfc5217SJeff Kirsher } 4731adfc5217SJeff Kirsher 4732adfc5217SJeff Kirsher /* Wait for the firmware to tell us it is ok to issue a reset. */ 4733adfc5217SJeff Kirsher bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1); 4734adfc5217SJeff Kirsher 4735adfc5217SJeff Kirsher /* Deposit a driver reset signature so the firmware knows that 4736adfc5217SJeff Kirsher * this is a soft reset. */ 4737adfc5217SJeff Kirsher bnx2_shmem_wr(bp, BNX2_DRV_RESET_SIGNATURE, 4738adfc5217SJeff Kirsher BNX2_DRV_RESET_SIGNATURE_MAGIC); 4739adfc5217SJeff Kirsher 4740adfc5217SJeff Kirsher /* Do a dummy read to force the chip to complete all current transaction 4741adfc5217SJeff Kirsher * before we issue a reset. */ 4742adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_ID); 4743adfc5217SJeff Kirsher 4744adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 4745adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET); 4746adfc5217SJeff Kirsher REG_RD(bp, BNX2_MISC_COMMAND); 4747adfc5217SJeff Kirsher udelay(5); 4748adfc5217SJeff Kirsher 4749adfc5217SJeff Kirsher val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 4750adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; 4751adfc5217SJeff Kirsher 4752adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); 4753adfc5217SJeff Kirsher 4754adfc5217SJeff Kirsher } else { 4755adfc5217SJeff Kirsher val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | 4756adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 4757adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; 4758adfc5217SJeff Kirsher 4759adfc5217SJeff Kirsher /* Chip reset. */ 4760adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); 4761adfc5217SJeff Kirsher 4762adfc5217SJeff Kirsher /* Reading back any register after chip reset will hang the 4763adfc5217SJeff Kirsher * bus on 5706 A0 and A1. The msleep below provides plenty 4764adfc5217SJeff Kirsher * of margin for write posting. 4765adfc5217SJeff Kirsher */ 4766adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || 4767adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5706_A1)) 4768adfc5217SJeff Kirsher msleep(20); 4769adfc5217SJeff Kirsher 4770adfc5217SJeff Kirsher /* Reset takes approximate 30 usec */ 4771adfc5217SJeff Kirsher for (i = 0; i < 10; i++) { 4772adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG); 4773adfc5217SJeff Kirsher if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | 4774adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) 4775adfc5217SJeff Kirsher break; 4776adfc5217SJeff Kirsher udelay(10); 4777adfc5217SJeff Kirsher } 4778adfc5217SJeff Kirsher 4779adfc5217SJeff Kirsher if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | 4780adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { 4781adfc5217SJeff Kirsher pr_err("Chip reset did not complete\n"); 4782adfc5217SJeff Kirsher return -EBUSY; 4783adfc5217SJeff Kirsher } 4784adfc5217SJeff Kirsher } 4785adfc5217SJeff Kirsher 4786adfc5217SJeff Kirsher /* Make sure byte swapping is properly configured. */ 4787adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0); 4788adfc5217SJeff Kirsher if (val != 0x01020304) { 4789adfc5217SJeff Kirsher pr_err("Chip not in correct endian mode\n"); 4790adfc5217SJeff Kirsher return -ENODEV; 4791adfc5217SJeff Kirsher } 4792adfc5217SJeff Kirsher 4793adfc5217SJeff Kirsher /* Wait for the firmware to finish its initialization. */ 4794adfc5217SJeff Kirsher rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 1, 0); 4795adfc5217SJeff Kirsher if (rc) 4796adfc5217SJeff Kirsher return rc; 4797adfc5217SJeff Kirsher 4798adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 4799adfc5217SJeff Kirsher old_port = bp->phy_port; 4800adfc5217SJeff Kirsher bnx2_init_fw_cap(bp); 4801adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) && 4802adfc5217SJeff Kirsher old_port != bp->phy_port) 4803adfc5217SJeff Kirsher bnx2_set_default_remote_link(bp); 4804adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 4805adfc5217SJeff Kirsher 4806adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A0) { 4807adfc5217SJeff Kirsher /* Adjust the voltage regular to two steps lower. The default 4808adfc5217SJeff Kirsher * of this register is 0x0000000e. */ 4809adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa); 4810adfc5217SJeff Kirsher 4811adfc5217SJeff Kirsher /* Remove bad rbuf memory from the free pool. */ 4812adfc5217SJeff Kirsher rc = bnx2_alloc_bad_rbuf(bp); 4813adfc5217SJeff Kirsher } 4814adfc5217SJeff Kirsher 4815adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSIX) { 4816adfc5217SJeff Kirsher bnx2_setup_msix_tbl(bp); 4817adfc5217SJeff Kirsher /* Prevent MSIX table reads and write from timing out */ 4818adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ECO_HW_CTL, 4819adfc5217SJeff Kirsher BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN); 4820adfc5217SJeff Kirsher } 4821adfc5217SJeff Kirsher 4822adfc5217SJeff Kirsher return rc; 4823adfc5217SJeff Kirsher } 4824adfc5217SJeff Kirsher 4825adfc5217SJeff Kirsher static int 4826adfc5217SJeff Kirsher bnx2_init_chip(struct bnx2 *bp) 4827adfc5217SJeff Kirsher { 4828adfc5217SJeff Kirsher u32 val, mtu; 4829adfc5217SJeff Kirsher int rc, i; 4830adfc5217SJeff Kirsher 4831adfc5217SJeff Kirsher /* Make sure the interrupt is not active. */ 4832adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); 4833adfc5217SJeff Kirsher 4834adfc5217SJeff Kirsher val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP | 4835adfc5217SJeff Kirsher BNX2_DMA_CONFIG_DATA_WORD_SWAP | 4836adfc5217SJeff Kirsher #ifdef __BIG_ENDIAN 4837adfc5217SJeff Kirsher BNX2_DMA_CONFIG_CNTL_BYTE_SWAP | 4838adfc5217SJeff Kirsher #endif 4839adfc5217SJeff Kirsher BNX2_DMA_CONFIG_CNTL_WORD_SWAP | 4840adfc5217SJeff Kirsher DMA_READ_CHANS << 12 | 4841adfc5217SJeff Kirsher DMA_WRITE_CHANS << 16; 4842adfc5217SJeff Kirsher 4843adfc5217SJeff Kirsher val |= (0x2 << 20) | (1 << 11); 4844adfc5217SJeff Kirsher 4845adfc5217SJeff Kirsher if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133)) 4846adfc5217SJeff Kirsher val |= (1 << 23); 4847adfc5217SJeff Kirsher 4848adfc5217SJeff Kirsher if ((CHIP_NUM(bp) == CHIP_NUM_5706) && 4849adfc5217SJeff Kirsher (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX)) 4850adfc5217SJeff Kirsher val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA; 4851adfc5217SJeff Kirsher 4852adfc5217SJeff Kirsher REG_WR(bp, BNX2_DMA_CONFIG, val); 4853adfc5217SJeff Kirsher 4854adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A0) { 4855adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_TDMA_CONFIG); 4856adfc5217SJeff Kirsher val |= BNX2_TDMA_CONFIG_ONE_DMA; 4857adfc5217SJeff Kirsher REG_WR(bp, BNX2_TDMA_CONFIG, val); 4858adfc5217SJeff Kirsher } 4859adfc5217SJeff Kirsher 4860adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_PCIX) { 4861adfc5217SJeff Kirsher u16 val16; 4862adfc5217SJeff Kirsher 4863adfc5217SJeff Kirsher pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD, 4864adfc5217SJeff Kirsher &val16); 4865adfc5217SJeff Kirsher pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD, 4866adfc5217SJeff Kirsher val16 & ~PCI_X_CMD_ERO); 4867adfc5217SJeff Kirsher } 4868adfc5217SJeff Kirsher 4869adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 4870adfc5217SJeff Kirsher BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | 4871adfc5217SJeff Kirsher BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | 4872adfc5217SJeff Kirsher BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); 4873adfc5217SJeff Kirsher 4874adfc5217SJeff Kirsher /* Initialize context mapping and zero out the quick contexts. The 4875adfc5217SJeff Kirsher * context block must have already been enabled. */ 4876adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 4877adfc5217SJeff Kirsher rc = bnx2_init_5709_context(bp); 4878adfc5217SJeff Kirsher if (rc) 4879adfc5217SJeff Kirsher return rc; 4880adfc5217SJeff Kirsher } else 4881adfc5217SJeff Kirsher bnx2_init_context(bp); 4882adfc5217SJeff Kirsher 4883adfc5217SJeff Kirsher if ((rc = bnx2_init_cpus(bp)) != 0) 4884adfc5217SJeff Kirsher return rc; 4885adfc5217SJeff Kirsher 4886adfc5217SJeff Kirsher bnx2_init_nvram(bp); 4887adfc5217SJeff Kirsher 4888adfc5217SJeff Kirsher bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0); 4889adfc5217SJeff Kirsher 4890adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MQ_CONFIG); 4891adfc5217SJeff Kirsher val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; 4892adfc5217SJeff Kirsher val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; 4893adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 4894adfc5217SJeff Kirsher val |= BNX2_MQ_CONFIG_BIN_MQ_MODE; 4895adfc5217SJeff Kirsher if (CHIP_REV(bp) == CHIP_REV_Ax) 4896adfc5217SJeff Kirsher val |= BNX2_MQ_CONFIG_HALT_DIS; 4897adfc5217SJeff Kirsher } 4898adfc5217SJeff Kirsher 4899adfc5217SJeff Kirsher REG_WR(bp, BNX2_MQ_CONFIG, val); 4900adfc5217SJeff Kirsher 4901adfc5217SJeff Kirsher val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); 4902adfc5217SJeff Kirsher REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val); 4903adfc5217SJeff Kirsher REG_WR(bp, BNX2_MQ_KNL_WIND_END, val); 4904adfc5217SJeff Kirsher 4905adfc5217SJeff Kirsher val = (BCM_PAGE_BITS - 8) << 24; 4906adfc5217SJeff Kirsher REG_WR(bp, BNX2_RV2P_CONFIG, val); 4907adfc5217SJeff Kirsher 4908adfc5217SJeff Kirsher /* Configure page size. */ 4909adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_TBDR_CONFIG); 4910adfc5217SJeff Kirsher val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE; 4911adfc5217SJeff Kirsher val |= (BCM_PAGE_BITS - 8) << 24 | 0x40; 4912adfc5217SJeff Kirsher REG_WR(bp, BNX2_TBDR_CONFIG, val); 4913adfc5217SJeff Kirsher 4914adfc5217SJeff Kirsher val = bp->mac_addr[0] + 4915adfc5217SJeff Kirsher (bp->mac_addr[1] << 8) + 4916adfc5217SJeff Kirsher (bp->mac_addr[2] << 16) + 4917adfc5217SJeff Kirsher bp->mac_addr[3] + 4918adfc5217SJeff Kirsher (bp->mac_addr[4] << 8) + 4919adfc5217SJeff Kirsher (bp->mac_addr[5] << 16); 4920adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val); 4921adfc5217SJeff Kirsher 4922adfc5217SJeff Kirsher /* Program the MTU. Also include 4 bytes for CRC32. */ 4923adfc5217SJeff Kirsher mtu = bp->dev->mtu; 4924adfc5217SJeff Kirsher val = mtu + ETH_HLEN + ETH_FCS_LEN; 4925adfc5217SJeff Kirsher if (val > (MAX_ETHERNET_PACKET_SIZE + 4)) 4926adfc5217SJeff Kirsher val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA; 4927adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val); 4928adfc5217SJeff Kirsher 4929adfc5217SJeff Kirsher if (mtu < 1500) 4930adfc5217SJeff Kirsher mtu = 1500; 4931adfc5217SJeff Kirsher 4932adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu)); 4933adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu)); 4934adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu)); 4935adfc5217SJeff Kirsher 4936adfc5217SJeff Kirsher memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size); 4937adfc5217SJeff Kirsher for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) 4938adfc5217SJeff Kirsher bp->bnx2_napi[i].last_status_idx = 0; 4939adfc5217SJeff Kirsher 4940adfc5217SJeff Kirsher bp->idle_chk_status_idx = 0xffff; 4941adfc5217SJeff Kirsher 4942adfc5217SJeff Kirsher bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; 4943adfc5217SJeff Kirsher 4944adfc5217SJeff Kirsher /* Set up how to generate a link change interrupt. */ 4945adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); 4946adfc5217SJeff Kirsher 4947adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATUS_ADDR_L, 4948adfc5217SJeff Kirsher (u64) bp->status_blk_mapping & 0xffffffff); 4949adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32); 4950adfc5217SJeff Kirsher 4951adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L, 4952adfc5217SJeff Kirsher (u64) bp->stats_blk_mapping & 0xffffffff); 4953adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H, 4954adfc5217SJeff Kirsher (u64) bp->stats_blk_mapping >> 32); 4955adfc5217SJeff Kirsher 4956adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, 4957adfc5217SJeff Kirsher (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); 4958adfc5217SJeff Kirsher 4959adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP, 4960adfc5217SJeff Kirsher (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip); 4961adfc5217SJeff Kirsher 4962adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMP_PROD_TRIP, 4963adfc5217SJeff Kirsher (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip); 4964adfc5217SJeff Kirsher 4965adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks); 4966adfc5217SJeff Kirsher 4967adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks); 4968adfc5217SJeff Kirsher 4969adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COM_TICKS, 4970adfc5217SJeff Kirsher (bp->com_ticks_int << 16) | bp->com_ticks); 4971adfc5217SJeff Kirsher 4972adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_CMD_TICKS, 4973adfc5217SJeff Kirsher (bp->cmd_ticks_int << 16) | bp->cmd_ticks); 4974adfc5217SJeff Kirsher 4975adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_BROKEN_STATS) 4976adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATS_TICKS, 0); 4977adfc5217SJeff Kirsher else 4978adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks); 4979adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ 4980adfc5217SJeff Kirsher 4981adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A1) 4982adfc5217SJeff Kirsher val = BNX2_HC_CONFIG_COLLECT_STATS; 4983adfc5217SJeff Kirsher else { 4984adfc5217SJeff Kirsher val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE | 4985adfc5217SJeff Kirsher BNX2_HC_CONFIG_COLLECT_STATS; 4986adfc5217SJeff Kirsher } 4987adfc5217SJeff Kirsher 4988adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSIX) { 4989adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR, 4990adfc5217SJeff Kirsher BNX2_HC_MSIX_BIT_VECTOR_VAL); 4991adfc5217SJeff Kirsher 4992adfc5217SJeff Kirsher val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B; 4993adfc5217SJeff Kirsher } 4994adfc5217SJeff Kirsher 4995adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI) 4996adfc5217SJeff Kirsher val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM; 4997adfc5217SJeff Kirsher 4998adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_CONFIG, val); 4999adfc5217SJeff Kirsher 5000adfc5217SJeff Kirsher if (bp->rx_ticks < 25) 5001adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1); 5002adfc5217SJeff Kirsher else 5003adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 0); 5004adfc5217SJeff Kirsher 5005adfc5217SJeff Kirsher for (i = 1; i < bp->irq_nvecs; i++) { 5006adfc5217SJeff Kirsher u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) + 5007adfc5217SJeff Kirsher BNX2_HC_SB_CONFIG_1; 5008adfc5217SJeff Kirsher 5009adfc5217SJeff Kirsher REG_WR(bp, base, 5010adfc5217SJeff Kirsher BNX2_HC_SB_CONFIG_1_TX_TMR_MODE | 5011adfc5217SJeff Kirsher BNX2_HC_SB_CONFIG_1_RX_TMR_MODE | 5012adfc5217SJeff Kirsher BNX2_HC_SB_CONFIG_1_ONE_SHOT); 5013adfc5217SJeff Kirsher 5014adfc5217SJeff Kirsher REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF, 5015adfc5217SJeff Kirsher (bp->tx_quick_cons_trip_int << 16) | 5016adfc5217SJeff Kirsher bp->tx_quick_cons_trip); 5017adfc5217SJeff Kirsher 5018adfc5217SJeff Kirsher REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF, 5019adfc5217SJeff Kirsher (bp->tx_ticks_int << 16) | bp->tx_ticks); 5020adfc5217SJeff Kirsher 5021adfc5217SJeff Kirsher REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF, 5022adfc5217SJeff Kirsher (bp->rx_quick_cons_trip_int << 16) | 5023adfc5217SJeff Kirsher bp->rx_quick_cons_trip); 5024adfc5217SJeff Kirsher 5025adfc5217SJeff Kirsher REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF, 5026adfc5217SJeff Kirsher (bp->rx_ticks_int << 16) | bp->rx_ticks); 5027adfc5217SJeff Kirsher } 5028adfc5217SJeff Kirsher 5029adfc5217SJeff Kirsher /* Clear internal stats counters. */ 5030adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); 5031adfc5217SJeff Kirsher 5032adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS); 5033adfc5217SJeff Kirsher 5034adfc5217SJeff Kirsher /* Initialize the receive filter. */ 5035adfc5217SJeff Kirsher bnx2_set_rx_mode(bp->dev); 5036adfc5217SJeff Kirsher 5037adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 5038adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); 5039adfc5217SJeff Kirsher val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; 5040adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); 5041adfc5217SJeff Kirsher } 5042adfc5217SJeff Kirsher rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, 5043adfc5217SJeff Kirsher 1, 0); 5044adfc5217SJeff Kirsher 5045adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); 5046adfc5217SJeff Kirsher REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); 5047adfc5217SJeff Kirsher 5048adfc5217SJeff Kirsher udelay(20); 5049adfc5217SJeff Kirsher 5050adfc5217SJeff Kirsher bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND); 5051adfc5217SJeff Kirsher 5052adfc5217SJeff Kirsher return rc; 5053adfc5217SJeff Kirsher } 5054adfc5217SJeff Kirsher 5055adfc5217SJeff Kirsher static void 5056adfc5217SJeff Kirsher bnx2_clear_ring_states(struct bnx2 *bp) 5057adfc5217SJeff Kirsher { 5058adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 5059adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr; 5060adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr; 5061adfc5217SJeff Kirsher int i; 5062adfc5217SJeff Kirsher 5063adfc5217SJeff Kirsher for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { 5064adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[i]; 5065adfc5217SJeff Kirsher txr = &bnapi->tx_ring; 5066adfc5217SJeff Kirsher rxr = &bnapi->rx_ring; 5067adfc5217SJeff Kirsher 5068adfc5217SJeff Kirsher txr->tx_cons = 0; 5069adfc5217SJeff Kirsher txr->hw_tx_cons = 0; 5070adfc5217SJeff Kirsher rxr->rx_prod_bseq = 0; 5071adfc5217SJeff Kirsher rxr->rx_prod = 0; 5072adfc5217SJeff Kirsher rxr->rx_cons = 0; 5073adfc5217SJeff Kirsher rxr->rx_pg_prod = 0; 5074adfc5217SJeff Kirsher rxr->rx_pg_cons = 0; 5075adfc5217SJeff Kirsher } 5076adfc5217SJeff Kirsher } 5077adfc5217SJeff Kirsher 5078adfc5217SJeff Kirsher static void 5079adfc5217SJeff Kirsher bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr) 5080adfc5217SJeff Kirsher { 5081adfc5217SJeff Kirsher u32 val, offset0, offset1, offset2, offset3; 5082adfc5217SJeff Kirsher u32 cid_addr = GET_CID_ADDR(cid); 5083adfc5217SJeff Kirsher 5084adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 5085adfc5217SJeff Kirsher offset0 = BNX2_L2CTX_TYPE_XI; 5086adfc5217SJeff Kirsher offset1 = BNX2_L2CTX_CMD_TYPE_XI; 5087adfc5217SJeff Kirsher offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; 5088adfc5217SJeff Kirsher offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI; 5089adfc5217SJeff Kirsher } else { 5090adfc5217SJeff Kirsher offset0 = BNX2_L2CTX_TYPE; 5091adfc5217SJeff Kirsher offset1 = BNX2_L2CTX_CMD_TYPE; 5092adfc5217SJeff Kirsher offset2 = BNX2_L2CTX_TBDR_BHADDR_HI; 5093adfc5217SJeff Kirsher offset3 = BNX2_L2CTX_TBDR_BHADDR_LO; 5094adfc5217SJeff Kirsher } 5095adfc5217SJeff Kirsher val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2; 5096adfc5217SJeff Kirsher bnx2_ctx_wr(bp, cid_addr, offset0, val); 5097adfc5217SJeff Kirsher 5098adfc5217SJeff Kirsher val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16); 5099adfc5217SJeff Kirsher bnx2_ctx_wr(bp, cid_addr, offset1, val); 5100adfc5217SJeff Kirsher 5101adfc5217SJeff Kirsher val = (u64) txr->tx_desc_mapping >> 32; 5102adfc5217SJeff Kirsher bnx2_ctx_wr(bp, cid_addr, offset2, val); 5103adfc5217SJeff Kirsher 5104adfc5217SJeff Kirsher val = (u64) txr->tx_desc_mapping & 0xffffffff; 5105adfc5217SJeff Kirsher bnx2_ctx_wr(bp, cid_addr, offset3, val); 5106adfc5217SJeff Kirsher } 5107adfc5217SJeff Kirsher 5108adfc5217SJeff Kirsher static void 5109adfc5217SJeff Kirsher bnx2_init_tx_ring(struct bnx2 *bp, int ring_num) 5110adfc5217SJeff Kirsher { 5111adfc5217SJeff Kirsher struct tx_bd *txbd; 5112adfc5217SJeff Kirsher u32 cid = TX_CID; 5113adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 5114adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr; 5115adfc5217SJeff Kirsher 5116adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[ring_num]; 5117adfc5217SJeff Kirsher txr = &bnapi->tx_ring; 5118adfc5217SJeff Kirsher 5119adfc5217SJeff Kirsher if (ring_num == 0) 5120adfc5217SJeff Kirsher cid = TX_CID; 5121adfc5217SJeff Kirsher else 5122adfc5217SJeff Kirsher cid = TX_TSS_CID + ring_num - 1; 5123adfc5217SJeff Kirsher 5124adfc5217SJeff Kirsher bp->tx_wake_thresh = bp->tx_ring_size / 2; 5125adfc5217SJeff Kirsher 5126adfc5217SJeff Kirsher txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT]; 5127adfc5217SJeff Kirsher 5128adfc5217SJeff Kirsher txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32; 5129adfc5217SJeff Kirsher txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff; 5130adfc5217SJeff Kirsher 5131adfc5217SJeff Kirsher txr->tx_prod = 0; 5132adfc5217SJeff Kirsher txr->tx_prod_bseq = 0; 5133adfc5217SJeff Kirsher 5134adfc5217SJeff Kirsher txr->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX; 5135adfc5217SJeff Kirsher txr->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ; 5136adfc5217SJeff Kirsher 5137adfc5217SJeff Kirsher bnx2_init_tx_context(bp, cid, txr); 5138adfc5217SJeff Kirsher } 5139adfc5217SJeff Kirsher 5140adfc5217SJeff Kirsher static void 5141adfc5217SJeff Kirsher bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size, 5142adfc5217SJeff Kirsher int num_rings) 5143adfc5217SJeff Kirsher { 5144adfc5217SJeff Kirsher int i; 5145adfc5217SJeff Kirsher struct rx_bd *rxbd; 5146adfc5217SJeff Kirsher 5147adfc5217SJeff Kirsher for (i = 0; i < num_rings; i++) { 5148adfc5217SJeff Kirsher int j; 5149adfc5217SJeff Kirsher 5150adfc5217SJeff Kirsher rxbd = &rx_ring[i][0]; 5151adfc5217SJeff Kirsher for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) { 5152adfc5217SJeff Kirsher rxbd->rx_bd_len = buf_size; 5153adfc5217SJeff Kirsher rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; 5154adfc5217SJeff Kirsher } 5155adfc5217SJeff Kirsher if (i == (num_rings - 1)) 5156adfc5217SJeff Kirsher j = 0; 5157adfc5217SJeff Kirsher else 5158adfc5217SJeff Kirsher j = i + 1; 5159adfc5217SJeff Kirsher rxbd->rx_bd_haddr_hi = (u64) dma[j] >> 32; 5160adfc5217SJeff Kirsher rxbd->rx_bd_haddr_lo = (u64) dma[j] & 0xffffffff; 5161adfc5217SJeff Kirsher } 5162adfc5217SJeff Kirsher } 5163adfc5217SJeff Kirsher 5164adfc5217SJeff Kirsher static void 5165adfc5217SJeff Kirsher bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) 5166adfc5217SJeff Kirsher { 5167adfc5217SJeff Kirsher int i; 5168adfc5217SJeff Kirsher u16 prod, ring_prod; 5169adfc5217SJeff Kirsher u32 cid, rx_cid_addr, val; 5170adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[ring_num]; 5171adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 5172adfc5217SJeff Kirsher 5173adfc5217SJeff Kirsher if (ring_num == 0) 5174adfc5217SJeff Kirsher cid = RX_CID; 5175adfc5217SJeff Kirsher else 5176adfc5217SJeff Kirsher cid = RX_RSS_CID + ring_num - 1; 5177adfc5217SJeff Kirsher 5178adfc5217SJeff Kirsher rx_cid_addr = GET_CID_ADDR(cid); 5179adfc5217SJeff Kirsher 5180adfc5217SJeff Kirsher bnx2_init_rxbd_rings(rxr->rx_desc_ring, rxr->rx_desc_mapping, 5181adfc5217SJeff Kirsher bp->rx_buf_use_size, bp->rx_max_ring); 5182adfc5217SJeff Kirsher 5183adfc5217SJeff Kirsher bnx2_init_rx_context(bp, cid); 5184adfc5217SJeff Kirsher 5185adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 5186adfc5217SJeff Kirsher val = REG_RD(bp, BNX2_MQ_MAP_L2_5); 5187adfc5217SJeff Kirsher REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM); 5188adfc5217SJeff Kirsher } 5189adfc5217SJeff Kirsher 5190adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0); 5191adfc5217SJeff Kirsher if (bp->rx_pg_ring_size) { 5192adfc5217SJeff Kirsher bnx2_init_rxbd_rings(rxr->rx_pg_desc_ring, 5193adfc5217SJeff Kirsher rxr->rx_pg_desc_mapping, 5194adfc5217SJeff Kirsher PAGE_SIZE, bp->rx_max_pg_ring); 5195adfc5217SJeff Kirsher val = (bp->rx_buf_use_size << 16) | PAGE_SIZE; 5196adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val); 5197adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY, 5198adfc5217SJeff Kirsher BNX2_L2CTX_RBDC_JUMBO_KEY - ring_num); 5199adfc5217SJeff Kirsher 5200adfc5217SJeff Kirsher val = (u64) rxr->rx_pg_desc_mapping[0] >> 32; 5201adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val); 5202adfc5217SJeff Kirsher 5203adfc5217SJeff Kirsher val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff; 5204adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val); 5205adfc5217SJeff Kirsher 5206adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 5207adfc5217SJeff Kirsher REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT); 5208adfc5217SJeff Kirsher } 5209adfc5217SJeff Kirsher 5210adfc5217SJeff Kirsher val = (u64) rxr->rx_desc_mapping[0] >> 32; 5211adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); 5212adfc5217SJeff Kirsher 5213adfc5217SJeff Kirsher val = (u64) rxr->rx_desc_mapping[0] & 0xffffffff; 5214adfc5217SJeff Kirsher bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); 5215adfc5217SJeff Kirsher 5216adfc5217SJeff Kirsher ring_prod = prod = rxr->rx_pg_prod; 5217adfc5217SJeff Kirsher for (i = 0; i < bp->rx_pg_ring_size; i++) { 5218adfc5217SJeff Kirsher if (bnx2_alloc_rx_page(bp, rxr, ring_prod, GFP_KERNEL) < 0) { 5219adfc5217SJeff Kirsher netdev_warn(bp->dev, "init'ed rx page ring %d with %d/%d pages only\n", 5220adfc5217SJeff Kirsher ring_num, i, bp->rx_pg_ring_size); 5221adfc5217SJeff Kirsher break; 5222adfc5217SJeff Kirsher } 5223adfc5217SJeff Kirsher prod = NEXT_RX_BD(prod); 5224adfc5217SJeff Kirsher ring_prod = RX_PG_RING_IDX(prod); 5225adfc5217SJeff Kirsher } 5226adfc5217SJeff Kirsher rxr->rx_pg_prod = prod; 5227adfc5217SJeff Kirsher 5228adfc5217SJeff Kirsher ring_prod = prod = rxr->rx_prod; 5229adfc5217SJeff Kirsher for (i = 0; i < bp->rx_ring_size; i++) { 5230dd2bc8e9SEric Dumazet if (bnx2_alloc_rx_data(bp, rxr, ring_prod, GFP_KERNEL) < 0) { 5231adfc5217SJeff Kirsher netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d skbs only\n", 5232adfc5217SJeff Kirsher ring_num, i, bp->rx_ring_size); 5233adfc5217SJeff Kirsher break; 5234adfc5217SJeff Kirsher } 5235adfc5217SJeff Kirsher prod = NEXT_RX_BD(prod); 5236adfc5217SJeff Kirsher ring_prod = RX_RING_IDX(prod); 5237adfc5217SJeff Kirsher } 5238adfc5217SJeff Kirsher rxr->rx_prod = prod; 5239adfc5217SJeff Kirsher 5240adfc5217SJeff Kirsher rxr->rx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BDIDX; 5241adfc5217SJeff Kirsher rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ; 5242adfc5217SJeff Kirsher rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX; 5243adfc5217SJeff Kirsher 5244adfc5217SJeff Kirsher REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); 5245adfc5217SJeff Kirsher REG_WR16(bp, rxr->rx_bidx_addr, prod); 5246adfc5217SJeff Kirsher 5247adfc5217SJeff Kirsher REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); 5248adfc5217SJeff Kirsher } 5249adfc5217SJeff Kirsher 5250adfc5217SJeff Kirsher static void 5251adfc5217SJeff Kirsher bnx2_init_all_rings(struct bnx2 *bp) 5252adfc5217SJeff Kirsher { 5253adfc5217SJeff Kirsher int i; 5254adfc5217SJeff Kirsher u32 val; 5255adfc5217SJeff Kirsher 5256adfc5217SJeff Kirsher bnx2_clear_ring_states(bp); 5257adfc5217SJeff Kirsher 5258adfc5217SJeff Kirsher REG_WR(bp, BNX2_TSCH_TSS_CFG, 0); 5259adfc5217SJeff Kirsher for (i = 0; i < bp->num_tx_rings; i++) 5260adfc5217SJeff Kirsher bnx2_init_tx_ring(bp, i); 5261adfc5217SJeff Kirsher 5262adfc5217SJeff Kirsher if (bp->num_tx_rings > 1) 5263adfc5217SJeff Kirsher REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) | 5264adfc5217SJeff Kirsher (TX_TSS_CID << 7)); 5265adfc5217SJeff Kirsher 5266adfc5217SJeff Kirsher REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0); 5267adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0); 5268adfc5217SJeff Kirsher 5269adfc5217SJeff Kirsher for (i = 0; i < bp->num_rx_rings; i++) 5270adfc5217SJeff Kirsher bnx2_init_rx_ring(bp, i); 5271adfc5217SJeff Kirsher 5272adfc5217SJeff Kirsher if (bp->num_rx_rings > 1) { 5273adfc5217SJeff Kirsher u32 tbl_32 = 0; 5274adfc5217SJeff Kirsher 5275adfc5217SJeff Kirsher for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) { 5276adfc5217SJeff Kirsher int shift = (i % 8) << 2; 5277adfc5217SJeff Kirsher 5278adfc5217SJeff Kirsher tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift; 5279adfc5217SJeff Kirsher if ((i % 8) == 7) { 5280adfc5217SJeff Kirsher REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32); 5281adfc5217SJeff Kirsher REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) | 5282adfc5217SJeff Kirsher BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK | 5283adfc5217SJeff Kirsher BNX2_RLUP_RSS_COMMAND_WRITE | 5284adfc5217SJeff Kirsher BNX2_RLUP_RSS_COMMAND_HASH_MASK); 5285adfc5217SJeff Kirsher tbl_32 = 0; 5286adfc5217SJeff Kirsher } 5287adfc5217SJeff Kirsher } 5288adfc5217SJeff Kirsher 5289adfc5217SJeff Kirsher val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI | 5290adfc5217SJeff Kirsher BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI; 5291adfc5217SJeff Kirsher 5292adfc5217SJeff Kirsher REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val); 5293adfc5217SJeff Kirsher 5294adfc5217SJeff Kirsher } 5295adfc5217SJeff Kirsher } 5296adfc5217SJeff Kirsher 5297adfc5217SJeff Kirsher static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size) 5298adfc5217SJeff Kirsher { 5299adfc5217SJeff Kirsher u32 max, num_rings = 1; 5300adfc5217SJeff Kirsher 5301adfc5217SJeff Kirsher while (ring_size > MAX_RX_DESC_CNT) { 5302adfc5217SJeff Kirsher ring_size -= MAX_RX_DESC_CNT; 5303adfc5217SJeff Kirsher num_rings++; 5304adfc5217SJeff Kirsher } 5305adfc5217SJeff Kirsher /* round to next power of 2 */ 5306adfc5217SJeff Kirsher max = max_size; 5307adfc5217SJeff Kirsher while ((max & num_rings) == 0) 5308adfc5217SJeff Kirsher max >>= 1; 5309adfc5217SJeff Kirsher 5310adfc5217SJeff Kirsher if (num_rings != max) 5311adfc5217SJeff Kirsher max <<= 1; 5312adfc5217SJeff Kirsher 5313adfc5217SJeff Kirsher return max; 5314adfc5217SJeff Kirsher } 5315adfc5217SJeff Kirsher 5316adfc5217SJeff Kirsher static void 5317adfc5217SJeff Kirsher bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) 5318adfc5217SJeff Kirsher { 5319adfc5217SJeff Kirsher u32 rx_size, rx_space, jumbo_size; 5320adfc5217SJeff Kirsher 5321adfc5217SJeff Kirsher /* 8 for CRC and VLAN */ 5322adfc5217SJeff Kirsher rx_size = bp->dev->mtu + ETH_HLEN + BNX2_RX_OFFSET + 8; 5323adfc5217SJeff Kirsher 5324adfc5217SJeff Kirsher rx_space = SKB_DATA_ALIGN(rx_size + BNX2_RX_ALIGN) + NET_SKB_PAD + 5325dd2bc8e9SEric Dumazet SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 5326adfc5217SJeff Kirsher 5327adfc5217SJeff Kirsher bp->rx_copy_thresh = BNX2_RX_COPY_THRESH; 5328adfc5217SJeff Kirsher bp->rx_pg_ring_size = 0; 5329adfc5217SJeff Kirsher bp->rx_max_pg_ring = 0; 5330adfc5217SJeff Kirsher bp->rx_max_pg_ring_idx = 0; 5331adfc5217SJeff Kirsher if ((rx_space > PAGE_SIZE) && !(bp->flags & BNX2_FLAG_JUMBO_BROKEN)) { 5332adfc5217SJeff Kirsher int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT; 5333adfc5217SJeff Kirsher 5334adfc5217SJeff Kirsher jumbo_size = size * pages; 5335adfc5217SJeff Kirsher if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT) 5336adfc5217SJeff Kirsher jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT; 5337adfc5217SJeff Kirsher 5338adfc5217SJeff Kirsher bp->rx_pg_ring_size = jumbo_size; 5339adfc5217SJeff Kirsher bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size, 5340adfc5217SJeff Kirsher MAX_RX_PG_RINGS); 5341adfc5217SJeff Kirsher bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1; 5342adfc5217SJeff Kirsher rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET; 5343adfc5217SJeff Kirsher bp->rx_copy_thresh = 0; 5344adfc5217SJeff Kirsher } 5345adfc5217SJeff Kirsher 5346adfc5217SJeff Kirsher bp->rx_buf_use_size = rx_size; 5347dd2bc8e9SEric Dumazet /* hw alignment + build_skb() overhead*/ 5348dd2bc8e9SEric Dumazet bp->rx_buf_size = SKB_DATA_ALIGN(bp->rx_buf_use_size + BNX2_RX_ALIGN) + 5349dd2bc8e9SEric Dumazet NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 5350adfc5217SJeff Kirsher bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET; 5351adfc5217SJeff Kirsher bp->rx_ring_size = size; 5352adfc5217SJeff Kirsher bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS); 5353adfc5217SJeff Kirsher bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1; 5354adfc5217SJeff Kirsher } 5355adfc5217SJeff Kirsher 5356adfc5217SJeff Kirsher static void 5357adfc5217SJeff Kirsher bnx2_free_tx_skbs(struct bnx2 *bp) 5358adfc5217SJeff Kirsher { 5359adfc5217SJeff Kirsher int i; 5360adfc5217SJeff Kirsher 5361adfc5217SJeff Kirsher for (i = 0; i < bp->num_tx_rings; i++) { 5362adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 5363adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 5364adfc5217SJeff Kirsher int j; 5365adfc5217SJeff Kirsher 5366adfc5217SJeff Kirsher if (txr->tx_buf_ring == NULL) 5367adfc5217SJeff Kirsher continue; 5368adfc5217SJeff Kirsher 5369adfc5217SJeff Kirsher for (j = 0; j < TX_DESC_CNT; ) { 5370adfc5217SJeff Kirsher struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; 5371adfc5217SJeff Kirsher struct sk_buff *skb = tx_buf->skb; 5372adfc5217SJeff Kirsher int k, last; 5373adfc5217SJeff Kirsher 5374adfc5217SJeff Kirsher if (skb == NULL) { 5375adfc5217SJeff Kirsher j++; 5376adfc5217SJeff Kirsher continue; 5377adfc5217SJeff Kirsher } 5378adfc5217SJeff Kirsher 5379adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, 5380adfc5217SJeff Kirsher dma_unmap_addr(tx_buf, mapping), 5381adfc5217SJeff Kirsher skb_headlen(skb), 5382adfc5217SJeff Kirsher PCI_DMA_TODEVICE); 5383adfc5217SJeff Kirsher 5384adfc5217SJeff Kirsher tx_buf->skb = NULL; 5385adfc5217SJeff Kirsher 5386adfc5217SJeff Kirsher last = tx_buf->nr_frags; 5387adfc5217SJeff Kirsher j++; 5388adfc5217SJeff Kirsher for (k = 0; k < last; k++, j++) { 5389adfc5217SJeff Kirsher tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; 5390adfc5217SJeff Kirsher dma_unmap_page(&bp->pdev->dev, 5391adfc5217SJeff Kirsher dma_unmap_addr(tx_buf, mapping), 53929e903e08SEric Dumazet skb_frag_size(&skb_shinfo(skb)->frags[k]), 5393adfc5217SJeff Kirsher PCI_DMA_TODEVICE); 5394adfc5217SJeff Kirsher } 5395adfc5217SJeff Kirsher dev_kfree_skb(skb); 5396adfc5217SJeff Kirsher } 5397e9831909SEric Dumazet netdev_tx_reset_queue(netdev_get_tx_queue(bp->dev, i)); 5398adfc5217SJeff Kirsher } 5399adfc5217SJeff Kirsher } 5400adfc5217SJeff Kirsher 5401adfc5217SJeff Kirsher static void 5402adfc5217SJeff Kirsher bnx2_free_rx_skbs(struct bnx2 *bp) 5403adfc5217SJeff Kirsher { 5404adfc5217SJeff Kirsher int i; 5405adfc5217SJeff Kirsher 5406adfc5217SJeff Kirsher for (i = 0; i < bp->num_rx_rings; i++) { 5407adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 5408adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 5409adfc5217SJeff Kirsher int j; 5410adfc5217SJeff Kirsher 5411adfc5217SJeff Kirsher if (rxr->rx_buf_ring == NULL) 5412adfc5217SJeff Kirsher return; 5413adfc5217SJeff Kirsher 5414adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_ring_idx; j++) { 5415adfc5217SJeff Kirsher struct sw_bd *rx_buf = &rxr->rx_buf_ring[j]; 5416dd2bc8e9SEric Dumazet u8 *data = rx_buf->data; 5417adfc5217SJeff Kirsher 5418dd2bc8e9SEric Dumazet if (data == NULL) 5419adfc5217SJeff Kirsher continue; 5420adfc5217SJeff Kirsher 5421adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, 5422adfc5217SJeff Kirsher dma_unmap_addr(rx_buf, mapping), 5423adfc5217SJeff Kirsher bp->rx_buf_use_size, 5424adfc5217SJeff Kirsher PCI_DMA_FROMDEVICE); 5425adfc5217SJeff Kirsher 5426dd2bc8e9SEric Dumazet rx_buf->data = NULL; 5427adfc5217SJeff Kirsher 5428dd2bc8e9SEric Dumazet kfree(data); 5429adfc5217SJeff Kirsher } 5430adfc5217SJeff Kirsher for (j = 0; j < bp->rx_max_pg_ring_idx; j++) 5431adfc5217SJeff Kirsher bnx2_free_rx_page(bp, rxr, j); 5432adfc5217SJeff Kirsher } 5433adfc5217SJeff Kirsher } 5434adfc5217SJeff Kirsher 5435adfc5217SJeff Kirsher static void 5436adfc5217SJeff Kirsher bnx2_free_skbs(struct bnx2 *bp) 5437adfc5217SJeff Kirsher { 5438adfc5217SJeff Kirsher bnx2_free_tx_skbs(bp); 5439adfc5217SJeff Kirsher bnx2_free_rx_skbs(bp); 5440adfc5217SJeff Kirsher } 5441adfc5217SJeff Kirsher 5442adfc5217SJeff Kirsher static int 5443adfc5217SJeff Kirsher bnx2_reset_nic(struct bnx2 *bp, u32 reset_code) 5444adfc5217SJeff Kirsher { 5445adfc5217SJeff Kirsher int rc; 5446adfc5217SJeff Kirsher 5447adfc5217SJeff Kirsher rc = bnx2_reset_chip(bp, reset_code); 5448adfc5217SJeff Kirsher bnx2_free_skbs(bp); 5449adfc5217SJeff Kirsher if (rc) 5450adfc5217SJeff Kirsher return rc; 5451adfc5217SJeff Kirsher 5452adfc5217SJeff Kirsher if ((rc = bnx2_init_chip(bp)) != 0) 5453adfc5217SJeff Kirsher return rc; 5454adfc5217SJeff Kirsher 5455adfc5217SJeff Kirsher bnx2_init_all_rings(bp); 5456adfc5217SJeff Kirsher return 0; 5457adfc5217SJeff Kirsher } 5458adfc5217SJeff Kirsher 5459adfc5217SJeff Kirsher static int 5460adfc5217SJeff Kirsher bnx2_init_nic(struct bnx2 *bp, int reset_phy) 5461adfc5217SJeff Kirsher { 5462adfc5217SJeff Kirsher int rc; 5463adfc5217SJeff Kirsher 5464adfc5217SJeff Kirsher if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0) 5465adfc5217SJeff Kirsher return rc; 5466adfc5217SJeff Kirsher 5467adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 5468adfc5217SJeff Kirsher bnx2_init_phy(bp, reset_phy); 5469adfc5217SJeff Kirsher bnx2_set_link(bp); 5470adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 5471adfc5217SJeff Kirsher bnx2_remote_phy_event(bp); 5472adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 5473adfc5217SJeff Kirsher return 0; 5474adfc5217SJeff Kirsher } 5475adfc5217SJeff Kirsher 5476adfc5217SJeff Kirsher static int 5477adfc5217SJeff Kirsher bnx2_shutdown_chip(struct bnx2 *bp) 5478adfc5217SJeff Kirsher { 5479adfc5217SJeff Kirsher u32 reset_code; 5480adfc5217SJeff Kirsher 5481adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_NO_WOL) 5482adfc5217SJeff Kirsher reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; 5483adfc5217SJeff Kirsher else if (bp->wol) 5484adfc5217SJeff Kirsher reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; 5485adfc5217SJeff Kirsher else 5486adfc5217SJeff Kirsher reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; 5487adfc5217SJeff Kirsher 5488adfc5217SJeff Kirsher return bnx2_reset_chip(bp, reset_code); 5489adfc5217SJeff Kirsher } 5490adfc5217SJeff Kirsher 5491adfc5217SJeff Kirsher static int 5492adfc5217SJeff Kirsher bnx2_test_registers(struct bnx2 *bp) 5493adfc5217SJeff Kirsher { 5494adfc5217SJeff Kirsher int ret; 5495adfc5217SJeff Kirsher int i, is_5709; 5496adfc5217SJeff Kirsher static const struct { 5497adfc5217SJeff Kirsher u16 offset; 5498adfc5217SJeff Kirsher u16 flags; 5499adfc5217SJeff Kirsher #define BNX2_FL_NOT_5709 1 5500adfc5217SJeff Kirsher u32 rw_mask; 5501adfc5217SJeff Kirsher u32 ro_mask; 5502adfc5217SJeff Kirsher } reg_tbl[] = { 5503adfc5217SJeff Kirsher { 0x006c, 0, 0x00000000, 0x0000003f }, 5504adfc5217SJeff Kirsher { 0x0090, 0, 0xffffffff, 0x00000000 }, 5505adfc5217SJeff Kirsher { 0x0094, 0, 0x00000000, 0x00000000 }, 5506adfc5217SJeff Kirsher 5507adfc5217SJeff Kirsher { 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 }, 5508adfc5217SJeff Kirsher { 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5509adfc5217SJeff Kirsher { 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5510adfc5217SJeff Kirsher { 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff }, 5511adfc5217SJeff Kirsher { 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 }, 5512adfc5217SJeff Kirsher { 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 }, 5513adfc5217SJeff Kirsher { 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff }, 5514adfc5217SJeff Kirsher { 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5515adfc5217SJeff Kirsher { 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5516adfc5217SJeff Kirsher 5517adfc5217SJeff Kirsher { 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5518adfc5217SJeff Kirsher { 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff }, 5519adfc5217SJeff Kirsher { 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, 5520adfc5217SJeff Kirsher { 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, 5521adfc5217SJeff Kirsher { 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, 5522adfc5217SJeff Kirsher { 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 }, 5523adfc5217SJeff Kirsher 5524adfc5217SJeff Kirsher { 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 }, 5525adfc5217SJeff Kirsher { 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 }, 5526adfc5217SJeff Kirsher { 0x0c08, BNX2_FL_NOT_5709, 0x0f0ff073, 0x00000000 }, 5527adfc5217SJeff Kirsher 5528adfc5217SJeff Kirsher { 0x1000, 0, 0x00000000, 0x00000001 }, 5529adfc5217SJeff Kirsher { 0x1004, BNX2_FL_NOT_5709, 0x00000000, 0x000f0001 }, 5530adfc5217SJeff Kirsher 5531adfc5217SJeff Kirsher { 0x1408, 0, 0x01c00800, 0x00000000 }, 5532adfc5217SJeff Kirsher { 0x149c, 0, 0x8000ffff, 0x00000000 }, 5533adfc5217SJeff Kirsher { 0x14a8, 0, 0x00000000, 0x000001ff }, 5534adfc5217SJeff Kirsher { 0x14ac, 0, 0x0fffffff, 0x10000000 }, 5535adfc5217SJeff Kirsher { 0x14b0, 0, 0x00000002, 0x00000001 }, 5536adfc5217SJeff Kirsher { 0x14b8, 0, 0x00000000, 0x00000000 }, 5537adfc5217SJeff Kirsher { 0x14c0, 0, 0x00000000, 0x00000009 }, 5538adfc5217SJeff Kirsher { 0x14c4, 0, 0x00003fff, 0x00000000 }, 5539adfc5217SJeff Kirsher { 0x14cc, 0, 0x00000000, 0x00000001 }, 5540adfc5217SJeff Kirsher { 0x14d0, 0, 0xffffffff, 0x00000000 }, 5541adfc5217SJeff Kirsher 5542adfc5217SJeff Kirsher { 0x1800, 0, 0x00000000, 0x00000001 }, 5543adfc5217SJeff Kirsher { 0x1804, 0, 0x00000000, 0x00000003 }, 5544adfc5217SJeff Kirsher 5545adfc5217SJeff Kirsher { 0x2800, 0, 0x00000000, 0x00000001 }, 5546adfc5217SJeff Kirsher { 0x2804, 0, 0x00000000, 0x00003f01 }, 5547adfc5217SJeff Kirsher { 0x2808, 0, 0x0f3f3f03, 0x00000000 }, 5548adfc5217SJeff Kirsher { 0x2810, 0, 0xffff0000, 0x00000000 }, 5549adfc5217SJeff Kirsher { 0x2814, 0, 0xffff0000, 0x00000000 }, 5550adfc5217SJeff Kirsher { 0x2818, 0, 0xffff0000, 0x00000000 }, 5551adfc5217SJeff Kirsher { 0x281c, 0, 0xffff0000, 0x00000000 }, 5552adfc5217SJeff Kirsher { 0x2834, 0, 0xffffffff, 0x00000000 }, 5553adfc5217SJeff Kirsher { 0x2840, 0, 0x00000000, 0xffffffff }, 5554adfc5217SJeff Kirsher { 0x2844, 0, 0x00000000, 0xffffffff }, 5555adfc5217SJeff Kirsher { 0x2848, 0, 0xffffffff, 0x00000000 }, 5556adfc5217SJeff Kirsher { 0x284c, 0, 0xf800f800, 0x07ff07ff }, 5557adfc5217SJeff Kirsher 5558adfc5217SJeff Kirsher { 0x2c00, 0, 0x00000000, 0x00000011 }, 5559adfc5217SJeff Kirsher { 0x2c04, 0, 0x00000000, 0x00030007 }, 5560adfc5217SJeff Kirsher 5561adfc5217SJeff Kirsher { 0x3c00, 0, 0x00000000, 0x00000001 }, 5562adfc5217SJeff Kirsher { 0x3c04, 0, 0x00000000, 0x00070000 }, 5563adfc5217SJeff Kirsher { 0x3c08, 0, 0x00007f71, 0x07f00000 }, 5564adfc5217SJeff Kirsher { 0x3c0c, 0, 0x1f3ffffc, 0x00000000 }, 5565adfc5217SJeff Kirsher { 0x3c10, 0, 0xffffffff, 0x00000000 }, 5566adfc5217SJeff Kirsher { 0x3c14, 0, 0x00000000, 0xffffffff }, 5567adfc5217SJeff Kirsher { 0x3c18, 0, 0x00000000, 0xffffffff }, 5568adfc5217SJeff Kirsher { 0x3c1c, 0, 0xfffff000, 0x00000000 }, 5569adfc5217SJeff Kirsher { 0x3c20, 0, 0xffffff00, 0x00000000 }, 5570adfc5217SJeff Kirsher 5571adfc5217SJeff Kirsher { 0x5004, 0, 0x00000000, 0x0000007f }, 5572adfc5217SJeff Kirsher { 0x5008, 0, 0x0f0007ff, 0x00000000 }, 5573adfc5217SJeff Kirsher 5574adfc5217SJeff Kirsher { 0x5c00, 0, 0x00000000, 0x00000001 }, 5575adfc5217SJeff Kirsher { 0x5c04, 0, 0x00000000, 0x0003000f }, 5576adfc5217SJeff Kirsher { 0x5c08, 0, 0x00000003, 0x00000000 }, 5577adfc5217SJeff Kirsher { 0x5c0c, 0, 0x0000fff8, 0x00000000 }, 5578adfc5217SJeff Kirsher { 0x5c10, 0, 0x00000000, 0xffffffff }, 5579adfc5217SJeff Kirsher { 0x5c80, 0, 0x00000000, 0x0f7113f1 }, 5580adfc5217SJeff Kirsher { 0x5c84, 0, 0x00000000, 0x0000f333 }, 5581adfc5217SJeff Kirsher { 0x5c88, 0, 0x00000000, 0x00077373 }, 5582adfc5217SJeff Kirsher { 0x5c8c, 0, 0x00000000, 0x0007f737 }, 5583adfc5217SJeff Kirsher 5584adfc5217SJeff Kirsher { 0x6808, 0, 0x0000ff7f, 0x00000000 }, 5585adfc5217SJeff Kirsher { 0x680c, 0, 0xffffffff, 0x00000000 }, 5586adfc5217SJeff Kirsher { 0x6810, 0, 0xffffffff, 0x00000000 }, 5587adfc5217SJeff Kirsher { 0x6814, 0, 0xffffffff, 0x00000000 }, 5588adfc5217SJeff Kirsher { 0x6818, 0, 0xffffffff, 0x00000000 }, 5589adfc5217SJeff Kirsher { 0x681c, 0, 0xffffffff, 0x00000000 }, 5590adfc5217SJeff Kirsher { 0x6820, 0, 0x00ff00ff, 0x00000000 }, 5591adfc5217SJeff Kirsher { 0x6824, 0, 0x00ff00ff, 0x00000000 }, 5592adfc5217SJeff Kirsher { 0x6828, 0, 0x00ff00ff, 0x00000000 }, 5593adfc5217SJeff Kirsher { 0x682c, 0, 0x03ff03ff, 0x00000000 }, 5594adfc5217SJeff Kirsher { 0x6830, 0, 0x03ff03ff, 0x00000000 }, 5595adfc5217SJeff Kirsher { 0x6834, 0, 0x03ff03ff, 0x00000000 }, 5596adfc5217SJeff Kirsher { 0x6838, 0, 0x03ff03ff, 0x00000000 }, 5597adfc5217SJeff Kirsher { 0x683c, 0, 0x0000ffff, 0x00000000 }, 5598adfc5217SJeff Kirsher { 0x6840, 0, 0x00000ff0, 0x00000000 }, 5599adfc5217SJeff Kirsher { 0x6844, 0, 0x00ffff00, 0x00000000 }, 5600adfc5217SJeff Kirsher { 0x684c, 0, 0xffffffff, 0x00000000 }, 5601adfc5217SJeff Kirsher { 0x6850, 0, 0x7f7f7f7f, 0x00000000 }, 5602adfc5217SJeff Kirsher { 0x6854, 0, 0x7f7f7f7f, 0x00000000 }, 5603adfc5217SJeff Kirsher { 0x6858, 0, 0x7f7f7f7f, 0x00000000 }, 5604adfc5217SJeff Kirsher { 0x685c, 0, 0x7f7f7f7f, 0x00000000 }, 5605adfc5217SJeff Kirsher { 0x6908, 0, 0x00000000, 0x0001ff0f }, 5606adfc5217SJeff Kirsher { 0x690c, 0, 0x00000000, 0x0ffe00f0 }, 5607adfc5217SJeff Kirsher 5608adfc5217SJeff Kirsher { 0xffff, 0, 0x00000000, 0x00000000 }, 5609adfc5217SJeff Kirsher }; 5610adfc5217SJeff Kirsher 5611adfc5217SJeff Kirsher ret = 0; 5612adfc5217SJeff Kirsher is_5709 = 0; 5613adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 5614adfc5217SJeff Kirsher is_5709 = 1; 5615adfc5217SJeff Kirsher 5616adfc5217SJeff Kirsher for (i = 0; reg_tbl[i].offset != 0xffff; i++) { 5617adfc5217SJeff Kirsher u32 offset, rw_mask, ro_mask, save_val, val; 5618adfc5217SJeff Kirsher u16 flags = reg_tbl[i].flags; 5619adfc5217SJeff Kirsher 5620adfc5217SJeff Kirsher if (is_5709 && (flags & BNX2_FL_NOT_5709)) 5621adfc5217SJeff Kirsher continue; 5622adfc5217SJeff Kirsher 5623adfc5217SJeff Kirsher offset = (u32) reg_tbl[i].offset; 5624adfc5217SJeff Kirsher rw_mask = reg_tbl[i].rw_mask; 5625adfc5217SJeff Kirsher ro_mask = reg_tbl[i].ro_mask; 5626adfc5217SJeff Kirsher 5627adfc5217SJeff Kirsher save_val = readl(bp->regview + offset); 5628adfc5217SJeff Kirsher 5629adfc5217SJeff Kirsher writel(0, bp->regview + offset); 5630adfc5217SJeff Kirsher 5631adfc5217SJeff Kirsher val = readl(bp->regview + offset); 5632adfc5217SJeff Kirsher if ((val & rw_mask) != 0) { 5633adfc5217SJeff Kirsher goto reg_test_err; 5634adfc5217SJeff Kirsher } 5635adfc5217SJeff Kirsher 5636adfc5217SJeff Kirsher if ((val & ro_mask) != (save_val & ro_mask)) { 5637adfc5217SJeff Kirsher goto reg_test_err; 5638adfc5217SJeff Kirsher } 5639adfc5217SJeff Kirsher 5640adfc5217SJeff Kirsher writel(0xffffffff, bp->regview + offset); 5641adfc5217SJeff Kirsher 5642adfc5217SJeff Kirsher val = readl(bp->regview + offset); 5643adfc5217SJeff Kirsher if ((val & rw_mask) != rw_mask) { 5644adfc5217SJeff Kirsher goto reg_test_err; 5645adfc5217SJeff Kirsher } 5646adfc5217SJeff Kirsher 5647adfc5217SJeff Kirsher if ((val & ro_mask) != (save_val & ro_mask)) { 5648adfc5217SJeff Kirsher goto reg_test_err; 5649adfc5217SJeff Kirsher } 5650adfc5217SJeff Kirsher 5651adfc5217SJeff Kirsher writel(save_val, bp->regview + offset); 5652adfc5217SJeff Kirsher continue; 5653adfc5217SJeff Kirsher 5654adfc5217SJeff Kirsher reg_test_err: 5655adfc5217SJeff Kirsher writel(save_val, bp->regview + offset); 5656adfc5217SJeff Kirsher ret = -ENODEV; 5657adfc5217SJeff Kirsher break; 5658adfc5217SJeff Kirsher } 5659adfc5217SJeff Kirsher return ret; 5660adfc5217SJeff Kirsher } 5661adfc5217SJeff Kirsher 5662adfc5217SJeff Kirsher static int 5663adfc5217SJeff Kirsher bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size) 5664adfc5217SJeff Kirsher { 5665adfc5217SJeff Kirsher static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555, 5666adfc5217SJeff Kirsher 0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa }; 5667adfc5217SJeff Kirsher int i; 5668adfc5217SJeff Kirsher 5669adfc5217SJeff Kirsher for (i = 0; i < sizeof(test_pattern) / 4; i++) { 5670adfc5217SJeff Kirsher u32 offset; 5671adfc5217SJeff Kirsher 5672adfc5217SJeff Kirsher for (offset = 0; offset < size; offset += 4) { 5673adfc5217SJeff Kirsher 5674adfc5217SJeff Kirsher bnx2_reg_wr_ind(bp, start + offset, test_pattern[i]); 5675adfc5217SJeff Kirsher 5676adfc5217SJeff Kirsher if (bnx2_reg_rd_ind(bp, start + offset) != 5677adfc5217SJeff Kirsher test_pattern[i]) { 5678adfc5217SJeff Kirsher return -ENODEV; 5679adfc5217SJeff Kirsher } 5680adfc5217SJeff Kirsher } 5681adfc5217SJeff Kirsher } 5682adfc5217SJeff Kirsher return 0; 5683adfc5217SJeff Kirsher } 5684adfc5217SJeff Kirsher 5685adfc5217SJeff Kirsher static int 5686adfc5217SJeff Kirsher bnx2_test_memory(struct bnx2 *bp) 5687adfc5217SJeff Kirsher { 5688adfc5217SJeff Kirsher int ret = 0; 5689adfc5217SJeff Kirsher int i; 5690adfc5217SJeff Kirsher static struct mem_entry { 5691adfc5217SJeff Kirsher u32 offset; 5692adfc5217SJeff Kirsher u32 len; 5693adfc5217SJeff Kirsher } mem_tbl_5706[] = { 5694adfc5217SJeff Kirsher { 0x60000, 0x4000 }, 5695adfc5217SJeff Kirsher { 0xa0000, 0x3000 }, 5696adfc5217SJeff Kirsher { 0xe0000, 0x4000 }, 5697adfc5217SJeff Kirsher { 0x120000, 0x4000 }, 5698adfc5217SJeff Kirsher { 0x1a0000, 0x4000 }, 5699adfc5217SJeff Kirsher { 0x160000, 0x4000 }, 5700adfc5217SJeff Kirsher { 0xffffffff, 0 }, 5701adfc5217SJeff Kirsher }, 5702adfc5217SJeff Kirsher mem_tbl_5709[] = { 5703adfc5217SJeff Kirsher { 0x60000, 0x4000 }, 5704adfc5217SJeff Kirsher { 0xa0000, 0x3000 }, 5705adfc5217SJeff Kirsher { 0xe0000, 0x4000 }, 5706adfc5217SJeff Kirsher { 0x120000, 0x4000 }, 5707adfc5217SJeff Kirsher { 0x1a0000, 0x4000 }, 5708adfc5217SJeff Kirsher { 0xffffffff, 0 }, 5709adfc5217SJeff Kirsher }; 5710adfc5217SJeff Kirsher struct mem_entry *mem_tbl; 5711adfc5217SJeff Kirsher 5712adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 5713adfc5217SJeff Kirsher mem_tbl = mem_tbl_5709; 5714adfc5217SJeff Kirsher else 5715adfc5217SJeff Kirsher mem_tbl = mem_tbl_5706; 5716adfc5217SJeff Kirsher 5717adfc5217SJeff Kirsher for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { 5718adfc5217SJeff Kirsher if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset, 5719adfc5217SJeff Kirsher mem_tbl[i].len)) != 0) { 5720adfc5217SJeff Kirsher return ret; 5721adfc5217SJeff Kirsher } 5722adfc5217SJeff Kirsher } 5723adfc5217SJeff Kirsher 5724adfc5217SJeff Kirsher return ret; 5725adfc5217SJeff Kirsher } 5726adfc5217SJeff Kirsher 5727adfc5217SJeff Kirsher #define BNX2_MAC_LOOPBACK 0 5728adfc5217SJeff Kirsher #define BNX2_PHY_LOOPBACK 1 5729adfc5217SJeff Kirsher 5730adfc5217SJeff Kirsher static int 5731adfc5217SJeff Kirsher bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) 5732adfc5217SJeff Kirsher { 5733adfc5217SJeff Kirsher unsigned int pkt_size, num_pkts, i; 5734dd2bc8e9SEric Dumazet struct sk_buff *skb; 5735dd2bc8e9SEric Dumazet u8 *data; 5736adfc5217SJeff Kirsher unsigned char *packet; 5737adfc5217SJeff Kirsher u16 rx_start_idx, rx_idx; 5738adfc5217SJeff Kirsher dma_addr_t map; 5739adfc5217SJeff Kirsher struct tx_bd *txbd; 5740adfc5217SJeff Kirsher struct sw_bd *rx_buf; 5741adfc5217SJeff Kirsher struct l2_fhdr *rx_hdr; 5742adfc5217SJeff Kirsher int ret = -ENODEV; 5743adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi; 5744adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; 5745adfc5217SJeff Kirsher struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; 5746adfc5217SJeff Kirsher 5747adfc5217SJeff Kirsher tx_napi = bnapi; 5748adfc5217SJeff Kirsher 5749adfc5217SJeff Kirsher txr = &tx_napi->tx_ring; 5750adfc5217SJeff Kirsher rxr = &bnapi->rx_ring; 5751adfc5217SJeff Kirsher if (loopback_mode == BNX2_MAC_LOOPBACK) { 5752adfc5217SJeff Kirsher bp->loopback = MAC_LOOPBACK; 5753adfc5217SJeff Kirsher bnx2_set_mac_loopback(bp); 5754adfc5217SJeff Kirsher } 5755adfc5217SJeff Kirsher else if (loopback_mode == BNX2_PHY_LOOPBACK) { 5756adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 5757adfc5217SJeff Kirsher return 0; 5758adfc5217SJeff Kirsher 5759adfc5217SJeff Kirsher bp->loopback = PHY_LOOPBACK; 5760adfc5217SJeff Kirsher bnx2_set_phy_loopback(bp); 5761adfc5217SJeff Kirsher } 5762adfc5217SJeff Kirsher else 5763adfc5217SJeff Kirsher return -EINVAL; 5764adfc5217SJeff Kirsher 5765adfc5217SJeff Kirsher pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_jumbo_thresh - 4); 5766adfc5217SJeff Kirsher skb = netdev_alloc_skb(bp->dev, pkt_size); 5767adfc5217SJeff Kirsher if (!skb) 5768adfc5217SJeff Kirsher return -ENOMEM; 5769adfc5217SJeff Kirsher packet = skb_put(skb, pkt_size); 5770adfc5217SJeff Kirsher memcpy(packet, bp->dev->dev_addr, 6); 5771adfc5217SJeff Kirsher memset(packet + 6, 0x0, 8); 5772adfc5217SJeff Kirsher for (i = 14; i < pkt_size; i++) 5773adfc5217SJeff Kirsher packet[i] = (unsigned char) (i & 0xff); 5774adfc5217SJeff Kirsher 5775adfc5217SJeff Kirsher map = dma_map_single(&bp->pdev->dev, skb->data, pkt_size, 5776adfc5217SJeff Kirsher PCI_DMA_TODEVICE); 5777adfc5217SJeff Kirsher if (dma_mapping_error(&bp->pdev->dev, map)) { 5778adfc5217SJeff Kirsher dev_kfree_skb(skb); 5779adfc5217SJeff Kirsher return -EIO; 5780adfc5217SJeff Kirsher } 5781adfc5217SJeff Kirsher 5782adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, 5783adfc5217SJeff Kirsher bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 5784adfc5217SJeff Kirsher 5785adfc5217SJeff Kirsher REG_RD(bp, BNX2_HC_COMMAND); 5786adfc5217SJeff Kirsher 5787adfc5217SJeff Kirsher udelay(5); 5788adfc5217SJeff Kirsher rx_start_idx = bnx2_get_hw_rx_cons(bnapi); 5789adfc5217SJeff Kirsher 5790adfc5217SJeff Kirsher num_pkts = 0; 5791adfc5217SJeff Kirsher 5792adfc5217SJeff Kirsher txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)]; 5793adfc5217SJeff Kirsher 5794adfc5217SJeff Kirsher txbd->tx_bd_haddr_hi = (u64) map >> 32; 5795adfc5217SJeff Kirsher txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff; 5796adfc5217SJeff Kirsher txbd->tx_bd_mss_nbytes = pkt_size; 5797adfc5217SJeff Kirsher txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END; 5798adfc5217SJeff Kirsher 5799adfc5217SJeff Kirsher num_pkts++; 5800adfc5217SJeff Kirsher txr->tx_prod = NEXT_TX_BD(txr->tx_prod); 5801adfc5217SJeff Kirsher txr->tx_prod_bseq += pkt_size; 5802adfc5217SJeff Kirsher 5803adfc5217SJeff Kirsher REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod); 5804adfc5217SJeff Kirsher REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); 5805adfc5217SJeff Kirsher 5806adfc5217SJeff Kirsher udelay(100); 5807adfc5217SJeff Kirsher 5808adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, 5809adfc5217SJeff Kirsher bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 5810adfc5217SJeff Kirsher 5811adfc5217SJeff Kirsher REG_RD(bp, BNX2_HC_COMMAND); 5812adfc5217SJeff Kirsher 5813adfc5217SJeff Kirsher udelay(5); 5814adfc5217SJeff Kirsher 5815adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, map, pkt_size, PCI_DMA_TODEVICE); 5816adfc5217SJeff Kirsher dev_kfree_skb(skb); 5817adfc5217SJeff Kirsher 5818adfc5217SJeff Kirsher if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod) 5819adfc5217SJeff Kirsher goto loopback_test_done; 5820adfc5217SJeff Kirsher 5821adfc5217SJeff Kirsher rx_idx = bnx2_get_hw_rx_cons(bnapi); 5822adfc5217SJeff Kirsher if (rx_idx != rx_start_idx + num_pkts) { 5823adfc5217SJeff Kirsher goto loopback_test_done; 5824adfc5217SJeff Kirsher } 5825adfc5217SJeff Kirsher 5826adfc5217SJeff Kirsher rx_buf = &rxr->rx_buf_ring[rx_start_idx]; 5827dd2bc8e9SEric Dumazet data = rx_buf->data; 5828adfc5217SJeff Kirsher 5829dd2bc8e9SEric Dumazet rx_hdr = get_l2_fhdr(data); 5830dd2bc8e9SEric Dumazet data = (u8 *)rx_hdr + BNX2_RX_OFFSET; 5831adfc5217SJeff Kirsher 5832adfc5217SJeff Kirsher dma_sync_single_for_cpu(&bp->pdev->dev, 5833adfc5217SJeff Kirsher dma_unmap_addr(rx_buf, mapping), 5834dd2bc8e9SEric Dumazet bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); 5835adfc5217SJeff Kirsher 5836adfc5217SJeff Kirsher if (rx_hdr->l2_fhdr_status & 5837adfc5217SJeff Kirsher (L2_FHDR_ERRORS_BAD_CRC | 5838adfc5217SJeff Kirsher L2_FHDR_ERRORS_PHY_DECODE | 5839adfc5217SJeff Kirsher L2_FHDR_ERRORS_ALIGNMENT | 5840adfc5217SJeff Kirsher L2_FHDR_ERRORS_TOO_SHORT | 5841adfc5217SJeff Kirsher L2_FHDR_ERRORS_GIANT_FRAME)) { 5842adfc5217SJeff Kirsher 5843adfc5217SJeff Kirsher goto loopback_test_done; 5844adfc5217SJeff Kirsher } 5845adfc5217SJeff Kirsher 5846adfc5217SJeff Kirsher if ((rx_hdr->l2_fhdr_pkt_len - 4) != pkt_size) { 5847adfc5217SJeff Kirsher goto loopback_test_done; 5848adfc5217SJeff Kirsher } 5849adfc5217SJeff Kirsher 5850adfc5217SJeff Kirsher for (i = 14; i < pkt_size; i++) { 5851dd2bc8e9SEric Dumazet if (*(data + i) != (unsigned char) (i & 0xff)) { 5852adfc5217SJeff Kirsher goto loopback_test_done; 5853adfc5217SJeff Kirsher } 5854adfc5217SJeff Kirsher } 5855adfc5217SJeff Kirsher 5856adfc5217SJeff Kirsher ret = 0; 5857adfc5217SJeff Kirsher 5858adfc5217SJeff Kirsher loopback_test_done: 5859adfc5217SJeff Kirsher bp->loopback = 0; 5860adfc5217SJeff Kirsher return ret; 5861adfc5217SJeff Kirsher } 5862adfc5217SJeff Kirsher 5863adfc5217SJeff Kirsher #define BNX2_MAC_LOOPBACK_FAILED 1 5864adfc5217SJeff Kirsher #define BNX2_PHY_LOOPBACK_FAILED 2 5865adfc5217SJeff Kirsher #define BNX2_LOOPBACK_FAILED (BNX2_MAC_LOOPBACK_FAILED | \ 5866adfc5217SJeff Kirsher BNX2_PHY_LOOPBACK_FAILED) 5867adfc5217SJeff Kirsher 5868adfc5217SJeff Kirsher static int 5869adfc5217SJeff Kirsher bnx2_test_loopback(struct bnx2 *bp) 5870adfc5217SJeff Kirsher { 5871adfc5217SJeff Kirsher int rc = 0; 5872adfc5217SJeff Kirsher 5873adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 5874adfc5217SJeff Kirsher return BNX2_LOOPBACK_FAILED; 5875adfc5217SJeff Kirsher 5876adfc5217SJeff Kirsher bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); 5877adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 5878adfc5217SJeff Kirsher bnx2_init_phy(bp, 1); 5879adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 5880adfc5217SJeff Kirsher if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK)) 5881adfc5217SJeff Kirsher rc |= BNX2_MAC_LOOPBACK_FAILED; 5882adfc5217SJeff Kirsher if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK)) 5883adfc5217SJeff Kirsher rc |= BNX2_PHY_LOOPBACK_FAILED; 5884adfc5217SJeff Kirsher return rc; 5885adfc5217SJeff Kirsher } 5886adfc5217SJeff Kirsher 5887adfc5217SJeff Kirsher #define NVRAM_SIZE 0x200 5888adfc5217SJeff Kirsher #define CRC32_RESIDUAL 0xdebb20e3 5889adfc5217SJeff Kirsher 5890adfc5217SJeff Kirsher static int 5891adfc5217SJeff Kirsher bnx2_test_nvram(struct bnx2 *bp) 5892adfc5217SJeff Kirsher { 5893adfc5217SJeff Kirsher __be32 buf[NVRAM_SIZE / 4]; 5894adfc5217SJeff Kirsher u8 *data = (u8 *) buf; 5895adfc5217SJeff Kirsher int rc = 0; 5896adfc5217SJeff Kirsher u32 magic, csum; 5897adfc5217SJeff Kirsher 5898adfc5217SJeff Kirsher if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0) 5899adfc5217SJeff Kirsher goto test_nvram_done; 5900adfc5217SJeff Kirsher 5901adfc5217SJeff Kirsher magic = be32_to_cpu(buf[0]); 5902adfc5217SJeff Kirsher if (magic != 0x669955aa) { 5903adfc5217SJeff Kirsher rc = -ENODEV; 5904adfc5217SJeff Kirsher goto test_nvram_done; 5905adfc5217SJeff Kirsher } 5906adfc5217SJeff Kirsher 5907adfc5217SJeff Kirsher if ((rc = bnx2_nvram_read(bp, 0x100, data, NVRAM_SIZE)) != 0) 5908adfc5217SJeff Kirsher goto test_nvram_done; 5909adfc5217SJeff Kirsher 5910adfc5217SJeff Kirsher csum = ether_crc_le(0x100, data); 5911adfc5217SJeff Kirsher if (csum != CRC32_RESIDUAL) { 5912adfc5217SJeff Kirsher rc = -ENODEV; 5913adfc5217SJeff Kirsher goto test_nvram_done; 5914adfc5217SJeff Kirsher } 5915adfc5217SJeff Kirsher 5916adfc5217SJeff Kirsher csum = ether_crc_le(0x100, data + 0x100); 5917adfc5217SJeff Kirsher if (csum != CRC32_RESIDUAL) { 5918adfc5217SJeff Kirsher rc = -ENODEV; 5919adfc5217SJeff Kirsher } 5920adfc5217SJeff Kirsher 5921adfc5217SJeff Kirsher test_nvram_done: 5922adfc5217SJeff Kirsher return rc; 5923adfc5217SJeff Kirsher } 5924adfc5217SJeff Kirsher 5925adfc5217SJeff Kirsher static int 5926adfc5217SJeff Kirsher bnx2_test_link(struct bnx2 *bp) 5927adfc5217SJeff Kirsher { 5928adfc5217SJeff Kirsher u32 bmsr; 5929adfc5217SJeff Kirsher 5930adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 5931adfc5217SJeff Kirsher return -ENODEV; 5932adfc5217SJeff Kirsher 5933adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) { 5934adfc5217SJeff Kirsher if (bp->link_up) 5935adfc5217SJeff Kirsher return 0; 5936adfc5217SJeff Kirsher return -ENODEV; 5937adfc5217SJeff Kirsher } 5938adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 5939adfc5217SJeff Kirsher bnx2_enable_bmsr1(bp); 5940adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); 5941adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); 5942adfc5217SJeff Kirsher bnx2_disable_bmsr1(bp); 5943adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 5944adfc5217SJeff Kirsher 5945adfc5217SJeff Kirsher if (bmsr & BMSR_LSTATUS) { 5946adfc5217SJeff Kirsher return 0; 5947adfc5217SJeff Kirsher } 5948adfc5217SJeff Kirsher return -ENODEV; 5949adfc5217SJeff Kirsher } 5950adfc5217SJeff Kirsher 5951adfc5217SJeff Kirsher static int 5952adfc5217SJeff Kirsher bnx2_test_intr(struct bnx2 *bp) 5953adfc5217SJeff Kirsher { 5954adfc5217SJeff Kirsher int i; 5955adfc5217SJeff Kirsher u16 status_idx; 5956adfc5217SJeff Kirsher 5957adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 5958adfc5217SJeff Kirsher return -ENODEV; 5959adfc5217SJeff Kirsher 5960adfc5217SJeff Kirsher status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; 5961adfc5217SJeff Kirsher 5962adfc5217SJeff Kirsher /* This register is not touched during run-time. */ 5963adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); 5964adfc5217SJeff Kirsher REG_RD(bp, BNX2_HC_COMMAND); 5965adfc5217SJeff Kirsher 5966adfc5217SJeff Kirsher for (i = 0; i < 10; i++) { 5967adfc5217SJeff Kirsher if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) != 5968adfc5217SJeff Kirsher status_idx) { 5969adfc5217SJeff Kirsher 5970adfc5217SJeff Kirsher break; 5971adfc5217SJeff Kirsher } 5972adfc5217SJeff Kirsher 5973adfc5217SJeff Kirsher msleep_interruptible(10); 5974adfc5217SJeff Kirsher } 5975adfc5217SJeff Kirsher if (i < 10) 5976adfc5217SJeff Kirsher return 0; 5977adfc5217SJeff Kirsher 5978adfc5217SJeff Kirsher return -ENODEV; 5979adfc5217SJeff Kirsher } 5980adfc5217SJeff Kirsher 5981adfc5217SJeff Kirsher /* Determining link for parallel detection. */ 5982adfc5217SJeff Kirsher static int 5983adfc5217SJeff Kirsher bnx2_5706_serdes_has_link(struct bnx2 *bp) 5984adfc5217SJeff Kirsher { 5985adfc5217SJeff Kirsher u32 mode_ctl, an_dbg, exp; 5986adfc5217SJeff Kirsher 5987adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_NO_PARALLEL) 5988adfc5217SJeff Kirsher return 0; 5989adfc5217SJeff Kirsher 5990adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_MODE_CTL); 5991adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &mode_ctl); 5992adfc5217SJeff Kirsher 5993adfc5217SJeff Kirsher if (!(mode_ctl & MISC_SHDW_MODE_CTL_SIG_DET)) 5994adfc5217SJeff Kirsher return 0; 5995adfc5217SJeff Kirsher 5996adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); 5997adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); 5998adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); 5999adfc5217SJeff Kirsher 6000adfc5217SJeff Kirsher if (an_dbg & (MISC_SHDW_AN_DBG_NOSYNC | MISC_SHDW_AN_DBG_RUDI_INVALID)) 6001adfc5217SJeff Kirsher return 0; 6002adfc5217SJeff Kirsher 6003adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_REG1); 6004adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp); 6005adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp); 6006adfc5217SJeff Kirsher 6007adfc5217SJeff Kirsher if (exp & MII_EXPAND_REG1_RUDI_C) /* receiving CONFIG */ 6008adfc5217SJeff Kirsher return 0; 6009adfc5217SJeff Kirsher 6010adfc5217SJeff Kirsher return 1; 6011adfc5217SJeff Kirsher } 6012adfc5217SJeff Kirsher 6013adfc5217SJeff Kirsher static void 6014adfc5217SJeff Kirsher bnx2_5706_serdes_timer(struct bnx2 *bp) 6015adfc5217SJeff Kirsher { 6016adfc5217SJeff Kirsher int check_link = 1; 6017adfc5217SJeff Kirsher 6018adfc5217SJeff Kirsher spin_lock(&bp->phy_lock); 6019adfc5217SJeff Kirsher if (bp->serdes_an_pending) { 6020adfc5217SJeff Kirsher bp->serdes_an_pending--; 6021adfc5217SJeff Kirsher check_link = 0; 6022adfc5217SJeff Kirsher } else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { 6023adfc5217SJeff Kirsher u32 bmcr; 6024adfc5217SJeff Kirsher 6025adfc5217SJeff Kirsher bp->current_interval = BNX2_TIMER_INTERVAL; 6026adfc5217SJeff Kirsher 6027adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 6028adfc5217SJeff Kirsher 6029adfc5217SJeff Kirsher if (bmcr & BMCR_ANENABLE) { 6030adfc5217SJeff Kirsher if (bnx2_5706_serdes_has_link(bp)) { 6031adfc5217SJeff Kirsher bmcr &= ~BMCR_ANENABLE; 6032adfc5217SJeff Kirsher bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; 6033adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr); 6034adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_PARALLEL_DETECT; 6035adfc5217SJeff Kirsher } 6036adfc5217SJeff Kirsher } 6037adfc5217SJeff Kirsher } 6038adfc5217SJeff Kirsher else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) && 6039adfc5217SJeff Kirsher (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)) { 6040adfc5217SJeff Kirsher u32 phy2; 6041adfc5217SJeff Kirsher 6042adfc5217SJeff Kirsher bnx2_write_phy(bp, 0x17, 0x0f01); 6043adfc5217SJeff Kirsher bnx2_read_phy(bp, 0x15, &phy2); 6044adfc5217SJeff Kirsher if (phy2 & 0x20) { 6045adfc5217SJeff Kirsher u32 bmcr; 6046adfc5217SJeff Kirsher 6047adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 6048adfc5217SJeff Kirsher bmcr |= BMCR_ANENABLE; 6049adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr); 6050adfc5217SJeff Kirsher 6051adfc5217SJeff Kirsher bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT; 6052adfc5217SJeff Kirsher } 6053adfc5217SJeff Kirsher } else 6054adfc5217SJeff Kirsher bp->current_interval = BNX2_TIMER_INTERVAL; 6055adfc5217SJeff Kirsher 6056adfc5217SJeff Kirsher if (check_link) { 6057adfc5217SJeff Kirsher u32 val; 6058adfc5217SJeff Kirsher 6059adfc5217SJeff Kirsher bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); 6060adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); 6061adfc5217SJeff Kirsher bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); 6062adfc5217SJeff Kirsher 6063adfc5217SJeff Kirsher if (bp->link_up && (val & MISC_SHDW_AN_DBG_NOSYNC)) { 6064adfc5217SJeff Kirsher if (!(bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN)) { 6065adfc5217SJeff Kirsher bnx2_5706s_force_link_dn(bp, 1); 6066adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN; 6067adfc5217SJeff Kirsher } else 6068adfc5217SJeff Kirsher bnx2_set_link(bp); 6069adfc5217SJeff Kirsher } else if (!bp->link_up && !(val & MISC_SHDW_AN_DBG_NOSYNC)) 6070adfc5217SJeff Kirsher bnx2_set_link(bp); 6071adfc5217SJeff Kirsher } 6072adfc5217SJeff Kirsher spin_unlock(&bp->phy_lock); 6073adfc5217SJeff Kirsher } 6074adfc5217SJeff Kirsher 6075adfc5217SJeff Kirsher static void 6076adfc5217SJeff Kirsher bnx2_5708_serdes_timer(struct bnx2 *bp) 6077adfc5217SJeff Kirsher { 6078adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 6079adfc5217SJeff Kirsher return; 6080adfc5217SJeff Kirsher 6081adfc5217SJeff Kirsher if ((bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) == 0) { 6082adfc5217SJeff Kirsher bp->serdes_an_pending = 0; 6083adfc5217SJeff Kirsher return; 6084adfc5217SJeff Kirsher } 6085adfc5217SJeff Kirsher 6086adfc5217SJeff Kirsher spin_lock(&bp->phy_lock); 6087adfc5217SJeff Kirsher if (bp->serdes_an_pending) 6088adfc5217SJeff Kirsher bp->serdes_an_pending--; 6089adfc5217SJeff Kirsher else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { 6090adfc5217SJeff Kirsher u32 bmcr; 6091adfc5217SJeff Kirsher 6092adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 6093adfc5217SJeff Kirsher if (bmcr & BMCR_ANENABLE) { 6094adfc5217SJeff Kirsher bnx2_enable_forced_2g5(bp); 6095adfc5217SJeff Kirsher bp->current_interval = BNX2_SERDES_FORCED_TIMEOUT; 6096adfc5217SJeff Kirsher } else { 6097adfc5217SJeff Kirsher bnx2_disable_forced_2g5(bp); 6098adfc5217SJeff Kirsher bp->serdes_an_pending = 2; 6099adfc5217SJeff Kirsher bp->current_interval = BNX2_TIMER_INTERVAL; 6100adfc5217SJeff Kirsher } 6101adfc5217SJeff Kirsher 6102adfc5217SJeff Kirsher } else 6103adfc5217SJeff Kirsher bp->current_interval = BNX2_TIMER_INTERVAL; 6104adfc5217SJeff Kirsher 6105adfc5217SJeff Kirsher spin_unlock(&bp->phy_lock); 6106adfc5217SJeff Kirsher } 6107adfc5217SJeff Kirsher 6108adfc5217SJeff Kirsher static void 6109adfc5217SJeff Kirsher bnx2_timer(unsigned long data) 6110adfc5217SJeff Kirsher { 6111adfc5217SJeff Kirsher struct bnx2 *bp = (struct bnx2 *) data; 6112adfc5217SJeff Kirsher 6113adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 6114adfc5217SJeff Kirsher return; 6115adfc5217SJeff Kirsher 6116adfc5217SJeff Kirsher if (atomic_read(&bp->intr_sem) != 0) 6117adfc5217SJeff Kirsher goto bnx2_restart_timer; 6118adfc5217SJeff Kirsher 6119adfc5217SJeff Kirsher if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) == 6120adfc5217SJeff Kirsher BNX2_FLAG_USING_MSI) 6121adfc5217SJeff Kirsher bnx2_chk_missed_msi(bp); 6122adfc5217SJeff Kirsher 6123adfc5217SJeff Kirsher bnx2_send_heart_beat(bp); 6124adfc5217SJeff Kirsher 6125adfc5217SJeff Kirsher bp->stats_blk->stat_FwRxDrop = 6126adfc5217SJeff Kirsher bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT); 6127adfc5217SJeff Kirsher 6128adfc5217SJeff Kirsher /* workaround occasional corrupted counters */ 6129adfc5217SJeff Kirsher if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks) 6130adfc5217SJeff Kirsher REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | 6131adfc5217SJeff Kirsher BNX2_HC_COMMAND_STATS_NOW); 6132adfc5217SJeff Kirsher 6133adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 6134adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706) 6135adfc5217SJeff Kirsher bnx2_5706_serdes_timer(bp); 6136adfc5217SJeff Kirsher else 6137adfc5217SJeff Kirsher bnx2_5708_serdes_timer(bp); 6138adfc5217SJeff Kirsher } 6139adfc5217SJeff Kirsher 6140adfc5217SJeff Kirsher bnx2_restart_timer: 6141adfc5217SJeff Kirsher mod_timer(&bp->timer, jiffies + bp->current_interval); 6142adfc5217SJeff Kirsher } 6143adfc5217SJeff Kirsher 6144adfc5217SJeff Kirsher static int 6145adfc5217SJeff Kirsher bnx2_request_irq(struct bnx2 *bp) 6146adfc5217SJeff Kirsher { 6147adfc5217SJeff Kirsher unsigned long flags; 6148adfc5217SJeff Kirsher struct bnx2_irq *irq; 6149adfc5217SJeff Kirsher int rc = 0, i; 6150adfc5217SJeff Kirsher 6151adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX) 6152adfc5217SJeff Kirsher flags = 0; 6153adfc5217SJeff Kirsher else 6154adfc5217SJeff Kirsher flags = IRQF_SHARED; 6155adfc5217SJeff Kirsher 6156adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 6157adfc5217SJeff Kirsher irq = &bp->irq_tbl[i]; 6158adfc5217SJeff Kirsher rc = request_irq(irq->vector, irq->handler, flags, irq->name, 6159adfc5217SJeff Kirsher &bp->bnx2_napi[i]); 6160adfc5217SJeff Kirsher if (rc) 6161adfc5217SJeff Kirsher break; 6162adfc5217SJeff Kirsher irq->requested = 1; 6163adfc5217SJeff Kirsher } 6164adfc5217SJeff Kirsher return rc; 6165adfc5217SJeff Kirsher } 6166adfc5217SJeff Kirsher 6167adfc5217SJeff Kirsher static void 6168adfc5217SJeff Kirsher __bnx2_free_irq(struct bnx2 *bp) 6169adfc5217SJeff Kirsher { 6170adfc5217SJeff Kirsher struct bnx2_irq *irq; 6171adfc5217SJeff Kirsher int i; 6172adfc5217SJeff Kirsher 6173adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 6174adfc5217SJeff Kirsher irq = &bp->irq_tbl[i]; 6175adfc5217SJeff Kirsher if (irq->requested) 6176adfc5217SJeff Kirsher free_irq(irq->vector, &bp->bnx2_napi[i]); 6177adfc5217SJeff Kirsher irq->requested = 0; 6178adfc5217SJeff Kirsher } 6179adfc5217SJeff Kirsher } 6180adfc5217SJeff Kirsher 6181adfc5217SJeff Kirsher static void 6182adfc5217SJeff Kirsher bnx2_free_irq(struct bnx2 *bp) 6183adfc5217SJeff Kirsher { 6184adfc5217SJeff Kirsher 6185adfc5217SJeff Kirsher __bnx2_free_irq(bp); 6186adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSI) 6187adfc5217SJeff Kirsher pci_disable_msi(bp->pdev); 6188adfc5217SJeff Kirsher else if (bp->flags & BNX2_FLAG_USING_MSIX) 6189adfc5217SJeff Kirsher pci_disable_msix(bp->pdev); 6190adfc5217SJeff Kirsher 6191adfc5217SJeff Kirsher bp->flags &= ~(BNX2_FLAG_USING_MSI_OR_MSIX | BNX2_FLAG_ONE_SHOT_MSI); 6192adfc5217SJeff Kirsher } 6193adfc5217SJeff Kirsher 6194adfc5217SJeff Kirsher static void 6195adfc5217SJeff Kirsher bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) 6196adfc5217SJeff Kirsher { 6197adfc5217SJeff Kirsher int i, total_vecs, rc; 6198adfc5217SJeff Kirsher struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC]; 6199adfc5217SJeff Kirsher struct net_device *dev = bp->dev; 6200adfc5217SJeff Kirsher const int len = sizeof(bp->irq_tbl[0].name); 6201adfc5217SJeff Kirsher 6202adfc5217SJeff Kirsher bnx2_setup_msix_tbl(bp); 6203adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1); 6204adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); 6205adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); 6206adfc5217SJeff Kirsher 6207adfc5217SJeff Kirsher /* Need to flush the previous three writes to ensure MSI-X 6208adfc5217SJeff Kirsher * is setup properly */ 6209adfc5217SJeff Kirsher REG_RD(bp, BNX2_PCI_MSIX_CONTROL); 6210adfc5217SJeff Kirsher 6211adfc5217SJeff Kirsher for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { 6212adfc5217SJeff Kirsher msix_ent[i].entry = i; 6213adfc5217SJeff Kirsher msix_ent[i].vector = 0; 6214adfc5217SJeff Kirsher } 6215adfc5217SJeff Kirsher 6216adfc5217SJeff Kirsher total_vecs = msix_vecs; 6217adfc5217SJeff Kirsher #ifdef BCM_CNIC 6218adfc5217SJeff Kirsher total_vecs++; 6219adfc5217SJeff Kirsher #endif 6220adfc5217SJeff Kirsher rc = -ENOSPC; 6221adfc5217SJeff Kirsher while (total_vecs >= BNX2_MIN_MSIX_VEC) { 6222adfc5217SJeff Kirsher rc = pci_enable_msix(bp->pdev, msix_ent, total_vecs); 6223adfc5217SJeff Kirsher if (rc <= 0) 6224adfc5217SJeff Kirsher break; 6225adfc5217SJeff Kirsher if (rc > 0) 6226adfc5217SJeff Kirsher total_vecs = rc; 6227adfc5217SJeff Kirsher } 6228adfc5217SJeff Kirsher 6229adfc5217SJeff Kirsher if (rc != 0) 6230adfc5217SJeff Kirsher return; 6231adfc5217SJeff Kirsher 6232adfc5217SJeff Kirsher msix_vecs = total_vecs; 6233adfc5217SJeff Kirsher #ifdef BCM_CNIC 6234adfc5217SJeff Kirsher msix_vecs--; 6235adfc5217SJeff Kirsher #endif 6236adfc5217SJeff Kirsher bp->irq_nvecs = msix_vecs; 6237adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI; 6238adfc5217SJeff Kirsher for (i = 0; i < total_vecs; i++) { 6239adfc5217SJeff Kirsher bp->irq_tbl[i].vector = msix_ent[i].vector; 6240adfc5217SJeff Kirsher snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); 6241adfc5217SJeff Kirsher bp->irq_tbl[i].handler = bnx2_msi_1shot; 6242adfc5217SJeff Kirsher } 6243adfc5217SJeff Kirsher } 6244adfc5217SJeff Kirsher 6245adfc5217SJeff Kirsher static int 6246adfc5217SJeff Kirsher bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) 6247adfc5217SJeff Kirsher { 6248adfc5217SJeff Kirsher int cpus = num_online_cpus(); 6249b033281fSMichael Chan int msix_vecs; 6250b033281fSMichael Chan 6251b033281fSMichael Chan if (!bp->num_req_rx_rings) 6252b033281fSMichael Chan msix_vecs = max(cpus + 1, bp->num_req_tx_rings); 6253b033281fSMichael Chan else if (!bp->num_req_tx_rings) 6254b033281fSMichael Chan msix_vecs = max(cpus, bp->num_req_rx_rings); 6255b033281fSMichael Chan else 6256b033281fSMichael Chan msix_vecs = max(bp->num_req_rx_rings, bp->num_req_tx_rings); 6257b033281fSMichael Chan 6258b033281fSMichael Chan msix_vecs = min(msix_vecs, RX_MAX_RINGS); 6259adfc5217SJeff Kirsher 6260adfc5217SJeff Kirsher bp->irq_tbl[0].handler = bnx2_interrupt; 6261adfc5217SJeff Kirsher strcpy(bp->irq_tbl[0].name, bp->dev->name); 6262adfc5217SJeff Kirsher bp->irq_nvecs = 1; 6263adfc5217SJeff Kirsher bp->irq_tbl[0].vector = bp->pdev->irq; 6264adfc5217SJeff Kirsher 6265adfc5217SJeff Kirsher if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi) 6266adfc5217SJeff Kirsher bnx2_enable_msix(bp, msix_vecs); 6267adfc5217SJeff Kirsher 6268adfc5217SJeff Kirsher if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi && 6269adfc5217SJeff Kirsher !(bp->flags & BNX2_FLAG_USING_MSIX)) { 6270adfc5217SJeff Kirsher if (pci_enable_msi(bp->pdev) == 0) { 6271adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_USING_MSI; 6272adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 6273adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_ONE_SHOT_MSI; 6274adfc5217SJeff Kirsher bp->irq_tbl[0].handler = bnx2_msi_1shot; 6275adfc5217SJeff Kirsher } else 6276adfc5217SJeff Kirsher bp->irq_tbl[0].handler = bnx2_msi; 6277adfc5217SJeff Kirsher 6278adfc5217SJeff Kirsher bp->irq_tbl[0].vector = bp->pdev->irq; 6279adfc5217SJeff Kirsher } 6280adfc5217SJeff Kirsher } 6281adfc5217SJeff Kirsher 6282b033281fSMichael Chan if (!bp->num_req_tx_rings) 6283adfc5217SJeff Kirsher bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs); 6284b033281fSMichael Chan else 6285b033281fSMichael Chan bp->num_tx_rings = min(bp->irq_nvecs, bp->num_req_tx_rings); 6286b033281fSMichael Chan 6287b033281fSMichael Chan if (!bp->num_req_rx_rings) 6288b033281fSMichael Chan bp->num_rx_rings = bp->irq_nvecs; 6289b033281fSMichael Chan else 6290b033281fSMichael Chan bp->num_rx_rings = min(bp->irq_nvecs, bp->num_req_rx_rings); 6291b033281fSMichael Chan 6292adfc5217SJeff Kirsher netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings); 6293adfc5217SJeff Kirsher 6294adfc5217SJeff Kirsher return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings); 6295adfc5217SJeff Kirsher } 6296adfc5217SJeff Kirsher 6297adfc5217SJeff Kirsher /* Called with rtnl_lock */ 6298adfc5217SJeff Kirsher static int 6299adfc5217SJeff Kirsher bnx2_open(struct net_device *dev) 6300adfc5217SJeff Kirsher { 6301adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6302adfc5217SJeff Kirsher int rc; 6303adfc5217SJeff Kirsher 63047880b72eSfrançois romieu rc = bnx2_request_firmware(bp); 63057880b72eSfrançois romieu if (rc < 0) 63067880b72eSfrançois romieu goto out; 63077880b72eSfrançois romieu 6308adfc5217SJeff Kirsher netif_carrier_off(dev); 6309adfc5217SJeff Kirsher 6310adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 6311adfc5217SJeff Kirsher bnx2_disable_int(bp); 6312adfc5217SJeff Kirsher 6313adfc5217SJeff Kirsher rc = bnx2_setup_int_mode(bp, disable_msi); 6314adfc5217SJeff Kirsher if (rc) 6315adfc5217SJeff Kirsher goto open_err; 6316adfc5217SJeff Kirsher bnx2_init_napi(bp); 6317adfc5217SJeff Kirsher bnx2_napi_enable(bp); 6318adfc5217SJeff Kirsher rc = bnx2_alloc_mem(bp); 6319adfc5217SJeff Kirsher if (rc) 6320adfc5217SJeff Kirsher goto open_err; 6321adfc5217SJeff Kirsher 6322adfc5217SJeff Kirsher rc = bnx2_request_irq(bp); 6323adfc5217SJeff Kirsher if (rc) 6324adfc5217SJeff Kirsher goto open_err; 6325adfc5217SJeff Kirsher 6326adfc5217SJeff Kirsher rc = bnx2_init_nic(bp, 1); 6327adfc5217SJeff Kirsher if (rc) 6328adfc5217SJeff Kirsher goto open_err; 6329adfc5217SJeff Kirsher 6330adfc5217SJeff Kirsher mod_timer(&bp->timer, jiffies + bp->current_interval); 6331adfc5217SJeff Kirsher 6332adfc5217SJeff Kirsher atomic_set(&bp->intr_sem, 0); 6333adfc5217SJeff Kirsher 6334adfc5217SJeff Kirsher memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block)); 6335adfc5217SJeff Kirsher 6336adfc5217SJeff Kirsher bnx2_enable_int(bp); 6337adfc5217SJeff Kirsher 6338adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSI) { 6339adfc5217SJeff Kirsher /* Test MSI to make sure it is working 6340adfc5217SJeff Kirsher * If MSI test fails, go back to INTx mode 6341adfc5217SJeff Kirsher */ 6342adfc5217SJeff Kirsher if (bnx2_test_intr(bp) != 0) { 6343adfc5217SJeff Kirsher netdev_warn(bp->dev, "No interrupt was generated using MSI, switching to INTx mode. Please report this failure to the PCI maintainer and include system chipset information.\n"); 6344adfc5217SJeff Kirsher 6345adfc5217SJeff Kirsher bnx2_disable_int(bp); 6346adfc5217SJeff Kirsher bnx2_free_irq(bp); 6347adfc5217SJeff Kirsher 6348adfc5217SJeff Kirsher bnx2_setup_int_mode(bp, 1); 6349adfc5217SJeff Kirsher 6350adfc5217SJeff Kirsher rc = bnx2_init_nic(bp, 0); 6351adfc5217SJeff Kirsher 6352adfc5217SJeff Kirsher if (!rc) 6353adfc5217SJeff Kirsher rc = bnx2_request_irq(bp); 6354adfc5217SJeff Kirsher 6355adfc5217SJeff Kirsher if (rc) { 6356adfc5217SJeff Kirsher del_timer_sync(&bp->timer); 6357adfc5217SJeff Kirsher goto open_err; 6358adfc5217SJeff Kirsher } 6359adfc5217SJeff Kirsher bnx2_enable_int(bp); 6360adfc5217SJeff Kirsher } 6361adfc5217SJeff Kirsher } 6362adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSI) 6363adfc5217SJeff Kirsher netdev_info(dev, "using MSI\n"); 6364adfc5217SJeff Kirsher else if (bp->flags & BNX2_FLAG_USING_MSIX) 6365adfc5217SJeff Kirsher netdev_info(dev, "using MSIX\n"); 6366adfc5217SJeff Kirsher 6367adfc5217SJeff Kirsher netif_tx_start_all_queues(dev); 63687880b72eSfrançois romieu out: 63697880b72eSfrançois romieu return rc; 6370adfc5217SJeff Kirsher 6371adfc5217SJeff Kirsher open_err: 6372adfc5217SJeff Kirsher bnx2_napi_disable(bp); 6373adfc5217SJeff Kirsher bnx2_free_skbs(bp); 6374adfc5217SJeff Kirsher bnx2_free_irq(bp); 6375adfc5217SJeff Kirsher bnx2_free_mem(bp); 6376adfc5217SJeff Kirsher bnx2_del_napi(bp); 63777880b72eSfrançois romieu bnx2_release_firmware(bp); 63787880b72eSfrançois romieu goto out; 6379adfc5217SJeff Kirsher } 6380adfc5217SJeff Kirsher 6381adfc5217SJeff Kirsher static void 6382adfc5217SJeff Kirsher bnx2_reset_task(struct work_struct *work) 6383adfc5217SJeff Kirsher { 6384adfc5217SJeff Kirsher struct bnx2 *bp = container_of(work, struct bnx2, reset_task); 6385adfc5217SJeff Kirsher int rc; 6386adfc5217SJeff Kirsher 6387adfc5217SJeff Kirsher rtnl_lock(); 6388adfc5217SJeff Kirsher if (!netif_running(bp->dev)) { 6389adfc5217SJeff Kirsher rtnl_unlock(); 6390adfc5217SJeff Kirsher return; 6391adfc5217SJeff Kirsher } 6392adfc5217SJeff Kirsher 6393adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 6394adfc5217SJeff Kirsher 6395adfc5217SJeff Kirsher rc = bnx2_init_nic(bp, 1); 6396adfc5217SJeff Kirsher if (rc) { 6397adfc5217SJeff Kirsher netdev_err(bp->dev, "failed to reset NIC, closing\n"); 6398adfc5217SJeff Kirsher bnx2_napi_enable(bp); 6399adfc5217SJeff Kirsher dev_close(bp->dev); 6400adfc5217SJeff Kirsher rtnl_unlock(); 6401adfc5217SJeff Kirsher return; 6402adfc5217SJeff Kirsher } 6403adfc5217SJeff Kirsher 6404adfc5217SJeff Kirsher atomic_set(&bp->intr_sem, 1); 6405adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 6406adfc5217SJeff Kirsher rtnl_unlock(); 6407adfc5217SJeff Kirsher } 6408adfc5217SJeff Kirsher 6409adfc5217SJeff Kirsher static void 6410adfc5217SJeff Kirsher bnx2_dump_state(struct bnx2 *bp) 6411adfc5217SJeff Kirsher { 6412adfc5217SJeff Kirsher struct net_device *dev = bp->dev; 6413adfc5217SJeff Kirsher u32 val1, val2; 6414adfc5217SJeff Kirsher 6415adfc5217SJeff Kirsher pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1); 6416adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n", 6417adfc5217SJeff Kirsher atomic_read(&bp->intr_sem), val1); 6418adfc5217SJeff Kirsher pci_read_config_dword(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &val1); 6419adfc5217SJeff Kirsher pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2); 6420adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2); 6421adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n", 6422adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_TX_STATUS), 6423adfc5217SJeff Kirsher REG_RD(bp, BNX2_EMAC_RX_STATUS)); 6424adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n", 6425adfc5217SJeff Kirsher REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL)); 6426adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n", 6427adfc5217SJeff Kirsher REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS)); 6428adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_USING_MSIX) 6429adfc5217SJeff Kirsher netdev_err(dev, "DEBUG: PBA[%08x]\n", 6430adfc5217SJeff Kirsher REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE)); 6431adfc5217SJeff Kirsher } 6432adfc5217SJeff Kirsher 6433adfc5217SJeff Kirsher static void 6434adfc5217SJeff Kirsher bnx2_tx_timeout(struct net_device *dev) 6435adfc5217SJeff Kirsher { 6436adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6437adfc5217SJeff Kirsher 6438adfc5217SJeff Kirsher bnx2_dump_state(bp); 6439adfc5217SJeff Kirsher bnx2_dump_mcp_state(bp); 6440adfc5217SJeff Kirsher 6441adfc5217SJeff Kirsher /* This allows the netif to be shutdown gracefully before resetting */ 6442adfc5217SJeff Kirsher schedule_work(&bp->reset_task); 6443adfc5217SJeff Kirsher } 6444adfc5217SJeff Kirsher 6445adfc5217SJeff Kirsher /* Called with netif_tx_lock. 6446adfc5217SJeff Kirsher * bnx2_tx_int() runs without netif_tx_lock unless it needs to call 6447adfc5217SJeff Kirsher * netif_wake_queue(). 6448adfc5217SJeff Kirsher */ 6449adfc5217SJeff Kirsher static netdev_tx_t 6450adfc5217SJeff Kirsher bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) 6451adfc5217SJeff Kirsher { 6452adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6453adfc5217SJeff Kirsher dma_addr_t mapping; 6454adfc5217SJeff Kirsher struct tx_bd *txbd; 6455adfc5217SJeff Kirsher struct sw_tx_bd *tx_buf; 6456adfc5217SJeff Kirsher u32 len, vlan_tag_flags, last_frag, mss; 6457adfc5217SJeff Kirsher u16 prod, ring_prod; 6458adfc5217SJeff Kirsher int i; 6459adfc5217SJeff Kirsher struct bnx2_napi *bnapi; 6460adfc5217SJeff Kirsher struct bnx2_tx_ring_info *txr; 6461adfc5217SJeff Kirsher struct netdev_queue *txq; 6462adfc5217SJeff Kirsher 6463adfc5217SJeff Kirsher /* Determine which tx ring we will be placed on */ 6464adfc5217SJeff Kirsher i = skb_get_queue_mapping(skb); 6465adfc5217SJeff Kirsher bnapi = &bp->bnx2_napi[i]; 6466adfc5217SJeff Kirsher txr = &bnapi->tx_ring; 6467adfc5217SJeff Kirsher txq = netdev_get_tx_queue(dev, i); 6468adfc5217SJeff Kirsher 6469adfc5217SJeff Kirsher if (unlikely(bnx2_tx_avail(bp, txr) < 6470adfc5217SJeff Kirsher (skb_shinfo(skb)->nr_frags + 1))) { 6471adfc5217SJeff Kirsher netif_tx_stop_queue(txq); 6472adfc5217SJeff Kirsher netdev_err(dev, "BUG! Tx ring full when queue awake!\n"); 6473adfc5217SJeff Kirsher 6474adfc5217SJeff Kirsher return NETDEV_TX_BUSY; 6475adfc5217SJeff Kirsher } 6476adfc5217SJeff Kirsher len = skb_headlen(skb); 6477adfc5217SJeff Kirsher prod = txr->tx_prod; 6478adfc5217SJeff Kirsher ring_prod = TX_RING_IDX(prod); 6479adfc5217SJeff Kirsher 6480adfc5217SJeff Kirsher vlan_tag_flags = 0; 6481adfc5217SJeff Kirsher if (skb->ip_summed == CHECKSUM_PARTIAL) { 6482adfc5217SJeff Kirsher vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; 6483adfc5217SJeff Kirsher } 6484adfc5217SJeff Kirsher 6485adfc5217SJeff Kirsher if (vlan_tx_tag_present(skb)) { 6486adfc5217SJeff Kirsher vlan_tag_flags |= 6487adfc5217SJeff Kirsher (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); 6488adfc5217SJeff Kirsher } 6489adfc5217SJeff Kirsher 6490adfc5217SJeff Kirsher if ((mss = skb_shinfo(skb)->gso_size)) { 6491adfc5217SJeff Kirsher u32 tcp_opt_len; 6492adfc5217SJeff Kirsher struct iphdr *iph; 6493adfc5217SJeff Kirsher 6494adfc5217SJeff Kirsher vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; 6495adfc5217SJeff Kirsher 6496adfc5217SJeff Kirsher tcp_opt_len = tcp_optlen(skb); 6497adfc5217SJeff Kirsher 6498adfc5217SJeff Kirsher if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { 6499adfc5217SJeff Kirsher u32 tcp_off = skb_transport_offset(skb) - 6500adfc5217SJeff Kirsher sizeof(struct ipv6hdr) - ETH_HLEN; 6501adfc5217SJeff Kirsher 6502adfc5217SJeff Kirsher vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) | 6503adfc5217SJeff Kirsher TX_BD_FLAGS_SW_FLAGS; 6504adfc5217SJeff Kirsher if (likely(tcp_off == 0)) 6505adfc5217SJeff Kirsher vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK; 6506adfc5217SJeff Kirsher else { 6507adfc5217SJeff Kirsher tcp_off >>= 3; 6508adfc5217SJeff Kirsher vlan_tag_flags |= ((tcp_off & 0x3) << 6509adfc5217SJeff Kirsher TX_BD_FLAGS_TCP6_OFF0_SHL) | 6510adfc5217SJeff Kirsher ((tcp_off & 0x10) << 6511adfc5217SJeff Kirsher TX_BD_FLAGS_TCP6_OFF4_SHL); 6512adfc5217SJeff Kirsher mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL; 6513adfc5217SJeff Kirsher } 6514adfc5217SJeff Kirsher } else { 6515adfc5217SJeff Kirsher iph = ip_hdr(skb); 6516adfc5217SJeff Kirsher if (tcp_opt_len || (iph->ihl > 5)) { 6517adfc5217SJeff Kirsher vlan_tag_flags |= ((iph->ihl - 5) + 6518adfc5217SJeff Kirsher (tcp_opt_len >> 2)) << 8; 6519adfc5217SJeff Kirsher } 6520adfc5217SJeff Kirsher } 6521adfc5217SJeff Kirsher } else 6522adfc5217SJeff Kirsher mss = 0; 6523adfc5217SJeff Kirsher 6524adfc5217SJeff Kirsher mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); 6525adfc5217SJeff Kirsher if (dma_mapping_error(&bp->pdev->dev, mapping)) { 6526adfc5217SJeff Kirsher dev_kfree_skb(skb); 6527adfc5217SJeff Kirsher return NETDEV_TX_OK; 6528adfc5217SJeff Kirsher } 6529adfc5217SJeff Kirsher 6530adfc5217SJeff Kirsher tx_buf = &txr->tx_buf_ring[ring_prod]; 6531adfc5217SJeff Kirsher tx_buf->skb = skb; 6532adfc5217SJeff Kirsher dma_unmap_addr_set(tx_buf, mapping, mapping); 6533adfc5217SJeff Kirsher 6534adfc5217SJeff Kirsher txbd = &txr->tx_desc_ring[ring_prod]; 6535adfc5217SJeff Kirsher 6536adfc5217SJeff Kirsher txbd->tx_bd_haddr_hi = (u64) mapping >> 32; 6537adfc5217SJeff Kirsher txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; 6538adfc5217SJeff Kirsher txbd->tx_bd_mss_nbytes = len | (mss << 16); 6539adfc5217SJeff Kirsher txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START; 6540adfc5217SJeff Kirsher 6541adfc5217SJeff Kirsher last_frag = skb_shinfo(skb)->nr_frags; 6542adfc5217SJeff Kirsher tx_buf->nr_frags = last_frag; 6543adfc5217SJeff Kirsher tx_buf->is_gso = skb_is_gso(skb); 6544adfc5217SJeff Kirsher 6545adfc5217SJeff Kirsher for (i = 0; i < last_frag; i++) { 65469e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 6547adfc5217SJeff Kirsher 6548adfc5217SJeff Kirsher prod = NEXT_TX_BD(prod); 6549adfc5217SJeff Kirsher ring_prod = TX_RING_IDX(prod); 6550adfc5217SJeff Kirsher txbd = &txr->tx_desc_ring[ring_prod]; 6551adfc5217SJeff Kirsher 65529e903e08SEric Dumazet len = skb_frag_size(frag); 6553b7b6a688SIan Campbell mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, len, 65545d6bcdfeSIan Campbell DMA_TO_DEVICE); 6555adfc5217SJeff Kirsher if (dma_mapping_error(&bp->pdev->dev, mapping)) 6556adfc5217SJeff Kirsher goto dma_error; 6557adfc5217SJeff Kirsher dma_unmap_addr_set(&txr->tx_buf_ring[ring_prod], mapping, 6558adfc5217SJeff Kirsher mapping); 6559adfc5217SJeff Kirsher 6560adfc5217SJeff Kirsher txbd->tx_bd_haddr_hi = (u64) mapping >> 32; 6561adfc5217SJeff Kirsher txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; 6562adfc5217SJeff Kirsher txbd->tx_bd_mss_nbytes = len | (mss << 16); 6563adfc5217SJeff Kirsher txbd->tx_bd_vlan_tag_flags = vlan_tag_flags; 6564adfc5217SJeff Kirsher 6565adfc5217SJeff Kirsher } 6566adfc5217SJeff Kirsher txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; 6567adfc5217SJeff Kirsher 656894bf91baSVlad Zolotarov /* Sync BD data before updating TX mailbox */ 656994bf91baSVlad Zolotarov wmb(); 657094bf91baSVlad Zolotarov 6571e9831909SEric Dumazet netdev_tx_sent_queue(txq, skb->len); 6572e9831909SEric Dumazet 6573adfc5217SJeff Kirsher prod = NEXT_TX_BD(prod); 6574adfc5217SJeff Kirsher txr->tx_prod_bseq += skb->len; 6575adfc5217SJeff Kirsher 6576adfc5217SJeff Kirsher REG_WR16(bp, txr->tx_bidx_addr, prod); 6577adfc5217SJeff Kirsher REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); 6578adfc5217SJeff Kirsher 6579adfc5217SJeff Kirsher mmiowb(); 6580adfc5217SJeff Kirsher 6581adfc5217SJeff Kirsher txr->tx_prod = prod; 6582adfc5217SJeff Kirsher 6583adfc5217SJeff Kirsher if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) { 6584adfc5217SJeff Kirsher netif_tx_stop_queue(txq); 6585adfc5217SJeff Kirsher 6586adfc5217SJeff Kirsher /* netif_tx_stop_queue() must be done before checking 6587adfc5217SJeff Kirsher * tx index in bnx2_tx_avail() below, because in 6588adfc5217SJeff Kirsher * bnx2_tx_int(), we update tx index before checking for 6589adfc5217SJeff Kirsher * netif_tx_queue_stopped(). 6590adfc5217SJeff Kirsher */ 6591adfc5217SJeff Kirsher smp_mb(); 6592adfc5217SJeff Kirsher if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh) 6593adfc5217SJeff Kirsher netif_tx_wake_queue(txq); 6594adfc5217SJeff Kirsher } 6595adfc5217SJeff Kirsher 6596adfc5217SJeff Kirsher return NETDEV_TX_OK; 6597adfc5217SJeff Kirsher dma_error: 6598adfc5217SJeff Kirsher /* save value of frag that failed */ 6599adfc5217SJeff Kirsher last_frag = i; 6600adfc5217SJeff Kirsher 6601adfc5217SJeff Kirsher /* start back at beginning and unmap skb */ 6602adfc5217SJeff Kirsher prod = txr->tx_prod; 6603adfc5217SJeff Kirsher ring_prod = TX_RING_IDX(prod); 6604adfc5217SJeff Kirsher tx_buf = &txr->tx_buf_ring[ring_prod]; 6605adfc5217SJeff Kirsher tx_buf->skb = NULL; 6606adfc5217SJeff Kirsher dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), 6607adfc5217SJeff Kirsher skb_headlen(skb), PCI_DMA_TODEVICE); 6608adfc5217SJeff Kirsher 6609adfc5217SJeff Kirsher /* unmap remaining mapped pages */ 6610adfc5217SJeff Kirsher for (i = 0; i < last_frag; i++) { 6611adfc5217SJeff Kirsher prod = NEXT_TX_BD(prod); 6612adfc5217SJeff Kirsher ring_prod = TX_RING_IDX(prod); 6613adfc5217SJeff Kirsher tx_buf = &txr->tx_buf_ring[ring_prod]; 6614adfc5217SJeff Kirsher dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), 66159e903e08SEric Dumazet skb_frag_size(&skb_shinfo(skb)->frags[i]), 6616adfc5217SJeff Kirsher PCI_DMA_TODEVICE); 6617adfc5217SJeff Kirsher } 6618adfc5217SJeff Kirsher 6619adfc5217SJeff Kirsher dev_kfree_skb(skb); 6620adfc5217SJeff Kirsher return NETDEV_TX_OK; 6621adfc5217SJeff Kirsher } 6622adfc5217SJeff Kirsher 6623adfc5217SJeff Kirsher /* Called with rtnl_lock */ 6624adfc5217SJeff Kirsher static int 6625adfc5217SJeff Kirsher bnx2_close(struct net_device *dev) 6626adfc5217SJeff Kirsher { 6627adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6628adfc5217SJeff Kirsher 6629adfc5217SJeff Kirsher bnx2_disable_int_sync(bp); 6630adfc5217SJeff Kirsher bnx2_napi_disable(bp); 6631adfc5217SJeff Kirsher del_timer_sync(&bp->timer); 6632adfc5217SJeff Kirsher bnx2_shutdown_chip(bp); 6633adfc5217SJeff Kirsher bnx2_free_irq(bp); 6634adfc5217SJeff Kirsher bnx2_free_skbs(bp); 6635adfc5217SJeff Kirsher bnx2_free_mem(bp); 6636adfc5217SJeff Kirsher bnx2_del_napi(bp); 6637adfc5217SJeff Kirsher bp->link_up = 0; 6638adfc5217SJeff Kirsher netif_carrier_off(bp->dev); 6639adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D3hot); 6640adfc5217SJeff Kirsher return 0; 6641adfc5217SJeff Kirsher } 6642adfc5217SJeff Kirsher 6643adfc5217SJeff Kirsher static void 6644adfc5217SJeff Kirsher bnx2_save_stats(struct bnx2 *bp) 6645adfc5217SJeff Kirsher { 6646adfc5217SJeff Kirsher u32 *hw_stats = (u32 *) bp->stats_blk; 6647adfc5217SJeff Kirsher u32 *temp_stats = (u32 *) bp->temp_stats_blk; 6648adfc5217SJeff Kirsher int i; 6649adfc5217SJeff Kirsher 6650adfc5217SJeff Kirsher /* The 1st 10 counters are 64-bit counters */ 6651adfc5217SJeff Kirsher for (i = 0; i < 20; i += 2) { 6652adfc5217SJeff Kirsher u32 hi; 6653adfc5217SJeff Kirsher u64 lo; 6654adfc5217SJeff Kirsher 6655adfc5217SJeff Kirsher hi = temp_stats[i] + hw_stats[i]; 6656adfc5217SJeff Kirsher lo = (u64) temp_stats[i + 1] + (u64) hw_stats[i + 1]; 6657adfc5217SJeff Kirsher if (lo > 0xffffffff) 6658adfc5217SJeff Kirsher hi++; 6659adfc5217SJeff Kirsher temp_stats[i] = hi; 6660adfc5217SJeff Kirsher temp_stats[i + 1] = lo & 0xffffffff; 6661adfc5217SJeff Kirsher } 6662adfc5217SJeff Kirsher 6663adfc5217SJeff Kirsher for ( ; i < sizeof(struct statistics_block) / 4; i++) 6664adfc5217SJeff Kirsher temp_stats[i] += hw_stats[i]; 6665adfc5217SJeff Kirsher } 6666adfc5217SJeff Kirsher 6667adfc5217SJeff Kirsher #define GET_64BIT_NET_STATS64(ctr) \ 6668adfc5217SJeff Kirsher (((u64) (ctr##_hi) << 32) + (u64) (ctr##_lo)) 6669adfc5217SJeff Kirsher 6670adfc5217SJeff Kirsher #define GET_64BIT_NET_STATS(ctr) \ 6671adfc5217SJeff Kirsher GET_64BIT_NET_STATS64(bp->stats_blk->ctr) + \ 6672adfc5217SJeff Kirsher GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr) 6673adfc5217SJeff Kirsher 6674adfc5217SJeff Kirsher #define GET_32BIT_NET_STATS(ctr) \ 6675adfc5217SJeff Kirsher (unsigned long) (bp->stats_blk->ctr + \ 6676adfc5217SJeff Kirsher bp->temp_stats_blk->ctr) 6677adfc5217SJeff Kirsher 6678adfc5217SJeff Kirsher static struct rtnl_link_stats64 * 6679adfc5217SJeff Kirsher bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) 6680adfc5217SJeff Kirsher { 6681adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6682adfc5217SJeff Kirsher 6683adfc5217SJeff Kirsher if (bp->stats_blk == NULL) 6684adfc5217SJeff Kirsher return net_stats; 6685adfc5217SJeff Kirsher 6686adfc5217SJeff Kirsher net_stats->rx_packets = 6687adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCInUcastPkts) + 6688adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts) + 6689adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCInBroadcastPkts); 6690adfc5217SJeff Kirsher 6691adfc5217SJeff Kirsher net_stats->tx_packets = 6692adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCOutUcastPkts) + 6693adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts) + 6694adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCOutBroadcastPkts); 6695adfc5217SJeff Kirsher 6696adfc5217SJeff Kirsher net_stats->rx_bytes = 6697adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCInOctets); 6698adfc5217SJeff Kirsher 6699adfc5217SJeff Kirsher net_stats->tx_bytes = 6700adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCOutOctets); 6701adfc5217SJeff Kirsher 6702adfc5217SJeff Kirsher net_stats->multicast = 6703adfc5217SJeff Kirsher GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts); 6704adfc5217SJeff Kirsher 6705adfc5217SJeff Kirsher net_stats->collisions = 6706adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_EtherStatsCollisions); 6707adfc5217SJeff Kirsher 6708adfc5217SJeff Kirsher net_stats->rx_length_errors = 6709adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_EtherStatsUndersizePkts) + 6710adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_EtherStatsOverrsizePkts); 6711adfc5217SJeff Kirsher 6712adfc5217SJeff Kirsher net_stats->rx_over_errors = 6713adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + 6714adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_IfInMBUFDiscards); 6715adfc5217SJeff Kirsher 6716adfc5217SJeff Kirsher net_stats->rx_frame_errors = 6717adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_Dot3StatsAlignmentErrors); 6718adfc5217SJeff Kirsher 6719adfc5217SJeff Kirsher net_stats->rx_crc_errors = 6720adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_Dot3StatsFCSErrors); 6721adfc5217SJeff Kirsher 6722adfc5217SJeff Kirsher net_stats->rx_errors = net_stats->rx_length_errors + 6723adfc5217SJeff Kirsher net_stats->rx_over_errors + net_stats->rx_frame_errors + 6724adfc5217SJeff Kirsher net_stats->rx_crc_errors; 6725adfc5217SJeff Kirsher 6726adfc5217SJeff Kirsher net_stats->tx_aborted_errors = 6727adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) + 6728adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions); 6729adfc5217SJeff Kirsher 6730adfc5217SJeff Kirsher if ((CHIP_NUM(bp) == CHIP_NUM_5706) || 6731adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_A0)) 6732adfc5217SJeff Kirsher net_stats->tx_carrier_errors = 0; 6733adfc5217SJeff Kirsher else { 6734adfc5217SJeff Kirsher net_stats->tx_carrier_errors = 6735adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_Dot3StatsCarrierSenseErrors); 6736adfc5217SJeff Kirsher } 6737adfc5217SJeff Kirsher 6738adfc5217SJeff Kirsher net_stats->tx_errors = 6739adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_emac_tx_stat_dot3statsinternalmactransmiterrors) + 6740adfc5217SJeff Kirsher net_stats->tx_aborted_errors + 6741adfc5217SJeff Kirsher net_stats->tx_carrier_errors; 6742adfc5217SJeff Kirsher 6743adfc5217SJeff Kirsher net_stats->rx_missed_errors = 6744adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + 6745adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_IfInMBUFDiscards) + 6746adfc5217SJeff Kirsher GET_32BIT_NET_STATS(stat_FwRxDrop); 6747adfc5217SJeff Kirsher 6748adfc5217SJeff Kirsher return net_stats; 6749adfc5217SJeff Kirsher } 6750adfc5217SJeff Kirsher 6751adfc5217SJeff Kirsher /* All ethtool functions called with rtnl_lock */ 6752adfc5217SJeff Kirsher 6753adfc5217SJeff Kirsher static int 6754adfc5217SJeff Kirsher bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 6755adfc5217SJeff Kirsher { 6756adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6757adfc5217SJeff Kirsher int support_serdes = 0, support_copper = 0; 6758adfc5217SJeff Kirsher 6759adfc5217SJeff Kirsher cmd->supported = SUPPORTED_Autoneg; 6760adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) { 6761adfc5217SJeff Kirsher support_serdes = 1; 6762adfc5217SJeff Kirsher support_copper = 1; 6763adfc5217SJeff Kirsher } else if (bp->phy_port == PORT_FIBRE) 6764adfc5217SJeff Kirsher support_serdes = 1; 6765adfc5217SJeff Kirsher else 6766adfc5217SJeff Kirsher support_copper = 1; 6767adfc5217SJeff Kirsher 6768adfc5217SJeff Kirsher if (support_serdes) { 6769adfc5217SJeff Kirsher cmd->supported |= SUPPORTED_1000baseT_Full | 6770adfc5217SJeff Kirsher SUPPORTED_FIBRE; 6771adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) 6772adfc5217SJeff Kirsher cmd->supported |= SUPPORTED_2500baseX_Full; 6773adfc5217SJeff Kirsher 6774adfc5217SJeff Kirsher } 6775adfc5217SJeff Kirsher if (support_copper) { 6776adfc5217SJeff Kirsher cmd->supported |= SUPPORTED_10baseT_Half | 6777adfc5217SJeff Kirsher SUPPORTED_10baseT_Full | 6778adfc5217SJeff Kirsher SUPPORTED_100baseT_Half | 6779adfc5217SJeff Kirsher SUPPORTED_100baseT_Full | 6780adfc5217SJeff Kirsher SUPPORTED_1000baseT_Full | 6781adfc5217SJeff Kirsher SUPPORTED_TP; 6782adfc5217SJeff Kirsher 6783adfc5217SJeff Kirsher } 6784adfc5217SJeff Kirsher 6785adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 6786adfc5217SJeff Kirsher cmd->port = bp->phy_port; 6787adfc5217SJeff Kirsher cmd->advertising = bp->advertising; 6788adfc5217SJeff Kirsher 6789adfc5217SJeff Kirsher if (bp->autoneg & AUTONEG_SPEED) { 6790adfc5217SJeff Kirsher cmd->autoneg = AUTONEG_ENABLE; 6791adfc5217SJeff Kirsher } else { 6792adfc5217SJeff Kirsher cmd->autoneg = AUTONEG_DISABLE; 6793adfc5217SJeff Kirsher } 6794adfc5217SJeff Kirsher 6795adfc5217SJeff Kirsher if (netif_carrier_ok(dev)) { 6796adfc5217SJeff Kirsher ethtool_cmd_speed_set(cmd, bp->line_speed); 6797adfc5217SJeff Kirsher cmd->duplex = bp->duplex; 6798adfc5217SJeff Kirsher } 6799adfc5217SJeff Kirsher else { 6800adfc5217SJeff Kirsher ethtool_cmd_speed_set(cmd, -1); 6801adfc5217SJeff Kirsher cmd->duplex = -1; 6802adfc5217SJeff Kirsher } 6803adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 6804adfc5217SJeff Kirsher 6805adfc5217SJeff Kirsher cmd->transceiver = XCVR_INTERNAL; 6806adfc5217SJeff Kirsher cmd->phy_address = bp->phy_addr; 6807adfc5217SJeff Kirsher 6808adfc5217SJeff Kirsher return 0; 6809adfc5217SJeff Kirsher } 6810adfc5217SJeff Kirsher 6811adfc5217SJeff Kirsher static int 6812adfc5217SJeff Kirsher bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 6813adfc5217SJeff Kirsher { 6814adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6815adfc5217SJeff Kirsher u8 autoneg = bp->autoneg; 6816adfc5217SJeff Kirsher u8 req_duplex = bp->req_duplex; 6817adfc5217SJeff Kirsher u16 req_line_speed = bp->req_line_speed; 6818adfc5217SJeff Kirsher u32 advertising = bp->advertising; 6819adfc5217SJeff Kirsher int err = -EINVAL; 6820adfc5217SJeff Kirsher 6821adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 6822adfc5217SJeff Kirsher 6823adfc5217SJeff Kirsher if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE) 6824adfc5217SJeff Kirsher goto err_out_unlock; 6825adfc5217SJeff Kirsher 6826adfc5217SJeff Kirsher if (cmd->port != bp->phy_port && 6827adfc5217SJeff Kirsher !(bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)) 6828adfc5217SJeff Kirsher goto err_out_unlock; 6829adfc5217SJeff Kirsher 6830adfc5217SJeff Kirsher /* If device is down, we can store the settings only if the user 6831adfc5217SJeff Kirsher * is setting the currently active port. 6832adfc5217SJeff Kirsher */ 6833adfc5217SJeff Kirsher if (!netif_running(dev) && cmd->port != bp->phy_port) 6834adfc5217SJeff Kirsher goto err_out_unlock; 6835adfc5217SJeff Kirsher 6836adfc5217SJeff Kirsher if (cmd->autoneg == AUTONEG_ENABLE) { 6837adfc5217SJeff Kirsher autoneg |= AUTONEG_SPEED; 6838adfc5217SJeff Kirsher 6839adfc5217SJeff Kirsher advertising = cmd->advertising; 6840adfc5217SJeff Kirsher if (cmd->port == PORT_TP) { 6841adfc5217SJeff Kirsher advertising &= ETHTOOL_ALL_COPPER_SPEED; 6842adfc5217SJeff Kirsher if (!advertising) 6843adfc5217SJeff Kirsher advertising = ETHTOOL_ALL_COPPER_SPEED; 6844adfc5217SJeff Kirsher } else { 6845adfc5217SJeff Kirsher advertising &= ETHTOOL_ALL_FIBRE_SPEED; 6846adfc5217SJeff Kirsher if (!advertising) 6847adfc5217SJeff Kirsher advertising = ETHTOOL_ALL_FIBRE_SPEED; 6848adfc5217SJeff Kirsher } 6849adfc5217SJeff Kirsher advertising |= ADVERTISED_Autoneg; 6850adfc5217SJeff Kirsher } 6851adfc5217SJeff Kirsher else { 6852adfc5217SJeff Kirsher u32 speed = ethtool_cmd_speed(cmd); 6853adfc5217SJeff Kirsher if (cmd->port == PORT_FIBRE) { 6854adfc5217SJeff Kirsher if ((speed != SPEED_1000 && 6855adfc5217SJeff Kirsher speed != SPEED_2500) || 6856adfc5217SJeff Kirsher (cmd->duplex != DUPLEX_FULL)) 6857adfc5217SJeff Kirsher goto err_out_unlock; 6858adfc5217SJeff Kirsher 6859adfc5217SJeff Kirsher if (speed == SPEED_2500 && 6860adfc5217SJeff Kirsher !(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) 6861adfc5217SJeff Kirsher goto err_out_unlock; 6862adfc5217SJeff Kirsher } else if (speed == SPEED_1000 || speed == SPEED_2500) 6863adfc5217SJeff Kirsher goto err_out_unlock; 6864adfc5217SJeff Kirsher 6865adfc5217SJeff Kirsher autoneg &= ~AUTONEG_SPEED; 6866adfc5217SJeff Kirsher req_line_speed = speed; 6867adfc5217SJeff Kirsher req_duplex = cmd->duplex; 6868adfc5217SJeff Kirsher advertising = 0; 6869adfc5217SJeff Kirsher } 6870adfc5217SJeff Kirsher 6871adfc5217SJeff Kirsher bp->autoneg = autoneg; 6872adfc5217SJeff Kirsher bp->advertising = advertising; 6873adfc5217SJeff Kirsher bp->req_line_speed = req_line_speed; 6874adfc5217SJeff Kirsher bp->req_duplex = req_duplex; 6875adfc5217SJeff Kirsher 6876adfc5217SJeff Kirsher err = 0; 6877adfc5217SJeff Kirsher /* If device is down, the new settings will be picked up when it is 6878adfc5217SJeff Kirsher * brought up. 6879adfc5217SJeff Kirsher */ 6880adfc5217SJeff Kirsher if (netif_running(dev)) 6881adfc5217SJeff Kirsher err = bnx2_setup_phy(bp, cmd->port); 6882adfc5217SJeff Kirsher 6883adfc5217SJeff Kirsher err_out_unlock: 6884adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 6885adfc5217SJeff Kirsher 6886adfc5217SJeff Kirsher return err; 6887adfc5217SJeff Kirsher } 6888adfc5217SJeff Kirsher 6889adfc5217SJeff Kirsher static void 6890adfc5217SJeff Kirsher bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) 6891adfc5217SJeff Kirsher { 6892adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6893adfc5217SJeff Kirsher 689468aad78cSRick Jones strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); 689568aad78cSRick Jones strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); 689668aad78cSRick Jones strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info)); 689768aad78cSRick Jones strlcpy(info->fw_version, bp->fw_version, sizeof(info->fw_version)); 6898adfc5217SJeff Kirsher } 6899adfc5217SJeff Kirsher 6900adfc5217SJeff Kirsher #define BNX2_REGDUMP_LEN (32 * 1024) 6901adfc5217SJeff Kirsher 6902adfc5217SJeff Kirsher static int 6903adfc5217SJeff Kirsher bnx2_get_regs_len(struct net_device *dev) 6904adfc5217SJeff Kirsher { 6905adfc5217SJeff Kirsher return BNX2_REGDUMP_LEN; 6906adfc5217SJeff Kirsher } 6907adfc5217SJeff Kirsher 6908adfc5217SJeff Kirsher static void 6909adfc5217SJeff Kirsher bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p) 6910adfc5217SJeff Kirsher { 6911adfc5217SJeff Kirsher u32 *p = _p, i, offset; 6912adfc5217SJeff Kirsher u8 *orig_p = _p; 6913adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6914adfc5217SJeff Kirsher static const u32 reg_boundaries[] = { 6915adfc5217SJeff Kirsher 0x0000, 0x0098, 0x0400, 0x045c, 6916adfc5217SJeff Kirsher 0x0800, 0x0880, 0x0c00, 0x0c10, 6917adfc5217SJeff Kirsher 0x0c30, 0x0d08, 0x1000, 0x101c, 6918adfc5217SJeff Kirsher 0x1040, 0x1048, 0x1080, 0x10a4, 6919adfc5217SJeff Kirsher 0x1400, 0x1490, 0x1498, 0x14f0, 6920adfc5217SJeff Kirsher 0x1500, 0x155c, 0x1580, 0x15dc, 6921adfc5217SJeff Kirsher 0x1600, 0x1658, 0x1680, 0x16d8, 6922adfc5217SJeff Kirsher 0x1800, 0x1820, 0x1840, 0x1854, 6923adfc5217SJeff Kirsher 0x1880, 0x1894, 0x1900, 0x1984, 6924adfc5217SJeff Kirsher 0x1c00, 0x1c0c, 0x1c40, 0x1c54, 6925adfc5217SJeff Kirsher 0x1c80, 0x1c94, 0x1d00, 0x1d84, 6926adfc5217SJeff Kirsher 0x2000, 0x2030, 0x23c0, 0x2400, 6927adfc5217SJeff Kirsher 0x2800, 0x2820, 0x2830, 0x2850, 6928adfc5217SJeff Kirsher 0x2b40, 0x2c10, 0x2fc0, 0x3058, 6929adfc5217SJeff Kirsher 0x3c00, 0x3c94, 0x4000, 0x4010, 6930adfc5217SJeff Kirsher 0x4080, 0x4090, 0x43c0, 0x4458, 6931adfc5217SJeff Kirsher 0x4c00, 0x4c18, 0x4c40, 0x4c54, 6932adfc5217SJeff Kirsher 0x4fc0, 0x5010, 0x53c0, 0x5444, 6933adfc5217SJeff Kirsher 0x5c00, 0x5c18, 0x5c80, 0x5c90, 6934adfc5217SJeff Kirsher 0x5fc0, 0x6000, 0x6400, 0x6428, 6935adfc5217SJeff Kirsher 0x6800, 0x6848, 0x684c, 0x6860, 6936adfc5217SJeff Kirsher 0x6888, 0x6910, 0x8000 6937adfc5217SJeff Kirsher }; 6938adfc5217SJeff Kirsher 6939adfc5217SJeff Kirsher regs->version = 0; 6940adfc5217SJeff Kirsher 6941adfc5217SJeff Kirsher memset(p, 0, BNX2_REGDUMP_LEN); 6942adfc5217SJeff Kirsher 6943adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 6944adfc5217SJeff Kirsher return; 6945adfc5217SJeff Kirsher 6946adfc5217SJeff Kirsher i = 0; 6947adfc5217SJeff Kirsher offset = reg_boundaries[0]; 6948adfc5217SJeff Kirsher p += offset; 6949adfc5217SJeff Kirsher while (offset < BNX2_REGDUMP_LEN) { 6950adfc5217SJeff Kirsher *p++ = REG_RD(bp, offset); 6951adfc5217SJeff Kirsher offset += 4; 6952adfc5217SJeff Kirsher if (offset == reg_boundaries[i + 1]) { 6953adfc5217SJeff Kirsher offset = reg_boundaries[i + 2]; 6954adfc5217SJeff Kirsher p = (u32 *) (orig_p + offset); 6955adfc5217SJeff Kirsher i += 2; 6956adfc5217SJeff Kirsher } 6957adfc5217SJeff Kirsher } 6958adfc5217SJeff Kirsher } 6959adfc5217SJeff Kirsher 6960adfc5217SJeff Kirsher static void 6961adfc5217SJeff Kirsher bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 6962adfc5217SJeff Kirsher { 6963adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6964adfc5217SJeff Kirsher 6965adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_NO_WOL) { 6966adfc5217SJeff Kirsher wol->supported = 0; 6967adfc5217SJeff Kirsher wol->wolopts = 0; 6968adfc5217SJeff Kirsher } 6969adfc5217SJeff Kirsher else { 6970adfc5217SJeff Kirsher wol->supported = WAKE_MAGIC; 6971adfc5217SJeff Kirsher if (bp->wol) 6972adfc5217SJeff Kirsher wol->wolopts = WAKE_MAGIC; 6973adfc5217SJeff Kirsher else 6974adfc5217SJeff Kirsher wol->wolopts = 0; 6975adfc5217SJeff Kirsher } 6976adfc5217SJeff Kirsher memset(&wol->sopass, 0, sizeof(wol->sopass)); 6977adfc5217SJeff Kirsher } 6978adfc5217SJeff Kirsher 6979adfc5217SJeff Kirsher static int 6980adfc5217SJeff Kirsher bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 6981adfc5217SJeff Kirsher { 6982adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 6983adfc5217SJeff Kirsher 6984adfc5217SJeff Kirsher if (wol->wolopts & ~WAKE_MAGIC) 6985adfc5217SJeff Kirsher return -EINVAL; 6986adfc5217SJeff Kirsher 6987adfc5217SJeff Kirsher if (wol->wolopts & WAKE_MAGIC) { 6988adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_NO_WOL) 6989adfc5217SJeff Kirsher return -EINVAL; 6990adfc5217SJeff Kirsher 6991adfc5217SJeff Kirsher bp->wol = 1; 6992adfc5217SJeff Kirsher } 6993adfc5217SJeff Kirsher else { 6994adfc5217SJeff Kirsher bp->wol = 0; 6995adfc5217SJeff Kirsher } 6996adfc5217SJeff Kirsher return 0; 6997adfc5217SJeff Kirsher } 6998adfc5217SJeff Kirsher 6999adfc5217SJeff Kirsher static int 7000adfc5217SJeff Kirsher bnx2_nway_reset(struct net_device *dev) 7001adfc5217SJeff Kirsher { 7002adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7003adfc5217SJeff Kirsher u32 bmcr; 7004adfc5217SJeff Kirsher 7005adfc5217SJeff Kirsher if (!netif_running(dev)) 7006adfc5217SJeff Kirsher return -EAGAIN; 7007adfc5217SJeff Kirsher 7008adfc5217SJeff Kirsher if (!(bp->autoneg & AUTONEG_SPEED)) { 7009adfc5217SJeff Kirsher return -EINVAL; 7010adfc5217SJeff Kirsher } 7011adfc5217SJeff Kirsher 7012adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 7013adfc5217SJeff Kirsher 7014adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) { 7015adfc5217SJeff Kirsher int rc; 7016adfc5217SJeff Kirsher 7017adfc5217SJeff Kirsher rc = bnx2_setup_remote_phy(bp, bp->phy_port); 7018adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7019adfc5217SJeff Kirsher return rc; 7020adfc5217SJeff Kirsher } 7021adfc5217SJeff Kirsher 7022adfc5217SJeff Kirsher /* Force a link down visible on the other side */ 7023adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 7024adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); 7025adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7026adfc5217SJeff Kirsher 7027adfc5217SJeff Kirsher msleep(20); 7028adfc5217SJeff Kirsher 7029adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 7030adfc5217SJeff Kirsher 7031adfc5217SJeff Kirsher bp->current_interval = BNX2_SERDES_AN_TIMEOUT; 7032adfc5217SJeff Kirsher bp->serdes_an_pending = 1; 7033adfc5217SJeff Kirsher mod_timer(&bp->timer, jiffies + bp->current_interval); 7034adfc5217SJeff Kirsher } 7035adfc5217SJeff Kirsher 7036adfc5217SJeff Kirsher bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); 7037adfc5217SJeff Kirsher bmcr &= ~BMCR_LOOPBACK; 7038adfc5217SJeff Kirsher bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); 7039adfc5217SJeff Kirsher 7040adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7041adfc5217SJeff Kirsher 7042adfc5217SJeff Kirsher return 0; 7043adfc5217SJeff Kirsher } 7044adfc5217SJeff Kirsher 7045adfc5217SJeff Kirsher static u32 7046adfc5217SJeff Kirsher bnx2_get_link(struct net_device *dev) 7047adfc5217SJeff Kirsher { 7048adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7049adfc5217SJeff Kirsher 7050adfc5217SJeff Kirsher return bp->link_up; 7051adfc5217SJeff Kirsher } 7052adfc5217SJeff Kirsher 7053adfc5217SJeff Kirsher static int 7054adfc5217SJeff Kirsher bnx2_get_eeprom_len(struct net_device *dev) 7055adfc5217SJeff Kirsher { 7056adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7057adfc5217SJeff Kirsher 7058adfc5217SJeff Kirsher if (bp->flash_info == NULL) 7059adfc5217SJeff Kirsher return 0; 7060adfc5217SJeff Kirsher 7061adfc5217SJeff Kirsher return (int) bp->flash_size; 7062adfc5217SJeff Kirsher } 7063adfc5217SJeff Kirsher 7064adfc5217SJeff Kirsher static int 7065adfc5217SJeff Kirsher bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 7066adfc5217SJeff Kirsher u8 *eebuf) 7067adfc5217SJeff Kirsher { 7068adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7069adfc5217SJeff Kirsher int rc; 7070adfc5217SJeff Kirsher 7071adfc5217SJeff Kirsher if (!netif_running(dev)) 7072adfc5217SJeff Kirsher return -EAGAIN; 7073adfc5217SJeff Kirsher 7074adfc5217SJeff Kirsher /* parameters already validated in ethtool_get_eeprom */ 7075adfc5217SJeff Kirsher 7076adfc5217SJeff Kirsher rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); 7077adfc5217SJeff Kirsher 7078adfc5217SJeff Kirsher return rc; 7079adfc5217SJeff Kirsher } 7080adfc5217SJeff Kirsher 7081adfc5217SJeff Kirsher static int 7082adfc5217SJeff Kirsher bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 7083adfc5217SJeff Kirsher u8 *eebuf) 7084adfc5217SJeff Kirsher { 7085adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7086adfc5217SJeff Kirsher int rc; 7087adfc5217SJeff Kirsher 7088adfc5217SJeff Kirsher if (!netif_running(dev)) 7089adfc5217SJeff Kirsher return -EAGAIN; 7090adfc5217SJeff Kirsher 7091adfc5217SJeff Kirsher /* parameters already validated in ethtool_set_eeprom */ 7092adfc5217SJeff Kirsher 7093adfc5217SJeff Kirsher rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); 7094adfc5217SJeff Kirsher 7095adfc5217SJeff Kirsher return rc; 7096adfc5217SJeff Kirsher } 7097adfc5217SJeff Kirsher 7098adfc5217SJeff Kirsher static int 7099adfc5217SJeff Kirsher bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) 7100adfc5217SJeff Kirsher { 7101adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7102adfc5217SJeff Kirsher 7103adfc5217SJeff Kirsher memset(coal, 0, sizeof(struct ethtool_coalesce)); 7104adfc5217SJeff Kirsher 7105adfc5217SJeff Kirsher coal->rx_coalesce_usecs = bp->rx_ticks; 7106adfc5217SJeff Kirsher coal->rx_max_coalesced_frames = bp->rx_quick_cons_trip; 7107adfc5217SJeff Kirsher coal->rx_coalesce_usecs_irq = bp->rx_ticks_int; 7108adfc5217SJeff Kirsher coal->rx_max_coalesced_frames_irq = bp->rx_quick_cons_trip_int; 7109adfc5217SJeff Kirsher 7110adfc5217SJeff Kirsher coal->tx_coalesce_usecs = bp->tx_ticks; 7111adfc5217SJeff Kirsher coal->tx_max_coalesced_frames = bp->tx_quick_cons_trip; 7112adfc5217SJeff Kirsher coal->tx_coalesce_usecs_irq = bp->tx_ticks_int; 7113adfc5217SJeff Kirsher coal->tx_max_coalesced_frames_irq = bp->tx_quick_cons_trip_int; 7114adfc5217SJeff Kirsher 7115adfc5217SJeff Kirsher coal->stats_block_coalesce_usecs = bp->stats_ticks; 7116adfc5217SJeff Kirsher 7117adfc5217SJeff Kirsher return 0; 7118adfc5217SJeff Kirsher } 7119adfc5217SJeff Kirsher 7120adfc5217SJeff Kirsher static int 7121adfc5217SJeff Kirsher bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) 7122adfc5217SJeff Kirsher { 7123adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7124adfc5217SJeff Kirsher 7125adfc5217SJeff Kirsher bp->rx_ticks = (u16) coal->rx_coalesce_usecs; 7126adfc5217SJeff Kirsher if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff; 7127adfc5217SJeff Kirsher 7128adfc5217SJeff Kirsher bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames; 7129adfc5217SJeff Kirsher if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff; 7130adfc5217SJeff Kirsher 7131adfc5217SJeff Kirsher bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq; 7132adfc5217SJeff Kirsher if (bp->rx_ticks_int > 0x3ff) bp->rx_ticks_int = 0x3ff; 7133adfc5217SJeff Kirsher 7134adfc5217SJeff Kirsher bp->rx_quick_cons_trip_int = (u16) coal->rx_max_coalesced_frames_irq; 7135adfc5217SJeff Kirsher if (bp->rx_quick_cons_trip_int > 0xff) 7136adfc5217SJeff Kirsher bp->rx_quick_cons_trip_int = 0xff; 7137adfc5217SJeff Kirsher 7138adfc5217SJeff Kirsher bp->tx_ticks = (u16) coal->tx_coalesce_usecs; 7139adfc5217SJeff Kirsher if (bp->tx_ticks > 0x3ff) bp->tx_ticks = 0x3ff; 7140adfc5217SJeff Kirsher 7141adfc5217SJeff Kirsher bp->tx_quick_cons_trip = (u16) coal->tx_max_coalesced_frames; 7142adfc5217SJeff Kirsher if (bp->tx_quick_cons_trip > 0xff) bp->tx_quick_cons_trip = 0xff; 7143adfc5217SJeff Kirsher 7144adfc5217SJeff Kirsher bp->tx_ticks_int = (u16) coal->tx_coalesce_usecs_irq; 7145adfc5217SJeff Kirsher if (bp->tx_ticks_int > 0x3ff) bp->tx_ticks_int = 0x3ff; 7146adfc5217SJeff Kirsher 7147adfc5217SJeff Kirsher bp->tx_quick_cons_trip_int = (u16) coal->tx_max_coalesced_frames_irq; 7148adfc5217SJeff Kirsher if (bp->tx_quick_cons_trip_int > 0xff) bp->tx_quick_cons_trip_int = 7149adfc5217SJeff Kirsher 0xff; 7150adfc5217SJeff Kirsher 7151adfc5217SJeff Kirsher bp->stats_ticks = coal->stats_block_coalesce_usecs; 7152adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_BROKEN_STATS) { 7153adfc5217SJeff Kirsher if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC) 7154adfc5217SJeff Kirsher bp->stats_ticks = USEC_PER_SEC; 7155adfc5217SJeff Kirsher } 7156adfc5217SJeff Kirsher if (bp->stats_ticks > BNX2_HC_STATS_TICKS_HC_STAT_TICKS) 7157adfc5217SJeff Kirsher bp->stats_ticks = BNX2_HC_STATS_TICKS_HC_STAT_TICKS; 7158adfc5217SJeff Kirsher bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS; 7159adfc5217SJeff Kirsher 7160adfc5217SJeff Kirsher if (netif_running(bp->dev)) { 7161adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 7162adfc5217SJeff Kirsher bnx2_init_nic(bp, 0); 7163adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 7164adfc5217SJeff Kirsher } 7165adfc5217SJeff Kirsher 7166adfc5217SJeff Kirsher return 0; 7167adfc5217SJeff Kirsher } 7168adfc5217SJeff Kirsher 7169adfc5217SJeff Kirsher static void 7170adfc5217SJeff Kirsher bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) 7171adfc5217SJeff Kirsher { 7172adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7173adfc5217SJeff Kirsher 7174adfc5217SJeff Kirsher ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT; 7175adfc5217SJeff Kirsher ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT; 7176adfc5217SJeff Kirsher 7177adfc5217SJeff Kirsher ering->rx_pending = bp->rx_ring_size; 7178adfc5217SJeff Kirsher ering->rx_jumbo_pending = bp->rx_pg_ring_size; 7179adfc5217SJeff Kirsher 7180adfc5217SJeff Kirsher ering->tx_max_pending = MAX_TX_DESC_CNT; 7181adfc5217SJeff Kirsher ering->tx_pending = bp->tx_ring_size; 7182adfc5217SJeff Kirsher } 7183adfc5217SJeff Kirsher 7184adfc5217SJeff Kirsher static int 7185b033281fSMichael Chan bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq) 7186adfc5217SJeff Kirsher { 7187adfc5217SJeff Kirsher if (netif_running(bp->dev)) { 7188adfc5217SJeff Kirsher /* Reset will erase chipset stats; save them */ 7189adfc5217SJeff Kirsher bnx2_save_stats(bp); 7190adfc5217SJeff Kirsher 7191adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 7192adfc5217SJeff Kirsher bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); 7193b033281fSMichael Chan if (reset_irq) { 7194b033281fSMichael Chan bnx2_free_irq(bp); 7195b033281fSMichael Chan bnx2_del_napi(bp); 7196b033281fSMichael Chan } else { 7197adfc5217SJeff Kirsher __bnx2_free_irq(bp); 7198b033281fSMichael Chan } 7199adfc5217SJeff Kirsher bnx2_free_skbs(bp); 7200adfc5217SJeff Kirsher bnx2_free_mem(bp); 7201adfc5217SJeff Kirsher } 7202adfc5217SJeff Kirsher 7203adfc5217SJeff Kirsher bnx2_set_rx_ring_size(bp, rx); 7204adfc5217SJeff Kirsher bp->tx_ring_size = tx; 7205adfc5217SJeff Kirsher 7206adfc5217SJeff Kirsher if (netif_running(bp->dev)) { 7207b033281fSMichael Chan int rc = 0; 7208adfc5217SJeff Kirsher 7209b033281fSMichael Chan if (reset_irq) { 7210b033281fSMichael Chan rc = bnx2_setup_int_mode(bp, disable_msi); 7211b033281fSMichael Chan bnx2_init_napi(bp); 7212b033281fSMichael Chan } 7213b033281fSMichael Chan 7214b033281fSMichael Chan if (!rc) 7215adfc5217SJeff Kirsher rc = bnx2_alloc_mem(bp); 7216b033281fSMichael Chan 7217adfc5217SJeff Kirsher if (!rc) 7218adfc5217SJeff Kirsher rc = bnx2_request_irq(bp); 7219adfc5217SJeff Kirsher 7220adfc5217SJeff Kirsher if (!rc) 7221adfc5217SJeff Kirsher rc = bnx2_init_nic(bp, 0); 7222adfc5217SJeff Kirsher 7223adfc5217SJeff Kirsher if (rc) { 7224adfc5217SJeff Kirsher bnx2_napi_enable(bp); 7225adfc5217SJeff Kirsher dev_close(bp->dev); 7226adfc5217SJeff Kirsher return rc; 7227adfc5217SJeff Kirsher } 7228adfc5217SJeff Kirsher #ifdef BCM_CNIC 7229adfc5217SJeff Kirsher mutex_lock(&bp->cnic_lock); 7230adfc5217SJeff Kirsher /* Let cnic know about the new status block. */ 7231adfc5217SJeff Kirsher if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) 7232adfc5217SJeff Kirsher bnx2_setup_cnic_irq_info(bp); 7233adfc5217SJeff Kirsher mutex_unlock(&bp->cnic_lock); 7234adfc5217SJeff Kirsher #endif 7235adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 7236adfc5217SJeff Kirsher } 7237adfc5217SJeff Kirsher return 0; 7238adfc5217SJeff Kirsher } 7239adfc5217SJeff Kirsher 7240adfc5217SJeff Kirsher static int 7241adfc5217SJeff Kirsher bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) 7242adfc5217SJeff Kirsher { 7243adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7244adfc5217SJeff Kirsher int rc; 7245adfc5217SJeff Kirsher 7246adfc5217SJeff Kirsher if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) || 7247adfc5217SJeff Kirsher (ering->tx_pending > MAX_TX_DESC_CNT) || 7248adfc5217SJeff Kirsher (ering->tx_pending <= MAX_SKB_FRAGS)) { 7249adfc5217SJeff Kirsher 7250adfc5217SJeff Kirsher return -EINVAL; 7251adfc5217SJeff Kirsher } 7252b033281fSMichael Chan rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending, 7253b033281fSMichael Chan false); 7254adfc5217SJeff Kirsher return rc; 7255adfc5217SJeff Kirsher } 7256adfc5217SJeff Kirsher 7257adfc5217SJeff Kirsher static void 7258adfc5217SJeff Kirsher bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) 7259adfc5217SJeff Kirsher { 7260adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7261adfc5217SJeff Kirsher 7262adfc5217SJeff Kirsher epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0); 7263adfc5217SJeff Kirsher epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0); 7264adfc5217SJeff Kirsher epause->tx_pause = ((bp->flow_ctrl & FLOW_CTRL_TX) != 0); 7265adfc5217SJeff Kirsher } 7266adfc5217SJeff Kirsher 7267adfc5217SJeff Kirsher static int 7268adfc5217SJeff Kirsher bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) 7269adfc5217SJeff Kirsher { 7270adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7271adfc5217SJeff Kirsher 7272adfc5217SJeff Kirsher bp->req_flow_ctrl = 0; 7273adfc5217SJeff Kirsher if (epause->rx_pause) 7274adfc5217SJeff Kirsher bp->req_flow_ctrl |= FLOW_CTRL_RX; 7275adfc5217SJeff Kirsher if (epause->tx_pause) 7276adfc5217SJeff Kirsher bp->req_flow_ctrl |= FLOW_CTRL_TX; 7277adfc5217SJeff Kirsher 7278adfc5217SJeff Kirsher if (epause->autoneg) { 7279adfc5217SJeff Kirsher bp->autoneg |= AUTONEG_FLOW_CTRL; 7280adfc5217SJeff Kirsher } 7281adfc5217SJeff Kirsher else { 7282adfc5217SJeff Kirsher bp->autoneg &= ~AUTONEG_FLOW_CTRL; 7283adfc5217SJeff Kirsher } 7284adfc5217SJeff Kirsher 7285adfc5217SJeff Kirsher if (netif_running(dev)) { 7286adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 7287adfc5217SJeff Kirsher bnx2_setup_phy(bp, bp->phy_port); 7288adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7289adfc5217SJeff Kirsher } 7290adfc5217SJeff Kirsher 7291adfc5217SJeff Kirsher return 0; 7292adfc5217SJeff Kirsher } 7293adfc5217SJeff Kirsher 7294adfc5217SJeff Kirsher static struct { 7295adfc5217SJeff Kirsher char string[ETH_GSTRING_LEN]; 7296adfc5217SJeff Kirsher } bnx2_stats_str_arr[] = { 7297adfc5217SJeff Kirsher { "rx_bytes" }, 7298adfc5217SJeff Kirsher { "rx_error_bytes" }, 7299adfc5217SJeff Kirsher { "tx_bytes" }, 7300adfc5217SJeff Kirsher { "tx_error_bytes" }, 7301adfc5217SJeff Kirsher { "rx_ucast_packets" }, 7302adfc5217SJeff Kirsher { "rx_mcast_packets" }, 7303adfc5217SJeff Kirsher { "rx_bcast_packets" }, 7304adfc5217SJeff Kirsher { "tx_ucast_packets" }, 7305adfc5217SJeff Kirsher { "tx_mcast_packets" }, 7306adfc5217SJeff Kirsher { "tx_bcast_packets" }, 7307adfc5217SJeff Kirsher { "tx_mac_errors" }, 7308adfc5217SJeff Kirsher { "tx_carrier_errors" }, 7309adfc5217SJeff Kirsher { "rx_crc_errors" }, 7310adfc5217SJeff Kirsher { "rx_align_errors" }, 7311adfc5217SJeff Kirsher { "tx_single_collisions" }, 7312adfc5217SJeff Kirsher { "tx_multi_collisions" }, 7313adfc5217SJeff Kirsher { "tx_deferred" }, 7314adfc5217SJeff Kirsher { "tx_excess_collisions" }, 7315adfc5217SJeff Kirsher { "tx_late_collisions" }, 7316adfc5217SJeff Kirsher { "tx_total_collisions" }, 7317adfc5217SJeff Kirsher { "rx_fragments" }, 7318adfc5217SJeff Kirsher { "rx_jabbers" }, 7319adfc5217SJeff Kirsher { "rx_undersize_packets" }, 7320adfc5217SJeff Kirsher { "rx_oversize_packets" }, 7321adfc5217SJeff Kirsher { "rx_64_byte_packets" }, 7322adfc5217SJeff Kirsher { "rx_65_to_127_byte_packets" }, 7323adfc5217SJeff Kirsher { "rx_128_to_255_byte_packets" }, 7324adfc5217SJeff Kirsher { "rx_256_to_511_byte_packets" }, 7325adfc5217SJeff Kirsher { "rx_512_to_1023_byte_packets" }, 7326adfc5217SJeff Kirsher { "rx_1024_to_1522_byte_packets" }, 7327adfc5217SJeff Kirsher { "rx_1523_to_9022_byte_packets" }, 7328adfc5217SJeff Kirsher { "tx_64_byte_packets" }, 7329adfc5217SJeff Kirsher { "tx_65_to_127_byte_packets" }, 7330adfc5217SJeff Kirsher { "tx_128_to_255_byte_packets" }, 7331adfc5217SJeff Kirsher { "tx_256_to_511_byte_packets" }, 7332adfc5217SJeff Kirsher { "tx_512_to_1023_byte_packets" }, 7333adfc5217SJeff Kirsher { "tx_1024_to_1522_byte_packets" }, 7334adfc5217SJeff Kirsher { "tx_1523_to_9022_byte_packets" }, 7335adfc5217SJeff Kirsher { "rx_xon_frames" }, 7336adfc5217SJeff Kirsher { "rx_xoff_frames" }, 7337adfc5217SJeff Kirsher { "tx_xon_frames" }, 7338adfc5217SJeff Kirsher { "tx_xoff_frames" }, 7339adfc5217SJeff Kirsher { "rx_mac_ctrl_frames" }, 7340adfc5217SJeff Kirsher { "rx_filtered_packets" }, 7341adfc5217SJeff Kirsher { "rx_ftq_discards" }, 7342adfc5217SJeff Kirsher { "rx_discards" }, 7343adfc5217SJeff Kirsher { "rx_fw_discards" }, 7344adfc5217SJeff Kirsher }; 7345adfc5217SJeff Kirsher 7346adfc5217SJeff Kirsher #define BNX2_NUM_STATS (sizeof(bnx2_stats_str_arr)/\ 7347adfc5217SJeff Kirsher sizeof(bnx2_stats_str_arr[0])) 7348adfc5217SJeff Kirsher 7349adfc5217SJeff Kirsher #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4) 7350adfc5217SJeff Kirsher 7351adfc5217SJeff Kirsher static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = { 7352adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCInOctets_hi), 7353adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCInBadOctets_hi), 7354adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCOutOctets_hi), 7355adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCOutBadOctets_hi), 7356adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCInUcastPkts_hi), 7357adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCInMulticastPkts_hi), 7358adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCInBroadcastPkts_hi), 7359adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCOutUcastPkts_hi), 7360adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi), 7361adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi), 7362adfc5217SJeff Kirsher STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors), 7363adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), 7364adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsFCSErrors), 7365adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsAlignmentErrors), 7366adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames), 7367adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames), 7368adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), 7369adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions), 7370adfc5217SJeff Kirsher STATS_OFFSET32(stat_Dot3StatsLateCollisions), 7371adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsCollisions), 7372adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsFragments), 7373adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsJabbers), 7374adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsUndersizePkts), 7375adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsOverrsizePkts), 7376adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx64Octets), 7377adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets), 7378adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets), 7379adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets), 7380adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets), 7381adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets), 7382adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets), 7383adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx64Octets), 7384adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets), 7385adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets), 7386adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets), 7387adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets), 7388adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets), 7389adfc5217SJeff Kirsher STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets), 7390adfc5217SJeff Kirsher STATS_OFFSET32(stat_XonPauseFramesReceived), 7391adfc5217SJeff Kirsher STATS_OFFSET32(stat_XoffPauseFramesReceived), 7392adfc5217SJeff Kirsher STATS_OFFSET32(stat_OutXonSent), 7393adfc5217SJeff Kirsher STATS_OFFSET32(stat_OutXoffSent), 7394adfc5217SJeff Kirsher STATS_OFFSET32(stat_MacControlFramesReceived), 7395adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfInFramesL2FilterDiscards), 7396adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfInFTQDiscards), 7397adfc5217SJeff Kirsher STATS_OFFSET32(stat_IfInMBUFDiscards), 7398adfc5217SJeff Kirsher STATS_OFFSET32(stat_FwRxDrop), 7399adfc5217SJeff Kirsher }; 7400adfc5217SJeff Kirsher 7401adfc5217SJeff Kirsher /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are 7402adfc5217SJeff Kirsher * skipped because of errata. 7403adfc5217SJeff Kirsher */ 7404adfc5217SJeff Kirsher static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { 7405adfc5217SJeff Kirsher 8,0,8,8,8,8,8,8,8,8, 7406adfc5217SJeff Kirsher 4,0,4,4,4,4,4,4,4,4, 7407adfc5217SJeff Kirsher 4,4,4,4,4,4,4,4,4,4, 7408adfc5217SJeff Kirsher 4,4,4,4,4,4,4,4,4,4, 7409adfc5217SJeff Kirsher 4,4,4,4,4,4,4, 7410adfc5217SJeff Kirsher }; 7411adfc5217SJeff Kirsher 7412adfc5217SJeff Kirsher static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = { 7413adfc5217SJeff Kirsher 8,0,8,8,8,8,8,8,8,8, 7414adfc5217SJeff Kirsher 4,4,4,4,4,4,4,4,4,4, 7415adfc5217SJeff Kirsher 4,4,4,4,4,4,4,4,4,4, 7416adfc5217SJeff Kirsher 4,4,4,4,4,4,4,4,4,4, 7417adfc5217SJeff Kirsher 4,4,4,4,4,4,4, 7418adfc5217SJeff Kirsher }; 7419adfc5217SJeff Kirsher 7420adfc5217SJeff Kirsher #define BNX2_NUM_TESTS 6 7421adfc5217SJeff Kirsher 7422adfc5217SJeff Kirsher static struct { 7423adfc5217SJeff Kirsher char string[ETH_GSTRING_LEN]; 7424adfc5217SJeff Kirsher } bnx2_tests_str_arr[BNX2_NUM_TESTS] = { 7425adfc5217SJeff Kirsher { "register_test (offline)" }, 7426adfc5217SJeff Kirsher { "memory_test (offline)" }, 7427adfc5217SJeff Kirsher { "loopback_test (offline)" }, 7428adfc5217SJeff Kirsher { "nvram_test (online)" }, 7429adfc5217SJeff Kirsher { "interrupt_test (online)" }, 7430adfc5217SJeff Kirsher { "link_test (online)" }, 7431adfc5217SJeff Kirsher }; 7432adfc5217SJeff Kirsher 7433adfc5217SJeff Kirsher static int 7434adfc5217SJeff Kirsher bnx2_get_sset_count(struct net_device *dev, int sset) 7435adfc5217SJeff Kirsher { 7436adfc5217SJeff Kirsher switch (sset) { 7437adfc5217SJeff Kirsher case ETH_SS_TEST: 7438adfc5217SJeff Kirsher return BNX2_NUM_TESTS; 7439adfc5217SJeff Kirsher case ETH_SS_STATS: 7440adfc5217SJeff Kirsher return BNX2_NUM_STATS; 7441adfc5217SJeff Kirsher default: 7442adfc5217SJeff Kirsher return -EOPNOTSUPP; 7443adfc5217SJeff Kirsher } 7444adfc5217SJeff Kirsher } 7445adfc5217SJeff Kirsher 7446adfc5217SJeff Kirsher static void 7447adfc5217SJeff Kirsher bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) 7448adfc5217SJeff Kirsher { 7449adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7450adfc5217SJeff Kirsher 7451adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 7452adfc5217SJeff Kirsher 7453adfc5217SJeff Kirsher memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); 7454adfc5217SJeff Kirsher if (etest->flags & ETH_TEST_FL_OFFLINE) { 7455adfc5217SJeff Kirsher int i; 7456adfc5217SJeff Kirsher 7457adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 7458adfc5217SJeff Kirsher bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); 7459adfc5217SJeff Kirsher bnx2_free_skbs(bp); 7460adfc5217SJeff Kirsher 7461adfc5217SJeff Kirsher if (bnx2_test_registers(bp) != 0) { 7462adfc5217SJeff Kirsher buf[0] = 1; 7463adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7464adfc5217SJeff Kirsher } 7465adfc5217SJeff Kirsher if (bnx2_test_memory(bp) != 0) { 7466adfc5217SJeff Kirsher buf[1] = 1; 7467adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7468adfc5217SJeff Kirsher } 7469adfc5217SJeff Kirsher if ((buf[2] = bnx2_test_loopback(bp)) != 0) 7470adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7471adfc5217SJeff Kirsher 7472adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 7473adfc5217SJeff Kirsher bnx2_shutdown_chip(bp); 7474adfc5217SJeff Kirsher else { 7475adfc5217SJeff Kirsher bnx2_init_nic(bp, 1); 7476adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 7477adfc5217SJeff Kirsher } 7478adfc5217SJeff Kirsher 7479adfc5217SJeff Kirsher /* wait for link up */ 7480adfc5217SJeff Kirsher for (i = 0; i < 7; i++) { 7481adfc5217SJeff Kirsher if (bp->link_up) 7482adfc5217SJeff Kirsher break; 7483adfc5217SJeff Kirsher msleep_interruptible(1000); 7484adfc5217SJeff Kirsher } 7485adfc5217SJeff Kirsher } 7486adfc5217SJeff Kirsher 7487adfc5217SJeff Kirsher if (bnx2_test_nvram(bp) != 0) { 7488adfc5217SJeff Kirsher buf[3] = 1; 7489adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7490adfc5217SJeff Kirsher } 7491adfc5217SJeff Kirsher if (bnx2_test_intr(bp) != 0) { 7492adfc5217SJeff Kirsher buf[4] = 1; 7493adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7494adfc5217SJeff Kirsher } 7495adfc5217SJeff Kirsher 7496adfc5217SJeff Kirsher if (bnx2_test_link(bp) != 0) { 7497adfc5217SJeff Kirsher buf[5] = 1; 7498adfc5217SJeff Kirsher etest->flags |= ETH_TEST_FL_FAILED; 7499adfc5217SJeff Kirsher 7500adfc5217SJeff Kirsher } 7501adfc5217SJeff Kirsher if (!netif_running(bp->dev)) 7502adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D3hot); 7503adfc5217SJeff Kirsher } 7504adfc5217SJeff Kirsher 7505adfc5217SJeff Kirsher static void 7506adfc5217SJeff Kirsher bnx2_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 7507adfc5217SJeff Kirsher { 7508adfc5217SJeff Kirsher switch (stringset) { 7509adfc5217SJeff Kirsher case ETH_SS_STATS: 7510adfc5217SJeff Kirsher memcpy(buf, bnx2_stats_str_arr, 7511adfc5217SJeff Kirsher sizeof(bnx2_stats_str_arr)); 7512adfc5217SJeff Kirsher break; 7513adfc5217SJeff Kirsher case ETH_SS_TEST: 7514adfc5217SJeff Kirsher memcpy(buf, bnx2_tests_str_arr, 7515adfc5217SJeff Kirsher sizeof(bnx2_tests_str_arr)); 7516adfc5217SJeff Kirsher break; 7517adfc5217SJeff Kirsher } 7518adfc5217SJeff Kirsher } 7519adfc5217SJeff Kirsher 7520adfc5217SJeff Kirsher static void 7521adfc5217SJeff Kirsher bnx2_get_ethtool_stats(struct net_device *dev, 7522adfc5217SJeff Kirsher struct ethtool_stats *stats, u64 *buf) 7523adfc5217SJeff Kirsher { 7524adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7525adfc5217SJeff Kirsher int i; 7526adfc5217SJeff Kirsher u32 *hw_stats = (u32 *) bp->stats_blk; 7527adfc5217SJeff Kirsher u32 *temp_stats = (u32 *) bp->temp_stats_blk; 7528adfc5217SJeff Kirsher u8 *stats_len_arr = NULL; 7529adfc5217SJeff Kirsher 7530adfc5217SJeff Kirsher if (hw_stats == NULL) { 7531adfc5217SJeff Kirsher memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS); 7532adfc5217SJeff Kirsher return; 7533adfc5217SJeff Kirsher } 7534adfc5217SJeff Kirsher 7535adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || 7536adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5706_A1) || 7537adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5706_A2) || 7538adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_A0)) 7539adfc5217SJeff Kirsher stats_len_arr = bnx2_5706_stats_len_arr; 7540adfc5217SJeff Kirsher else 7541adfc5217SJeff Kirsher stats_len_arr = bnx2_5708_stats_len_arr; 7542adfc5217SJeff Kirsher 7543adfc5217SJeff Kirsher for (i = 0; i < BNX2_NUM_STATS; i++) { 7544adfc5217SJeff Kirsher unsigned long offset; 7545adfc5217SJeff Kirsher 7546adfc5217SJeff Kirsher if (stats_len_arr[i] == 0) { 7547adfc5217SJeff Kirsher /* skip this counter */ 7548adfc5217SJeff Kirsher buf[i] = 0; 7549adfc5217SJeff Kirsher continue; 7550adfc5217SJeff Kirsher } 7551adfc5217SJeff Kirsher 7552adfc5217SJeff Kirsher offset = bnx2_stats_offset_arr[i]; 7553adfc5217SJeff Kirsher if (stats_len_arr[i] == 4) { 7554adfc5217SJeff Kirsher /* 4-byte counter */ 7555adfc5217SJeff Kirsher buf[i] = (u64) *(hw_stats + offset) + 7556adfc5217SJeff Kirsher *(temp_stats + offset); 7557adfc5217SJeff Kirsher continue; 7558adfc5217SJeff Kirsher } 7559adfc5217SJeff Kirsher /* 8-byte counter */ 7560adfc5217SJeff Kirsher buf[i] = (((u64) *(hw_stats + offset)) << 32) + 7561adfc5217SJeff Kirsher *(hw_stats + offset + 1) + 7562adfc5217SJeff Kirsher (((u64) *(temp_stats + offset)) << 32) + 7563adfc5217SJeff Kirsher *(temp_stats + offset + 1); 7564adfc5217SJeff Kirsher } 7565adfc5217SJeff Kirsher } 7566adfc5217SJeff Kirsher 7567adfc5217SJeff Kirsher static int 7568adfc5217SJeff Kirsher bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) 7569adfc5217SJeff Kirsher { 7570adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7571adfc5217SJeff Kirsher 7572adfc5217SJeff Kirsher switch (state) { 7573adfc5217SJeff Kirsher case ETHTOOL_ID_ACTIVE: 7574adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 7575adfc5217SJeff Kirsher 7576adfc5217SJeff Kirsher bp->leds_save = REG_RD(bp, BNX2_MISC_CFG); 7577adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); 7578adfc5217SJeff Kirsher return 1; /* cycle on/off once per second */ 7579adfc5217SJeff Kirsher 7580adfc5217SJeff Kirsher case ETHTOOL_ID_ON: 7581adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | 7582adfc5217SJeff Kirsher BNX2_EMAC_LED_1000MB_OVERRIDE | 7583adfc5217SJeff Kirsher BNX2_EMAC_LED_100MB_OVERRIDE | 7584adfc5217SJeff Kirsher BNX2_EMAC_LED_10MB_OVERRIDE | 7585adfc5217SJeff Kirsher BNX2_EMAC_LED_TRAFFIC_OVERRIDE | 7586adfc5217SJeff Kirsher BNX2_EMAC_LED_TRAFFIC); 7587adfc5217SJeff Kirsher break; 7588adfc5217SJeff Kirsher 7589adfc5217SJeff Kirsher case ETHTOOL_ID_OFF: 7590adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); 7591adfc5217SJeff Kirsher break; 7592adfc5217SJeff Kirsher 7593adfc5217SJeff Kirsher case ETHTOOL_ID_INACTIVE: 7594adfc5217SJeff Kirsher REG_WR(bp, BNX2_EMAC_LED, 0); 7595adfc5217SJeff Kirsher REG_WR(bp, BNX2_MISC_CFG, bp->leds_save); 7596adfc5217SJeff Kirsher 7597adfc5217SJeff Kirsher if (!netif_running(dev)) 7598adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D3hot); 7599adfc5217SJeff Kirsher break; 7600adfc5217SJeff Kirsher } 7601adfc5217SJeff Kirsher 7602adfc5217SJeff Kirsher return 0; 7603adfc5217SJeff Kirsher } 7604adfc5217SJeff Kirsher 7605c8f44affSMichał Mirosław static netdev_features_t 7606c8f44affSMichał Mirosław bnx2_fix_features(struct net_device *dev, netdev_features_t features) 7607adfc5217SJeff Kirsher { 7608adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7609adfc5217SJeff Kirsher 7610adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) 7611adfc5217SJeff Kirsher features |= NETIF_F_HW_VLAN_RX; 7612adfc5217SJeff Kirsher 7613adfc5217SJeff Kirsher return features; 7614adfc5217SJeff Kirsher } 7615adfc5217SJeff Kirsher 7616adfc5217SJeff Kirsher static int 7617c8f44affSMichał Mirosław bnx2_set_features(struct net_device *dev, netdev_features_t features) 7618adfc5217SJeff Kirsher { 7619adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7620adfc5217SJeff Kirsher 7621adfc5217SJeff Kirsher /* TSO with VLAN tag won't work with current firmware */ 7622adfc5217SJeff Kirsher if (features & NETIF_F_HW_VLAN_TX) 7623adfc5217SJeff Kirsher dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO); 7624adfc5217SJeff Kirsher else 7625adfc5217SJeff Kirsher dev->vlan_features &= ~NETIF_F_ALL_TSO; 7626adfc5217SJeff Kirsher 7627adfc5217SJeff Kirsher if ((!!(features & NETIF_F_HW_VLAN_RX) != 7628adfc5217SJeff Kirsher !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) && 7629adfc5217SJeff Kirsher netif_running(dev)) { 7630adfc5217SJeff Kirsher bnx2_netif_stop(bp, false); 7631adfc5217SJeff Kirsher dev->features = features; 7632adfc5217SJeff Kirsher bnx2_set_rx_mode(dev); 7633adfc5217SJeff Kirsher bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1); 7634adfc5217SJeff Kirsher bnx2_netif_start(bp, false); 7635adfc5217SJeff Kirsher return 1; 7636adfc5217SJeff Kirsher } 7637adfc5217SJeff Kirsher 7638adfc5217SJeff Kirsher return 0; 7639adfc5217SJeff Kirsher } 7640adfc5217SJeff Kirsher 7641b033281fSMichael Chan static void bnx2_get_channels(struct net_device *dev, 7642b033281fSMichael Chan struct ethtool_channels *channels) 7643b033281fSMichael Chan { 7644b033281fSMichael Chan struct bnx2 *bp = netdev_priv(dev); 7645b033281fSMichael Chan u32 max_rx_rings = 1; 7646b033281fSMichael Chan u32 max_tx_rings = 1; 7647b033281fSMichael Chan 7648b033281fSMichael Chan if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { 7649b033281fSMichael Chan max_rx_rings = RX_MAX_RINGS; 7650b033281fSMichael Chan max_tx_rings = TX_MAX_RINGS; 7651b033281fSMichael Chan } 7652b033281fSMichael Chan 7653b033281fSMichael Chan channels->max_rx = max_rx_rings; 7654b033281fSMichael Chan channels->max_tx = max_tx_rings; 7655b033281fSMichael Chan channels->max_other = 0; 7656b033281fSMichael Chan channels->max_combined = 0; 7657b033281fSMichael Chan channels->rx_count = bp->num_rx_rings; 7658b033281fSMichael Chan channels->tx_count = bp->num_tx_rings; 7659b033281fSMichael Chan channels->other_count = 0; 7660b033281fSMichael Chan channels->combined_count = 0; 7661b033281fSMichael Chan } 7662b033281fSMichael Chan 7663b033281fSMichael Chan static int bnx2_set_channels(struct net_device *dev, 7664b033281fSMichael Chan struct ethtool_channels *channels) 7665b033281fSMichael Chan { 7666b033281fSMichael Chan struct bnx2 *bp = netdev_priv(dev); 7667b033281fSMichael Chan u32 max_rx_rings = 1; 7668b033281fSMichael Chan u32 max_tx_rings = 1; 7669b033281fSMichael Chan int rc = 0; 7670b033281fSMichael Chan 7671b033281fSMichael Chan if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { 7672b033281fSMichael Chan max_rx_rings = RX_MAX_RINGS; 7673b033281fSMichael Chan max_tx_rings = TX_MAX_RINGS; 7674b033281fSMichael Chan } 7675b033281fSMichael Chan if (channels->rx_count > max_rx_rings || 7676b033281fSMichael Chan channels->tx_count > max_tx_rings) 7677b033281fSMichael Chan return -EINVAL; 7678b033281fSMichael Chan 7679b033281fSMichael Chan bp->num_req_rx_rings = channels->rx_count; 7680b033281fSMichael Chan bp->num_req_tx_rings = channels->tx_count; 7681b033281fSMichael Chan 7682b033281fSMichael Chan if (netif_running(dev)) 7683b033281fSMichael Chan rc = bnx2_change_ring_size(bp, bp->rx_ring_size, 7684b033281fSMichael Chan bp->tx_ring_size, true); 7685b033281fSMichael Chan 7686b033281fSMichael Chan return rc; 7687b033281fSMichael Chan } 7688b033281fSMichael Chan 7689adfc5217SJeff Kirsher static const struct ethtool_ops bnx2_ethtool_ops = { 7690adfc5217SJeff Kirsher .get_settings = bnx2_get_settings, 7691adfc5217SJeff Kirsher .set_settings = bnx2_set_settings, 7692adfc5217SJeff Kirsher .get_drvinfo = bnx2_get_drvinfo, 7693adfc5217SJeff Kirsher .get_regs_len = bnx2_get_regs_len, 7694adfc5217SJeff Kirsher .get_regs = bnx2_get_regs, 7695adfc5217SJeff Kirsher .get_wol = bnx2_get_wol, 7696adfc5217SJeff Kirsher .set_wol = bnx2_set_wol, 7697adfc5217SJeff Kirsher .nway_reset = bnx2_nway_reset, 7698adfc5217SJeff Kirsher .get_link = bnx2_get_link, 7699adfc5217SJeff Kirsher .get_eeprom_len = bnx2_get_eeprom_len, 7700adfc5217SJeff Kirsher .get_eeprom = bnx2_get_eeprom, 7701adfc5217SJeff Kirsher .set_eeprom = bnx2_set_eeprom, 7702adfc5217SJeff Kirsher .get_coalesce = bnx2_get_coalesce, 7703adfc5217SJeff Kirsher .set_coalesce = bnx2_set_coalesce, 7704adfc5217SJeff Kirsher .get_ringparam = bnx2_get_ringparam, 7705adfc5217SJeff Kirsher .set_ringparam = bnx2_set_ringparam, 7706adfc5217SJeff Kirsher .get_pauseparam = bnx2_get_pauseparam, 7707adfc5217SJeff Kirsher .set_pauseparam = bnx2_set_pauseparam, 7708adfc5217SJeff Kirsher .self_test = bnx2_self_test, 7709adfc5217SJeff Kirsher .get_strings = bnx2_get_strings, 7710adfc5217SJeff Kirsher .set_phys_id = bnx2_set_phys_id, 7711adfc5217SJeff Kirsher .get_ethtool_stats = bnx2_get_ethtool_stats, 7712adfc5217SJeff Kirsher .get_sset_count = bnx2_get_sset_count, 7713b033281fSMichael Chan .get_channels = bnx2_get_channels, 7714b033281fSMichael Chan .set_channels = bnx2_set_channels, 7715adfc5217SJeff Kirsher }; 7716adfc5217SJeff Kirsher 7717adfc5217SJeff Kirsher /* Called with rtnl_lock */ 7718adfc5217SJeff Kirsher static int 7719adfc5217SJeff Kirsher bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 7720adfc5217SJeff Kirsher { 7721adfc5217SJeff Kirsher struct mii_ioctl_data *data = if_mii(ifr); 7722adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7723adfc5217SJeff Kirsher int err; 7724adfc5217SJeff Kirsher 7725adfc5217SJeff Kirsher switch(cmd) { 7726adfc5217SJeff Kirsher case SIOCGMIIPHY: 7727adfc5217SJeff Kirsher data->phy_id = bp->phy_addr; 7728adfc5217SJeff Kirsher 7729adfc5217SJeff Kirsher /* fallthru */ 7730adfc5217SJeff Kirsher case SIOCGMIIREG: { 7731adfc5217SJeff Kirsher u32 mii_regval; 7732adfc5217SJeff Kirsher 7733adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 7734adfc5217SJeff Kirsher return -EOPNOTSUPP; 7735adfc5217SJeff Kirsher 7736adfc5217SJeff Kirsher if (!netif_running(dev)) 7737adfc5217SJeff Kirsher return -EAGAIN; 7738adfc5217SJeff Kirsher 7739adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 7740adfc5217SJeff Kirsher err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval); 7741adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7742adfc5217SJeff Kirsher 7743adfc5217SJeff Kirsher data->val_out = mii_regval; 7744adfc5217SJeff Kirsher 7745adfc5217SJeff Kirsher return err; 7746adfc5217SJeff Kirsher } 7747adfc5217SJeff Kirsher 7748adfc5217SJeff Kirsher case SIOCSMIIREG: 7749adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) 7750adfc5217SJeff Kirsher return -EOPNOTSUPP; 7751adfc5217SJeff Kirsher 7752adfc5217SJeff Kirsher if (!netif_running(dev)) 7753adfc5217SJeff Kirsher return -EAGAIN; 7754adfc5217SJeff Kirsher 7755adfc5217SJeff Kirsher spin_lock_bh(&bp->phy_lock); 7756adfc5217SJeff Kirsher err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in); 7757adfc5217SJeff Kirsher spin_unlock_bh(&bp->phy_lock); 7758adfc5217SJeff Kirsher 7759adfc5217SJeff Kirsher return err; 7760adfc5217SJeff Kirsher 7761adfc5217SJeff Kirsher default: 7762adfc5217SJeff Kirsher /* do nothing */ 7763adfc5217SJeff Kirsher break; 7764adfc5217SJeff Kirsher } 7765adfc5217SJeff Kirsher return -EOPNOTSUPP; 7766adfc5217SJeff Kirsher } 7767adfc5217SJeff Kirsher 7768adfc5217SJeff Kirsher /* Called with rtnl_lock */ 7769adfc5217SJeff Kirsher static int 7770adfc5217SJeff Kirsher bnx2_change_mac_addr(struct net_device *dev, void *p) 7771adfc5217SJeff Kirsher { 7772adfc5217SJeff Kirsher struct sockaddr *addr = p; 7773adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7774adfc5217SJeff Kirsher 7775adfc5217SJeff Kirsher if (!is_valid_ether_addr(addr->sa_data)) 7776504f9b5aSDanny Kukawka return -EADDRNOTAVAIL; 7777adfc5217SJeff Kirsher 7778adfc5217SJeff Kirsher memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 7779adfc5217SJeff Kirsher if (netif_running(dev)) 7780adfc5217SJeff Kirsher bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0); 7781adfc5217SJeff Kirsher 7782adfc5217SJeff Kirsher return 0; 7783adfc5217SJeff Kirsher } 7784adfc5217SJeff Kirsher 7785adfc5217SJeff Kirsher /* Called with rtnl_lock */ 7786adfc5217SJeff Kirsher static int 7787adfc5217SJeff Kirsher bnx2_change_mtu(struct net_device *dev, int new_mtu) 7788adfc5217SJeff Kirsher { 7789adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7790adfc5217SJeff Kirsher 7791adfc5217SJeff Kirsher if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || 7792adfc5217SJeff Kirsher ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE)) 7793adfc5217SJeff Kirsher return -EINVAL; 7794adfc5217SJeff Kirsher 7795adfc5217SJeff Kirsher dev->mtu = new_mtu; 7796b033281fSMichael Chan return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size, 7797b033281fSMichael Chan false); 7798adfc5217SJeff Kirsher } 7799adfc5217SJeff Kirsher 7800adfc5217SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 7801adfc5217SJeff Kirsher static void 7802adfc5217SJeff Kirsher poll_bnx2(struct net_device *dev) 7803adfc5217SJeff Kirsher { 7804adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 7805adfc5217SJeff Kirsher int i; 7806adfc5217SJeff Kirsher 7807adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 7808adfc5217SJeff Kirsher struct bnx2_irq *irq = &bp->irq_tbl[i]; 7809adfc5217SJeff Kirsher 7810adfc5217SJeff Kirsher disable_irq(irq->vector); 7811adfc5217SJeff Kirsher irq->handler(irq->vector, &bp->bnx2_napi[i]); 7812adfc5217SJeff Kirsher enable_irq(irq->vector); 7813adfc5217SJeff Kirsher } 7814adfc5217SJeff Kirsher } 7815adfc5217SJeff Kirsher #endif 7816adfc5217SJeff Kirsher 7817adfc5217SJeff Kirsher static void __devinit 7818adfc5217SJeff Kirsher bnx2_get_5709_media(struct bnx2 *bp) 7819adfc5217SJeff Kirsher { 7820adfc5217SJeff Kirsher u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL); 7821adfc5217SJeff Kirsher u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID; 7822adfc5217SJeff Kirsher u32 strap; 7823adfc5217SJeff Kirsher 7824adfc5217SJeff Kirsher if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C) 7825adfc5217SJeff Kirsher return; 7826adfc5217SJeff Kirsher else if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) { 7827adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_SERDES; 7828adfc5217SJeff Kirsher return; 7829adfc5217SJeff Kirsher } 7830adfc5217SJeff Kirsher 7831adfc5217SJeff Kirsher if (val & BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE) 7832adfc5217SJeff Kirsher strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21; 7833adfc5217SJeff Kirsher else 7834adfc5217SJeff Kirsher strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8; 7835adfc5217SJeff Kirsher 7836adfc5217SJeff Kirsher if (PCI_FUNC(bp->pdev->devfn) == 0) { 7837adfc5217SJeff Kirsher switch (strap) { 7838adfc5217SJeff Kirsher case 0x4: 7839adfc5217SJeff Kirsher case 0x5: 7840adfc5217SJeff Kirsher case 0x6: 7841adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_SERDES; 7842adfc5217SJeff Kirsher return; 7843adfc5217SJeff Kirsher } 7844adfc5217SJeff Kirsher } else { 7845adfc5217SJeff Kirsher switch (strap) { 7846adfc5217SJeff Kirsher case 0x1: 7847adfc5217SJeff Kirsher case 0x2: 7848adfc5217SJeff Kirsher case 0x4: 7849adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_SERDES; 7850adfc5217SJeff Kirsher return; 7851adfc5217SJeff Kirsher } 7852adfc5217SJeff Kirsher } 7853adfc5217SJeff Kirsher } 7854adfc5217SJeff Kirsher 7855adfc5217SJeff Kirsher static void __devinit 7856adfc5217SJeff Kirsher bnx2_get_pci_speed(struct bnx2 *bp) 7857adfc5217SJeff Kirsher { 7858adfc5217SJeff Kirsher u32 reg; 7859adfc5217SJeff Kirsher 7860adfc5217SJeff Kirsher reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); 7861adfc5217SJeff Kirsher if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { 7862adfc5217SJeff Kirsher u32 clkreg; 7863adfc5217SJeff Kirsher 7864adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_PCIX; 7865adfc5217SJeff Kirsher 7866adfc5217SJeff Kirsher clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); 7867adfc5217SJeff Kirsher 7868adfc5217SJeff Kirsher clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; 7869adfc5217SJeff Kirsher switch (clkreg) { 7870adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: 7871adfc5217SJeff Kirsher bp->bus_speed_mhz = 133; 7872adfc5217SJeff Kirsher break; 7873adfc5217SJeff Kirsher 7874adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: 7875adfc5217SJeff Kirsher bp->bus_speed_mhz = 100; 7876adfc5217SJeff Kirsher break; 7877adfc5217SJeff Kirsher 7878adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: 7879adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: 7880adfc5217SJeff Kirsher bp->bus_speed_mhz = 66; 7881adfc5217SJeff Kirsher break; 7882adfc5217SJeff Kirsher 7883adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: 7884adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: 7885adfc5217SJeff Kirsher bp->bus_speed_mhz = 50; 7886adfc5217SJeff Kirsher break; 7887adfc5217SJeff Kirsher 7888adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: 7889adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: 7890adfc5217SJeff Kirsher case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: 7891adfc5217SJeff Kirsher bp->bus_speed_mhz = 33; 7892adfc5217SJeff Kirsher break; 7893adfc5217SJeff Kirsher } 7894adfc5217SJeff Kirsher } 7895adfc5217SJeff Kirsher else { 7896adfc5217SJeff Kirsher if (reg & BNX2_PCICFG_MISC_STATUS_M66EN) 7897adfc5217SJeff Kirsher bp->bus_speed_mhz = 66; 7898adfc5217SJeff Kirsher else 7899adfc5217SJeff Kirsher bp->bus_speed_mhz = 33; 7900adfc5217SJeff Kirsher } 7901adfc5217SJeff Kirsher 7902adfc5217SJeff Kirsher if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET) 7903adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_PCI_32BIT; 7904adfc5217SJeff Kirsher 7905adfc5217SJeff Kirsher } 7906adfc5217SJeff Kirsher 7907adfc5217SJeff Kirsher static void __devinit 7908adfc5217SJeff Kirsher bnx2_read_vpd_fw_ver(struct bnx2 *bp) 7909adfc5217SJeff Kirsher { 7910adfc5217SJeff Kirsher int rc, i, j; 7911adfc5217SJeff Kirsher u8 *data; 7912adfc5217SJeff Kirsher unsigned int block_end, rosize, len; 7913adfc5217SJeff Kirsher 7914adfc5217SJeff Kirsher #define BNX2_VPD_NVRAM_OFFSET 0x300 7915adfc5217SJeff Kirsher #define BNX2_VPD_LEN 128 7916adfc5217SJeff Kirsher #define BNX2_MAX_VER_SLEN 30 7917adfc5217SJeff Kirsher 7918adfc5217SJeff Kirsher data = kmalloc(256, GFP_KERNEL); 7919adfc5217SJeff Kirsher if (!data) 7920adfc5217SJeff Kirsher return; 7921adfc5217SJeff Kirsher 7922adfc5217SJeff Kirsher rc = bnx2_nvram_read(bp, BNX2_VPD_NVRAM_OFFSET, data + BNX2_VPD_LEN, 7923adfc5217SJeff Kirsher BNX2_VPD_LEN); 7924adfc5217SJeff Kirsher if (rc) 7925adfc5217SJeff Kirsher goto vpd_done; 7926adfc5217SJeff Kirsher 7927adfc5217SJeff Kirsher for (i = 0; i < BNX2_VPD_LEN; i += 4) { 7928adfc5217SJeff Kirsher data[i] = data[i + BNX2_VPD_LEN + 3]; 7929adfc5217SJeff Kirsher data[i + 1] = data[i + BNX2_VPD_LEN + 2]; 7930adfc5217SJeff Kirsher data[i + 2] = data[i + BNX2_VPD_LEN + 1]; 7931adfc5217SJeff Kirsher data[i + 3] = data[i + BNX2_VPD_LEN]; 7932adfc5217SJeff Kirsher } 7933adfc5217SJeff Kirsher 7934adfc5217SJeff Kirsher i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA); 7935adfc5217SJeff Kirsher if (i < 0) 7936adfc5217SJeff Kirsher goto vpd_done; 7937adfc5217SJeff Kirsher 7938adfc5217SJeff Kirsher rosize = pci_vpd_lrdt_size(&data[i]); 7939adfc5217SJeff Kirsher i += PCI_VPD_LRDT_TAG_SIZE; 7940adfc5217SJeff Kirsher block_end = i + rosize; 7941adfc5217SJeff Kirsher 7942adfc5217SJeff Kirsher if (block_end > BNX2_VPD_LEN) 7943adfc5217SJeff Kirsher goto vpd_done; 7944adfc5217SJeff Kirsher 7945adfc5217SJeff Kirsher j = pci_vpd_find_info_keyword(data, i, rosize, 7946adfc5217SJeff Kirsher PCI_VPD_RO_KEYWORD_MFR_ID); 7947adfc5217SJeff Kirsher if (j < 0) 7948adfc5217SJeff Kirsher goto vpd_done; 7949adfc5217SJeff Kirsher 7950adfc5217SJeff Kirsher len = pci_vpd_info_field_size(&data[j]); 7951adfc5217SJeff Kirsher 7952adfc5217SJeff Kirsher j += PCI_VPD_INFO_FLD_HDR_SIZE; 7953adfc5217SJeff Kirsher if (j + len > block_end || len != 4 || 7954adfc5217SJeff Kirsher memcmp(&data[j], "1028", 4)) 7955adfc5217SJeff Kirsher goto vpd_done; 7956adfc5217SJeff Kirsher 7957adfc5217SJeff Kirsher j = pci_vpd_find_info_keyword(data, i, rosize, 7958adfc5217SJeff Kirsher PCI_VPD_RO_KEYWORD_VENDOR0); 7959adfc5217SJeff Kirsher if (j < 0) 7960adfc5217SJeff Kirsher goto vpd_done; 7961adfc5217SJeff Kirsher 7962adfc5217SJeff Kirsher len = pci_vpd_info_field_size(&data[j]); 7963adfc5217SJeff Kirsher 7964adfc5217SJeff Kirsher j += PCI_VPD_INFO_FLD_HDR_SIZE; 7965adfc5217SJeff Kirsher if (j + len > block_end || len > BNX2_MAX_VER_SLEN) 7966adfc5217SJeff Kirsher goto vpd_done; 7967adfc5217SJeff Kirsher 7968adfc5217SJeff Kirsher memcpy(bp->fw_version, &data[j], len); 7969adfc5217SJeff Kirsher bp->fw_version[len] = ' '; 7970adfc5217SJeff Kirsher 7971adfc5217SJeff Kirsher vpd_done: 7972adfc5217SJeff Kirsher kfree(data); 7973adfc5217SJeff Kirsher } 7974adfc5217SJeff Kirsher 7975adfc5217SJeff Kirsher static int __devinit 7976adfc5217SJeff Kirsher bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 7977adfc5217SJeff Kirsher { 7978adfc5217SJeff Kirsher struct bnx2 *bp; 7979adfc5217SJeff Kirsher int rc, i, j; 7980adfc5217SJeff Kirsher u32 reg; 7981adfc5217SJeff Kirsher u64 dma_mask, persist_dma_mask; 7982adfc5217SJeff Kirsher int err; 7983adfc5217SJeff Kirsher 7984adfc5217SJeff Kirsher SET_NETDEV_DEV(dev, &pdev->dev); 7985adfc5217SJeff Kirsher bp = netdev_priv(dev); 7986adfc5217SJeff Kirsher 7987adfc5217SJeff Kirsher bp->flags = 0; 7988adfc5217SJeff Kirsher bp->phy_flags = 0; 7989adfc5217SJeff Kirsher 7990adfc5217SJeff Kirsher bp->temp_stats_blk = 7991adfc5217SJeff Kirsher kzalloc(sizeof(struct statistics_block), GFP_KERNEL); 7992adfc5217SJeff Kirsher 7993adfc5217SJeff Kirsher if (bp->temp_stats_blk == NULL) { 7994adfc5217SJeff Kirsher rc = -ENOMEM; 7995adfc5217SJeff Kirsher goto err_out; 7996adfc5217SJeff Kirsher } 7997adfc5217SJeff Kirsher 7998adfc5217SJeff Kirsher /* enable device (incl. PCI PM wakeup), and bus-mastering */ 7999adfc5217SJeff Kirsher rc = pci_enable_device(pdev); 8000adfc5217SJeff Kirsher if (rc) { 8001adfc5217SJeff Kirsher dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); 8002adfc5217SJeff Kirsher goto err_out; 8003adfc5217SJeff Kirsher } 8004adfc5217SJeff Kirsher 8005adfc5217SJeff Kirsher if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 8006adfc5217SJeff Kirsher dev_err(&pdev->dev, 8007adfc5217SJeff Kirsher "Cannot find PCI device base address, aborting\n"); 8008adfc5217SJeff Kirsher rc = -ENODEV; 8009adfc5217SJeff Kirsher goto err_out_disable; 8010adfc5217SJeff Kirsher } 8011adfc5217SJeff Kirsher 8012adfc5217SJeff Kirsher rc = pci_request_regions(pdev, DRV_MODULE_NAME); 8013adfc5217SJeff Kirsher if (rc) { 8014adfc5217SJeff Kirsher dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); 8015adfc5217SJeff Kirsher goto err_out_disable; 8016adfc5217SJeff Kirsher } 8017adfc5217SJeff Kirsher 8018adfc5217SJeff Kirsher pci_set_master(pdev); 8019adfc5217SJeff Kirsher 8020adfc5217SJeff Kirsher bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); 8021adfc5217SJeff Kirsher if (bp->pm_cap == 0) { 8022adfc5217SJeff Kirsher dev_err(&pdev->dev, 8023adfc5217SJeff Kirsher "Cannot find power management capability, aborting\n"); 8024adfc5217SJeff Kirsher rc = -EIO; 8025adfc5217SJeff Kirsher goto err_out_release; 8026adfc5217SJeff Kirsher } 8027adfc5217SJeff Kirsher 8028adfc5217SJeff Kirsher bp->dev = dev; 8029adfc5217SJeff Kirsher bp->pdev = pdev; 8030adfc5217SJeff Kirsher 8031adfc5217SJeff Kirsher spin_lock_init(&bp->phy_lock); 8032adfc5217SJeff Kirsher spin_lock_init(&bp->indirect_lock); 8033adfc5217SJeff Kirsher #ifdef BCM_CNIC 8034adfc5217SJeff Kirsher mutex_init(&bp->cnic_lock); 8035adfc5217SJeff Kirsher #endif 8036adfc5217SJeff Kirsher INIT_WORK(&bp->reset_task, bnx2_reset_task); 8037adfc5217SJeff Kirsher 8038c0357e97SFrancois Romieu bp->regview = pci_iomap(pdev, 0, MB_GET_CID_ADDR(TX_TSS_CID + 8039c0357e97SFrancois Romieu TX_MAX_TSS_RINGS + 1)); 8040adfc5217SJeff Kirsher if (!bp->regview) { 8041adfc5217SJeff Kirsher dev_err(&pdev->dev, "Cannot map register space, aborting\n"); 8042adfc5217SJeff Kirsher rc = -ENOMEM; 8043adfc5217SJeff Kirsher goto err_out_release; 8044adfc5217SJeff Kirsher } 8045adfc5217SJeff Kirsher 8046adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 8047adfc5217SJeff Kirsher 8048adfc5217SJeff Kirsher /* Configure byte swap and enable write to the reg_window registers. 8049adfc5217SJeff Kirsher * Rely on CPU to do target byte swapping on big endian systems 8050adfc5217SJeff Kirsher * The chip's target access swapping will not swap all accesses 8051adfc5217SJeff Kirsher */ 8052adfc5217SJeff Kirsher REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, 8053adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | 8054adfc5217SJeff Kirsher BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); 8055adfc5217SJeff Kirsher 8056adfc5217SJeff Kirsher bp->chip_id = REG_RD(bp, BNX2_MISC_ID); 8057adfc5217SJeff Kirsher 8058adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) { 8059adfc5217SJeff Kirsher if (!pci_is_pcie(pdev)) { 8060adfc5217SJeff Kirsher dev_err(&pdev->dev, "Not PCIE, aborting\n"); 8061adfc5217SJeff Kirsher rc = -EIO; 8062adfc5217SJeff Kirsher goto err_out_unmap; 8063adfc5217SJeff Kirsher } 8064adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_PCIE; 8065adfc5217SJeff Kirsher if (CHIP_REV(bp) == CHIP_REV_Ax) 8066adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_JUMBO_BROKEN; 8067adfc5217SJeff Kirsher 8068adfc5217SJeff Kirsher /* AER (Advanced Error Reporting) hooks */ 8069adfc5217SJeff Kirsher err = pci_enable_pcie_error_reporting(pdev); 8070adfc5217SJeff Kirsher if (!err) 8071adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_AER_ENABLED; 8072adfc5217SJeff Kirsher 8073adfc5217SJeff Kirsher } else { 8074adfc5217SJeff Kirsher bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); 8075adfc5217SJeff Kirsher if (bp->pcix_cap == 0) { 8076adfc5217SJeff Kirsher dev_err(&pdev->dev, 8077adfc5217SJeff Kirsher "Cannot find PCIX capability, aborting\n"); 8078adfc5217SJeff Kirsher rc = -EIO; 8079adfc5217SJeff Kirsher goto err_out_unmap; 8080adfc5217SJeff Kirsher } 8081adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_BROKEN_STATS; 8082adfc5217SJeff Kirsher } 8083adfc5217SJeff Kirsher 8084adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) { 8085adfc5217SJeff Kirsher if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) 8086adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_MSIX_CAP; 8087adfc5217SJeff Kirsher } 8088adfc5217SJeff Kirsher 8089adfc5217SJeff Kirsher if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) { 8090adfc5217SJeff Kirsher if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) 8091adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_MSI_CAP; 8092adfc5217SJeff Kirsher } 8093adfc5217SJeff Kirsher 8094adfc5217SJeff Kirsher /* 5708 cannot support DMA addresses > 40-bit. */ 8095adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5708) 8096adfc5217SJeff Kirsher persist_dma_mask = dma_mask = DMA_BIT_MASK(40); 8097adfc5217SJeff Kirsher else 8098adfc5217SJeff Kirsher persist_dma_mask = dma_mask = DMA_BIT_MASK(64); 8099adfc5217SJeff Kirsher 8100adfc5217SJeff Kirsher /* Configure DMA attributes. */ 8101adfc5217SJeff Kirsher if (pci_set_dma_mask(pdev, dma_mask) == 0) { 8102adfc5217SJeff Kirsher dev->features |= NETIF_F_HIGHDMA; 8103adfc5217SJeff Kirsher rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask); 8104adfc5217SJeff Kirsher if (rc) { 8105adfc5217SJeff Kirsher dev_err(&pdev->dev, 8106adfc5217SJeff Kirsher "pci_set_consistent_dma_mask failed, aborting\n"); 8107adfc5217SJeff Kirsher goto err_out_unmap; 8108adfc5217SJeff Kirsher } 8109adfc5217SJeff Kirsher } else if ((rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { 8110adfc5217SJeff Kirsher dev_err(&pdev->dev, "System does not support DMA, aborting\n"); 8111adfc5217SJeff Kirsher goto err_out_unmap; 8112adfc5217SJeff Kirsher } 8113adfc5217SJeff Kirsher 8114adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_PCIE)) 8115adfc5217SJeff Kirsher bnx2_get_pci_speed(bp); 8116adfc5217SJeff Kirsher 8117adfc5217SJeff Kirsher /* 5706A0 may falsely detect SERR and PERR. */ 8118adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A0) { 8119adfc5217SJeff Kirsher reg = REG_RD(bp, PCI_COMMAND); 8120adfc5217SJeff Kirsher reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); 8121adfc5217SJeff Kirsher REG_WR(bp, PCI_COMMAND, reg); 8122adfc5217SJeff Kirsher } 8123adfc5217SJeff Kirsher else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) && 8124adfc5217SJeff Kirsher !(bp->flags & BNX2_FLAG_PCIX)) { 8125adfc5217SJeff Kirsher 8126adfc5217SJeff Kirsher dev_err(&pdev->dev, 8127adfc5217SJeff Kirsher "5706 A1 can only be used in a PCIX bus, aborting\n"); 8128adfc5217SJeff Kirsher goto err_out_unmap; 8129adfc5217SJeff Kirsher } 8130adfc5217SJeff Kirsher 8131adfc5217SJeff Kirsher bnx2_init_nvram(bp); 8132adfc5217SJeff Kirsher 8133adfc5217SJeff Kirsher reg = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_SIGNATURE); 8134adfc5217SJeff Kirsher 8135adfc5217SJeff Kirsher if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) == 8136adfc5217SJeff Kirsher BNX2_SHM_HDR_SIGNATURE_SIG) { 8137adfc5217SJeff Kirsher u32 off = PCI_FUNC(pdev->devfn) << 2; 8138adfc5217SJeff Kirsher 8139adfc5217SJeff Kirsher bp->shmem_base = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_ADDR_0 + off); 8140adfc5217SJeff Kirsher } else 8141adfc5217SJeff Kirsher bp->shmem_base = HOST_VIEW_SHMEM_BASE; 8142adfc5217SJeff Kirsher 8143adfc5217SJeff Kirsher /* Get the permanent MAC address. First we need to make sure the 8144adfc5217SJeff Kirsher * firmware is actually running. 8145adfc5217SJeff Kirsher */ 8146adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE); 8147adfc5217SJeff Kirsher 8148adfc5217SJeff Kirsher if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != 8149adfc5217SJeff Kirsher BNX2_DEV_INFO_SIGNATURE_MAGIC) { 8150adfc5217SJeff Kirsher dev_err(&pdev->dev, "Firmware not running, aborting\n"); 8151adfc5217SJeff Kirsher rc = -ENODEV; 8152adfc5217SJeff Kirsher goto err_out_unmap; 8153adfc5217SJeff Kirsher } 8154adfc5217SJeff Kirsher 8155adfc5217SJeff Kirsher bnx2_read_vpd_fw_ver(bp); 8156adfc5217SJeff Kirsher 8157adfc5217SJeff Kirsher j = strlen(bp->fw_version); 8158adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV); 8159adfc5217SJeff Kirsher for (i = 0; i < 3 && j < 24; i++) { 8160adfc5217SJeff Kirsher u8 num, k, skip0; 8161adfc5217SJeff Kirsher 8162adfc5217SJeff Kirsher if (i == 0) { 8163adfc5217SJeff Kirsher bp->fw_version[j++] = 'b'; 8164adfc5217SJeff Kirsher bp->fw_version[j++] = 'c'; 8165adfc5217SJeff Kirsher bp->fw_version[j++] = ' '; 8166adfc5217SJeff Kirsher } 8167adfc5217SJeff Kirsher num = (u8) (reg >> (24 - (i * 8))); 8168adfc5217SJeff Kirsher for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { 8169adfc5217SJeff Kirsher if (num >= k || !skip0 || k == 1) { 8170adfc5217SJeff Kirsher bp->fw_version[j++] = (num / k) + '0'; 8171adfc5217SJeff Kirsher skip0 = 0; 8172adfc5217SJeff Kirsher } 8173adfc5217SJeff Kirsher } 8174adfc5217SJeff Kirsher if (i != 2) 8175adfc5217SJeff Kirsher bp->fw_version[j++] = '.'; 8176adfc5217SJeff Kirsher } 8177adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE); 8178adfc5217SJeff Kirsher if (reg & BNX2_PORT_FEATURE_WOL_ENABLED) 8179adfc5217SJeff Kirsher bp->wol = 1; 8180adfc5217SJeff Kirsher 8181adfc5217SJeff Kirsher if (reg & BNX2_PORT_FEATURE_ASF_ENABLED) { 8182adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_ASF_ENABLE; 8183adfc5217SJeff Kirsher 8184adfc5217SJeff Kirsher for (i = 0; i < 30; i++) { 8185adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); 8186adfc5217SJeff Kirsher if (reg & BNX2_CONDITION_MFW_RUN_MASK) 8187adfc5217SJeff Kirsher break; 8188adfc5217SJeff Kirsher msleep(10); 8189adfc5217SJeff Kirsher } 8190adfc5217SJeff Kirsher } 8191adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); 8192adfc5217SJeff Kirsher reg &= BNX2_CONDITION_MFW_RUN_MASK; 8193adfc5217SJeff Kirsher if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN && 8194adfc5217SJeff Kirsher reg != BNX2_CONDITION_MFW_RUN_NONE) { 8195adfc5217SJeff Kirsher u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR); 8196adfc5217SJeff Kirsher 8197adfc5217SJeff Kirsher if (j < 32) 8198adfc5217SJeff Kirsher bp->fw_version[j++] = ' '; 8199adfc5217SJeff Kirsher for (i = 0; i < 3 && j < 28; i++) { 8200adfc5217SJeff Kirsher reg = bnx2_reg_rd_ind(bp, addr + i * 4); 8201adfc5217SJeff Kirsher reg = be32_to_cpu(reg); 8202adfc5217SJeff Kirsher memcpy(&bp->fw_version[j], ®, 4); 8203adfc5217SJeff Kirsher j += 4; 8204adfc5217SJeff Kirsher } 8205adfc5217SJeff Kirsher } 8206adfc5217SJeff Kirsher 8207adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_UPPER); 8208adfc5217SJeff Kirsher bp->mac_addr[0] = (u8) (reg >> 8); 8209adfc5217SJeff Kirsher bp->mac_addr[1] = (u8) reg; 8210adfc5217SJeff Kirsher 8211adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_LOWER); 8212adfc5217SJeff Kirsher bp->mac_addr[2] = (u8) (reg >> 24); 8213adfc5217SJeff Kirsher bp->mac_addr[3] = (u8) (reg >> 16); 8214adfc5217SJeff Kirsher bp->mac_addr[4] = (u8) (reg >> 8); 8215adfc5217SJeff Kirsher bp->mac_addr[5] = (u8) reg; 8216adfc5217SJeff Kirsher 8217adfc5217SJeff Kirsher bp->tx_ring_size = MAX_TX_DESC_CNT; 8218adfc5217SJeff Kirsher bnx2_set_rx_ring_size(bp, 255); 8219adfc5217SJeff Kirsher 8220adfc5217SJeff Kirsher bp->tx_quick_cons_trip_int = 2; 8221adfc5217SJeff Kirsher bp->tx_quick_cons_trip = 20; 8222adfc5217SJeff Kirsher bp->tx_ticks_int = 18; 8223adfc5217SJeff Kirsher bp->tx_ticks = 80; 8224adfc5217SJeff Kirsher 8225adfc5217SJeff Kirsher bp->rx_quick_cons_trip_int = 2; 8226adfc5217SJeff Kirsher bp->rx_quick_cons_trip = 12; 8227adfc5217SJeff Kirsher bp->rx_ticks_int = 18; 8228adfc5217SJeff Kirsher bp->rx_ticks = 18; 8229adfc5217SJeff Kirsher 8230adfc5217SJeff Kirsher bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS; 8231adfc5217SJeff Kirsher 8232adfc5217SJeff Kirsher bp->current_interval = BNX2_TIMER_INTERVAL; 8233adfc5217SJeff Kirsher 8234adfc5217SJeff Kirsher bp->phy_addr = 1; 8235adfc5217SJeff Kirsher 8236adfc5217SJeff Kirsher /* Disable WOL support if we are running on a SERDES chip. */ 8237adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 8238adfc5217SJeff Kirsher bnx2_get_5709_media(bp); 8239adfc5217SJeff Kirsher else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) 8240adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_SERDES; 8241adfc5217SJeff Kirsher 8242adfc5217SJeff Kirsher bp->phy_port = PORT_TP; 8243adfc5217SJeff Kirsher if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { 8244adfc5217SJeff Kirsher bp->phy_port = PORT_FIBRE; 8245adfc5217SJeff Kirsher reg = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG); 8246adfc5217SJeff Kirsher if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) { 8247adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_NO_WOL; 8248adfc5217SJeff Kirsher bp->wol = 0; 8249adfc5217SJeff Kirsher } 8250adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706) { 8251adfc5217SJeff Kirsher /* Don't do parallel detect on this board because of 8252adfc5217SJeff Kirsher * some board problems. The link will not go down 8253adfc5217SJeff Kirsher * if we do parallel detect. 8254adfc5217SJeff Kirsher */ 8255adfc5217SJeff Kirsher if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP && 8256adfc5217SJeff Kirsher pdev->subsystem_device == 0x310c) 8257adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_NO_PARALLEL; 8258adfc5217SJeff Kirsher } else { 8259adfc5217SJeff Kirsher bp->phy_addr = 2; 8260adfc5217SJeff Kirsher if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) 8261adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE; 8262adfc5217SJeff Kirsher } 8263adfc5217SJeff Kirsher } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || 8264adfc5217SJeff Kirsher CHIP_NUM(bp) == CHIP_NUM_5708) 8265adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX; 8266adfc5217SJeff Kirsher else if (CHIP_NUM(bp) == CHIP_NUM_5709 && 8267adfc5217SJeff Kirsher (CHIP_REV(bp) == CHIP_REV_Ax || 8268adfc5217SJeff Kirsher CHIP_REV(bp) == CHIP_REV_Bx)) 8269adfc5217SJeff Kirsher bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC; 8270adfc5217SJeff Kirsher 8271adfc5217SJeff Kirsher bnx2_init_fw_cap(bp); 8272adfc5217SJeff Kirsher 8273adfc5217SJeff Kirsher if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || 8274adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_B0) || 8275adfc5217SJeff Kirsher (CHIP_ID(bp) == CHIP_ID_5708_B1) || 8276adfc5217SJeff Kirsher !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) { 8277adfc5217SJeff Kirsher bp->flags |= BNX2_FLAG_NO_WOL; 8278adfc5217SJeff Kirsher bp->wol = 0; 8279adfc5217SJeff Kirsher } 8280adfc5217SJeff Kirsher 8281adfc5217SJeff Kirsher if (CHIP_ID(bp) == CHIP_ID_5706_A0) { 8282adfc5217SJeff Kirsher bp->tx_quick_cons_trip_int = 8283adfc5217SJeff Kirsher bp->tx_quick_cons_trip; 8284adfc5217SJeff Kirsher bp->tx_ticks_int = bp->tx_ticks; 8285adfc5217SJeff Kirsher bp->rx_quick_cons_trip_int = 8286adfc5217SJeff Kirsher bp->rx_quick_cons_trip; 8287adfc5217SJeff Kirsher bp->rx_ticks_int = bp->rx_ticks; 8288adfc5217SJeff Kirsher bp->comp_prod_trip_int = bp->comp_prod_trip; 8289adfc5217SJeff Kirsher bp->com_ticks_int = bp->com_ticks; 8290adfc5217SJeff Kirsher bp->cmd_ticks_int = bp->cmd_ticks; 8291adfc5217SJeff Kirsher } 8292adfc5217SJeff Kirsher 8293adfc5217SJeff Kirsher /* Disable MSI on 5706 if AMD 8132 bridge is found. 8294adfc5217SJeff Kirsher * 8295adfc5217SJeff Kirsher * MSI is defined to be 32-bit write. The 5706 does 64-bit MSI writes 8296adfc5217SJeff Kirsher * with byte enables disabled on the unused 32-bit word. This is legal 8297adfc5217SJeff Kirsher * but causes problems on the AMD 8132 which will eventually stop 8298adfc5217SJeff Kirsher * responding after a while. 8299adfc5217SJeff Kirsher * 8300adfc5217SJeff Kirsher * AMD believes this incompatibility is unique to the 5706, and 8301adfc5217SJeff Kirsher * prefers to locally disable MSI rather than globally disabling it. 8302adfc5217SJeff Kirsher */ 8303adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { 8304adfc5217SJeff Kirsher struct pci_dev *amd_8132 = NULL; 8305adfc5217SJeff Kirsher 8306adfc5217SJeff Kirsher while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, 8307adfc5217SJeff Kirsher PCI_DEVICE_ID_AMD_8132_BRIDGE, 8308adfc5217SJeff Kirsher amd_8132))) { 8309adfc5217SJeff Kirsher 8310adfc5217SJeff Kirsher if (amd_8132->revision >= 0x10 && 8311adfc5217SJeff Kirsher amd_8132->revision <= 0x13) { 8312adfc5217SJeff Kirsher disable_msi = 1; 8313adfc5217SJeff Kirsher pci_dev_put(amd_8132); 8314adfc5217SJeff Kirsher break; 8315adfc5217SJeff Kirsher } 8316adfc5217SJeff Kirsher } 8317adfc5217SJeff Kirsher } 8318adfc5217SJeff Kirsher 8319adfc5217SJeff Kirsher bnx2_set_default_link(bp); 8320adfc5217SJeff Kirsher bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; 8321adfc5217SJeff Kirsher 8322adfc5217SJeff Kirsher init_timer(&bp->timer); 8323adfc5217SJeff Kirsher bp->timer.expires = RUN_AT(BNX2_TIMER_INTERVAL); 8324adfc5217SJeff Kirsher bp->timer.data = (unsigned long) bp; 8325adfc5217SJeff Kirsher bp->timer.function = bnx2_timer; 8326adfc5217SJeff Kirsher 8327adfc5217SJeff Kirsher #ifdef BCM_CNIC 8328adfc5217SJeff Kirsher if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN) 8329adfc5217SJeff Kirsher bp->cnic_eth_dev.max_iscsi_conn = 8330adfc5217SJeff Kirsher (bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) & 8331adfc5217SJeff Kirsher BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT; 8332adfc5217SJeff Kirsher #endif 8333adfc5217SJeff Kirsher pci_save_state(pdev); 8334adfc5217SJeff Kirsher 8335adfc5217SJeff Kirsher return 0; 8336adfc5217SJeff Kirsher 8337adfc5217SJeff Kirsher err_out_unmap: 8338adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_AER_ENABLED) { 8339adfc5217SJeff Kirsher pci_disable_pcie_error_reporting(pdev); 8340adfc5217SJeff Kirsher bp->flags &= ~BNX2_FLAG_AER_ENABLED; 8341adfc5217SJeff Kirsher } 8342adfc5217SJeff Kirsher 8343c0357e97SFrancois Romieu pci_iounmap(pdev, bp->regview); 8344adfc5217SJeff Kirsher bp->regview = NULL; 8345adfc5217SJeff Kirsher 8346adfc5217SJeff Kirsher err_out_release: 8347adfc5217SJeff Kirsher pci_release_regions(pdev); 8348adfc5217SJeff Kirsher 8349adfc5217SJeff Kirsher err_out_disable: 8350adfc5217SJeff Kirsher pci_disable_device(pdev); 8351adfc5217SJeff Kirsher pci_set_drvdata(pdev, NULL); 8352adfc5217SJeff Kirsher 8353adfc5217SJeff Kirsher err_out: 8354adfc5217SJeff Kirsher return rc; 8355adfc5217SJeff Kirsher } 8356adfc5217SJeff Kirsher 8357adfc5217SJeff Kirsher static char * __devinit 8358adfc5217SJeff Kirsher bnx2_bus_string(struct bnx2 *bp, char *str) 8359adfc5217SJeff Kirsher { 8360adfc5217SJeff Kirsher char *s = str; 8361adfc5217SJeff Kirsher 8362adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_PCIE) { 8363adfc5217SJeff Kirsher s += sprintf(s, "PCI Express"); 8364adfc5217SJeff Kirsher } else { 8365adfc5217SJeff Kirsher s += sprintf(s, "PCI"); 8366adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_PCIX) 8367adfc5217SJeff Kirsher s += sprintf(s, "-X"); 8368adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_PCI_32BIT) 8369adfc5217SJeff Kirsher s += sprintf(s, " 32-bit"); 8370adfc5217SJeff Kirsher else 8371adfc5217SJeff Kirsher s += sprintf(s, " 64-bit"); 8372adfc5217SJeff Kirsher s += sprintf(s, " %dMHz", bp->bus_speed_mhz); 8373adfc5217SJeff Kirsher } 8374adfc5217SJeff Kirsher return str; 8375adfc5217SJeff Kirsher } 8376adfc5217SJeff Kirsher 8377adfc5217SJeff Kirsher static void 8378adfc5217SJeff Kirsher bnx2_del_napi(struct bnx2 *bp) 8379adfc5217SJeff Kirsher { 8380adfc5217SJeff Kirsher int i; 8381adfc5217SJeff Kirsher 8382adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) 8383adfc5217SJeff Kirsher netif_napi_del(&bp->bnx2_napi[i].napi); 8384adfc5217SJeff Kirsher } 8385adfc5217SJeff Kirsher 8386adfc5217SJeff Kirsher static void 8387adfc5217SJeff Kirsher bnx2_init_napi(struct bnx2 *bp) 8388adfc5217SJeff Kirsher { 8389adfc5217SJeff Kirsher int i; 8390adfc5217SJeff Kirsher 8391adfc5217SJeff Kirsher for (i = 0; i < bp->irq_nvecs; i++) { 8392adfc5217SJeff Kirsher struct bnx2_napi *bnapi = &bp->bnx2_napi[i]; 8393adfc5217SJeff Kirsher int (*poll)(struct napi_struct *, int); 8394adfc5217SJeff Kirsher 8395adfc5217SJeff Kirsher if (i == 0) 8396adfc5217SJeff Kirsher poll = bnx2_poll; 8397adfc5217SJeff Kirsher else 8398adfc5217SJeff Kirsher poll = bnx2_poll_msix; 8399adfc5217SJeff Kirsher 8400adfc5217SJeff Kirsher netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64); 8401adfc5217SJeff Kirsher bnapi->bp = bp; 8402adfc5217SJeff Kirsher } 8403adfc5217SJeff Kirsher } 8404adfc5217SJeff Kirsher 8405adfc5217SJeff Kirsher static const struct net_device_ops bnx2_netdev_ops = { 8406adfc5217SJeff Kirsher .ndo_open = bnx2_open, 8407adfc5217SJeff Kirsher .ndo_start_xmit = bnx2_start_xmit, 8408adfc5217SJeff Kirsher .ndo_stop = bnx2_close, 8409adfc5217SJeff Kirsher .ndo_get_stats64 = bnx2_get_stats64, 8410adfc5217SJeff Kirsher .ndo_set_rx_mode = bnx2_set_rx_mode, 8411adfc5217SJeff Kirsher .ndo_do_ioctl = bnx2_ioctl, 8412adfc5217SJeff Kirsher .ndo_validate_addr = eth_validate_addr, 8413adfc5217SJeff Kirsher .ndo_set_mac_address = bnx2_change_mac_addr, 8414adfc5217SJeff Kirsher .ndo_change_mtu = bnx2_change_mtu, 8415adfc5217SJeff Kirsher .ndo_fix_features = bnx2_fix_features, 8416adfc5217SJeff Kirsher .ndo_set_features = bnx2_set_features, 8417adfc5217SJeff Kirsher .ndo_tx_timeout = bnx2_tx_timeout, 8418adfc5217SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 8419adfc5217SJeff Kirsher .ndo_poll_controller = poll_bnx2, 8420adfc5217SJeff Kirsher #endif 8421adfc5217SJeff Kirsher }; 8422adfc5217SJeff Kirsher 8423adfc5217SJeff Kirsher static int __devinit 8424adfc5217SJeff Kirsher bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 8425adfc5217SJeff Kirsher { 8426adfc5217SJeff Kirsher static int version_printed = 0; 8427c0357e97SFrancois Romieu struct net_device *dev; 8428adfc5217SJeff Kirsher struct bnx2 *bp; 8429adfc5217SJeff Kirsher int rc; 8430adfc5217SJeff Kirsher char str[40]; 8431adfc5217SJeff Kirsher 8432adfc5217SJeff Kirsher if (version_printed++ == 0) 8433adfc5217SJeff Kirsher pr_info("%s", version); 8434adfc5217SJeff Kirsher 8435adfc5217SJeff Kirsher /* dev zeroed in init_etherdev */ 8436adfc5217SJeff Kirsher dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS); 8437adfc5217SJeff Kirsher if (!dev) 8438adfc5217SJeff Kirsher return -ENOMEM; 8439adfc5217SJeff Kirsher 8440adfc5217SJeff Kirsher rc = bnx2_init_board(pdev, dev); 8441c0357e97SFrancois Romieu if (rc < 0) 8442c0357e97SFrancois Romieu goto err_free; 8443adfc5217SJeff Kirsher 8444adfc5217SJeff Kirsher dev->netdev_ops = &bnx2_netdev_ops; 8445adfc5217SJeff Kirsher dev->watchdog_timeo = TX_TIMEOUT; 8446adfc5217SJeff Kirsher dev->ethtool_ops = &bnx2_ethtool_ops; 8447adfc5217SJeff Kirsher 8448adfc5217SJeff Kirsher bp = netdev_priv(dev); 8449adfc5217SJeff Kirsher 8450adfc5217SJeff Kirsher pci_set_drvdata(pdev, dev); 8451adfc5217SJeff Kirsher 8452adfc5217SJeff Kirsher memcpy(dev->dev_addr, bp->mac_addr, 6); 8453adfc5217SJeff Kirsher memcpy(dev->perm_addr, bp->mac_addr, 6); 8454adfc5217SJeff Kirsher 8455adfc5217SJeff Kirsher dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | 8456adfc5217SJeff Kirsher NETIF_F_TSO | NETIF_F_TSO_ECN | 8457adfc5217SJeff Kirsher NETIF_F_RXHASH | NETIF_F_RXCSUM; 8458adfc5217SJeff Kirsher 8459adfc5217SJeff Kirsher if (CHIP_NUM(bp) == CHIP_NUM_5709) 8460adfc5217SJeff Kirsher dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; 8461adfc5217SJeff Kirsher 8462adfc5217SJeff Kirsher dev->vlan_features = dev->hw_features; 8463adfc5217SJeff Kirsher dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; 8464adfc5217SJeff Kirsher dev->features |= dev->hw_features; 846501789349SJiri Pirko dev->priv_flags |= IFF_UNICAST_FLT; 8466adfc5217SJeff Kirsher 8467adfc5217SJeff Kirsher if ((rc = register_netdev(dev))) { 8468adfc5217SJeff Kirsher dev_err(&pdev->dev, "Cannot register net device\n"); 8469adfc5217SJeff Kirsher goto error; 8470adfc5217SJeff Kirsher } 8471adfc5217SJeff Kirsher 8472c0357e97SFrancois Romieu netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, " 8473c0357e97SFrancois Romieu "node addr %pM\n", board_info[ent->driver_data].name, 8474adfc5217SJeff Kirsher ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', 8475adfc5217SJeff Kirsher ((CHIP_ID(bp) & 0x0ff0) >> 4), 8476c0357e97SFrancois Romieu bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0), 8477c0357e97SFrancois Romieu pdev->irq, dev->dev_addr); 8478adfc5217SJeff Kirsher 8479adfc5217SJeff Kirsher return 0; 8480adfc5217SJeff Kirsher 8481adfc5217SJeff Kirsher error: 8482adfc5217SJeff Kirsher iounmap(bp->regview); 8483adfc5217SJeff Kirsher pci_release_regions(pdev); 8484adfc5217SJeff Kirsher pci_disable_device(pdev); 8485adfc5217SJeff Kirsher pci_set_drvdata(pdev, NULL); 8486c0357e97SFrancois Romieu err_free: 8487adfc5217SJeff Kirsher free_netdev(dev); 8488adfc5217SJeff Kirsher return rc; 8489adfc5217SJeff Kirsher } 8490adfc5217SJeff Kirsher 8491adfc5217SJeff Kirsher static void __devexit 8492adfc5217SJeff Kirsher bnx2_remove_one(struct pci_dev *pdev) 8493adfc5217SJeff Kirsher { 8494adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8495adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8496adfc5217SJeff Kirsher 8497adfc5217SJeff Kirsher unregister_netdev(dev); 8498adfc5217SJeff Kirsher 8499adfc5217SJeff Kirsher del_timer_sync(&bp->timer); 8500adfc5217SJeff Kirsher cancel_work_sync(&bp->reset_task); 8501adfc5217SJeff Kirsher 8502c0357e97SFrancois Romieu pci_iounmap(bp->pdev, bp->regview); 8503adfc5217SJeff Kirsher 8504adfc5217SJeff Kirsher kfree(bp->temp_stats_blk); 8505adfc5217SJeff Kirsher 8506adfc5217SJeff Kirsher if (bp->flags & BNX2_FLAG_AER_ENABLED) { 8507adfc5217SJeff Kirsher pci_disable_pcie_error_reporting(pdev); 8508adfc5217SJeff Kirsher bp->flags &= ~BNX2_FLAG_AER_ENABLED; 8509adfc5217SJeff Kirsher } 8510adfc5217SJeff Kirsher 85117880b72eSfrançois romieu bnx2_release_firmware(bp); 85127880b72eSfrançois romieu 8513adfc5217SJeff Kirsher free_netdev(dev); 8514adfc5217SJeff Kirsher 8515adfc5217SJeff Kirsher pci_release_regions(pdev); 8516adfc5217SJeff Kirsher pci_disable_device(pdev); 8517adfc5217SJeff Kirsher pci_set_drvdata(pdev, NULL); 8518adfc5217SJeff Kirsher } 8519adfc5217SJeff Kirsher 8520adfc5217SJeff Kirsher static int 8521adfc5217SJeff Kirsher bnx2_suspend(struct pci_dev *pdev, pm_message_t state) 8522adfc5217SJeff Kirsher { 8523adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8524adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8525adfc5217SJeff Kirsher 8526adfc5217SJeff Kirsher /* PCI register 4 needs to be saved whether netif_running() or not. 8527adfc5217SJeff Kirsher * MSI address and data need to be saved if using MSI and 8528adfc5217SJeff Kirsher * netif_running(). 8529adfc5217SJeff Kirsher */ 8530adfc5217SJeff Kirsher pci_save_state(pdev); 8531adfc5217SJeff Kirsher if (!netif_running(dev)) 8532adfc5217SJeff Kirsher return 0; 8533adfc5217SJeff Kirsher 8534adfc5217SJeff Kirsher cancel_work_sync(&bp->reset_task); 8535adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 8536adfc5217SJeff Kirsher netif_device_detach(dev); 8537adfc5217SJeff Kirsher del_timer_sync(&bp->timer); 8538adfc5217SJeff Kirsher bnx2_shutdown_chip(bp); 8539adfc5217SJeff Kirsher bnx2_free_skbs(bp); 8540adfc5217SJeff Kirsher bnx2_set_power_state(bp, pci_choose_state(pdev, state)); 8541adfc5217SJeff Kirsher return 0; 8542adfc5217SJeff Kirsher } 8543adfc5217SJeff Kirsher 8544adfc5217SJeff Kirsher static int 8545adfc5217SJeff Kirsher bnx2_resume(struct pci_dev *pdev) 8546adfc5217SJeff Kirsher { 8547adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8548adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8549adfc5217SJeff Kirsher 8550adfc5217SJeff Kirsher pci_restore_state(pdev); 8551adfc5217SJeff Kirsher if (!netif_running(dev)) 8552adfc5217SJeff Kirsher return 0; 8553adfc5217SJeff Kirsher 8554adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 8555adfc5217SJeff Kirsher netif_device_attach(dev); 8556adfc5217SJeff Kirsher bnx2_init_nic(bp, 1); 8557adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 8558adfc5217SJeff Kirsher return 0; 8559adfc5217SJeff Kirsher } 8560adfc5217SJeff Kirsher 8561adfc5217SJeff Kirsher /** 8562adfc5217SJeff Kirsher * bnx2_io_error_detected - called when PCI error is detected 8563adfc5217SJeff Kirsher * @pdev: Pointer to PCI device 8564adfc5217SJeff Kirsher * @state: The current pci connection state 8565adfc5217SJeff Kirsher * 8566adfc5217SJeff Kirsher * This function is called after a PCI bus error affecting 8567adfc5217SJeff Kirsher * this device has been detected. 8568adfc5217SJeff Kirsher */ 8569adfc5217SJeff Kirsher static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev, 8570adfc5217SJeff Kirsher pci_channel_state_t state) 8571adfc5217SJeff Kirsher { 8572adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8573adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8574adfc5217SJeff Kirsher 8575adfc5217SJeff Kirsher rtnl_lock(); 8576adfc5217SJeff Kirsher netif_device_detach(dev); 8577adfc5217SJeff Kirsher 8578adfc5217SJeff Kirsher if (state == pci_channel_io_perm_failure) { 8579adfc5217SJeff Kirsher rtnl_unlock(); 8580adfc5217SJeff Kirsher return PCI_ERS_RESULT_DISCONNECT; 8581adfc5217SJeff Kirsher } 8582adfc5217SJeff Kirsher 8583adfc5217SJeff Kirsher if (netif_running(dev)) { 8584adfc5217SJeff Kirsher bnx2_netif_stop(bp, true); 8585adfc5217SJeff Kirsher del_timer_sync(&bp->timer); 8586adfc5217SJeff Kirsher bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); 8587adfc5217SJeff Kirsher } 8588adfc5217SJeff Kirsher 8589adfc5217SJeff Kirsher pci_disable_device(pdev); 8590adfc5217SJeff Kirsher rtnl_unlock(); 8591adfc5217SJeff Kirsher 8592adfc5217SJeff Kirsher /* Request a slot slot reset. */ 8593adfc5217SJeff Kirsher return PCI_ERS_RESULT_NEED_RESET; 8594adfc5217SJeff Kirsher } 8595adfc5217SJeff Kirsher 8596adfc5217SJeff Kirsher /** 8597adfc5217SJeff Kirsher * bnx2_io_slot_reset - called after the pci bus has been reset. 8598adfc5217SJeff Kirsher * @pdev: Pointer to PCI device 8599adfc5217SJeff Kirsher * 8600adfc5217SJeff Kirsher * Restart the card from scratch, as if from a cold-boot. 8601adfc5217SJeff Kirsher */ 8602adfc5217SJeff Kirsher static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) 8603adfc5217SJeff Kirsher { 8604adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8605adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8606adfc5217SJeff Kirsher pci_ers_result_t result; 8607adfc5217SJeff Kirsher int err; 8608adfc5217SJeff Kirsher 8609adfc5217SJeff Kirsher rtnl_lock(); 8610adfc5217SJeff Kirsher if (pci_enable_device(pdev)) { 8611adfc5217SJeff Kirsher dev_err(&pdev->dev, 8612adfc5217SJeff Kirsher "Cannot re-enable PCI device after reset\n"); 8613adfc5217SJeff Kirsher result = PCI_ERS_RESULT_DISCONNECT; 8614adfc5217SJeff Kirsher } else { 8615adfc5217SJeff Kirsher pci_set_master(pdev); 8616adfc5217SJeff Kirsher pci_restore_state(pdev); 8617adfc5217SJeff Kirsher pci_save_state(pdev); 8618adfc5217SJeff Kirsher 8619adfc5217SJeff Kirsher if (netif_running(dev)) { 8620adfc5217SJeff Kirsher bnx2_set_power_state(bp, PCI_D0); 8621adfc5217SJeff Kirsher bnx2_init_nic(bp, 1); 8622adfc5217SJeff Kirsher } 8623adfc5217SJeff Kirsher result = PCI_ERS_RESULT_RECOVERED; 8624adfc5217SJeff Kirsher } 8625adfc5217SJeff Kirsher rtnl_unlock(); 8626adfc5217SJeff Kirsher 8627adfc5217SJeff Kirsher if (!(bp->flags & BNX2_FLAG_AER_ENABLED)) 8628adfc5217SJeff Kirsher return result; 8629adfc5217SJeff Kirsher 8630adfc5217SJeff Kirsher err = pci_cleanup_aer_uncorrect_error_status(pdev); 8631adfc5217SJeff Kirsher if (err) { 8632adfc5217SJeff Kirsher dev_err(&pdev->dev, 8633adfc5217SJeff Kirsher "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", 8634adfc5217SJeff Kirsher err); /* non-fatal, continue */ 8635adfc5217SJeff Kirsher } 8636adfc5217SJeff Kirsher 8637adfc5217SJeff Kirsher return result; 8638adfc5217SJeff Kirsher } 8639adfc5217SJeff Kirsher 8640adfc5217SJeff Kirsher /** 8641adfc5217SJeff Kirsher * bnx2_io_resume - called when traffic can start flowing again. 8642adfc5217SJeff Kirsher * @pdev: Pointer to PCI device 8643adfc5217SJeff Kirsher * 8644adfc5217SJeff Kirsher * This callback is called when the error recovery driver tells us that 8645adfc5217SJeff Kirsher * its OK to resume normal operation. 8646adfc5217SJeff Kirsher */ 8647adfc5217SJeff Kirsher static void bnx2_io_resume(struct pci_dev *pdev) 8648adfc5217SJeff Kirsher { 8649adfc5217SJeff Kirsher struct net_device *dev = pci_get_drvdata(pdev); 8650adfc5217SJeff Kirsher struct bnx2 *bp = netdev_priv(dev); 8651adfc5217SJeff Kirsher 8652adfc5217SJeff Kirsher rtnl_lock(); 8653adfc5217SJeff Kirsher if (netif_running(dev)) 8654adfc5217SJeff Kirsher bnx2_netif_start(bp, true); 8655adfc5217SJeff Kirsher 8656adfc5217SJeff Kirsher netif_device_attach(dev); 8657adfc5217SJeff Kirsher rtnl_unlock(); 8658adfc5217SJeff Kirsher } 8659adfc5217SJeff Kirsher 8660adfc5217SJeff Kirsher static struct pci_error_handlers bnx2_err_handler = { 8661adfc5217SJeff Kirsher .error_detected = bnx2_io_error_detected, 8662adfc5217SJeff Kirsher .slot_reset = bnx2_io_slot_reset, 8663adfc5217SJeff Kirsher .resume = bnx2_io_resume, 8664adfc5217SJeff Kirsher }; 8665adfc5217SJeff Kirsher 8666adfc5217SJeff Kirsher static struct pci_driver bnx2_pci_driver = { 8667adfc5217SJeff Kirsher .name = DRV_MODULE_NAME, 8668adfc5217SJeff Kirsher .id_table = bnx2_pci_tbl, 8669adfc5217SJeff Kirsher .probe = bnx2_init_one, 8670adfc5217SJeff Kirsher .remove = __devexit_p(bnx2_remove_one), 8671adfc5217SJeff Kirsher .suspend = bnx2_suspend, 8672adfc5217SJeff Kirsher .resume = bnx2_resume, 8673adfc5217SJeff Kirsher .err_handler = &bnx2_err_handler, 8674adfc5217SJeff Kirsher }; 8675adfc5217SJeff Kirsher 8676adfc5217SJeff Kirsher static int __init bnx2_init(void) 8677adfc5217SJeff Kirsher { 8678adfc5217SJeff Kirsher return pci_register_driver(&bnx2_pci_driver); 8679adfc5217SJeff Kirsher } 8680adfc5217SJeff Kirsher 8681adfc5217SJeff Kirsher static void __exit bnx2_cleanup(void) 8682adfc5217SJeff Kirsher { 8683adfc5217SJeff Kirsher pci_unregister_driver(&bnx2_pci_driver); 8684adfc5217SJeff Kirsher } 8685adfc5217SJeff Kirsher 8686adfc5217SJeff Kirsher module_init(bnx2_init); 8687adfc5217SJeff Kirsher module_exit(bnx2_cleanup); 8688adfc5217SJeff Kirsher 8689adfc5217SJeff Kirsher 8690adfc5217SJeff Kirsher 8691