#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.6.5"
-#define DRV_MODULE_RELDATE "September 20, 2007"
+#define DRV_MODULE_VERSION "1.6.7"
+#define DRV_MODULE_RELDATE "October 10, 2007"
#define RUN_AT(x) (jiffies + (x))
return 0;
}
-static int
-bnx2_poll(struct napi_struct *napi, int budget)
+static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
{
- struct bnx2 *bp = container_of(napi, struct bnx2, napi);
- struct net_device *dev = bp->dev;
struct status_block *sblk = bp->status_blk;
u32 status_attn_bits = sblk->status_attn_bits;
u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
- int work_done = 0;
if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
(status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
REG_RD(bp, BNX2_HC_COMMAND);
}
- if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
+ if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
bnx2_tx_int(bp);
- if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
- work_done = bnx2_rx_int(bp, budget);
+ if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
+ work_done += bnx2_rx_int(bp, budget - work_done);
- bp->last_status_idx = bp->status_blk->status_idx;
- rmb();
+ return work_done;
+}
+
+static int bnx2_poll(struct napi_struct *napi, int budget)
+{
+ struct bnx2 *bp = container_of(napi, struct bnx2, napi);
+ int work_done = 0;
+ struct status_block *sblk = bp->status_blk;
+
+ while (1) {
+ work_done = bnx2_poll_work(bp, work_done, budget);
+
+ if (unlikely(work_done >= budget))
+ break;
- if (!bnx2_has_work(bp)) {
- netif_rx_complete(dev, napi);
- if (likely(bp->flags & USING_MSI_FLAG)) {
+ /* bp->last_status_idx is used below to tell the hw how
+ * much work has been processed, so we must read it before
+ * checking for more work.
+ */
+ bp->last_status_idx = sblk->status_idx;
+ rmb();
+ if (likely(!bnx2_has_work(bp))) {
+ netif_rx_complete(bp->dev, napi);
+ if (likely(bp->flags & USING_MSI_FLAG)) {
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bp->last_status_idx);
+ break;
+ }
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
bp->last_status_idx);
- return 0;
- }
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
- bp->last_status_idx);
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bp->last_status_idx);
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bp->last_status_idx);
+ break;
+ }
}
return work_done;
spin_unlock_bh(&bp->phy_lock);
}
-/* To be moved to generic lib/ */
-static int
-bnx2_gunzip(void *gunzip_buf, unsigned sz, u8 *zbuf, int len)
-{
- struct z_stream_s *strm;
- int rc;
-
- /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename)
- * is stripped */
-
- rc = -ENOMEM;
- strm = kmalloc(sizeof(*strm), GFP_KERNEL);
- if (strm == NULL)
- goto gunzip_nomem2;
- strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (strm->workspace == NULL)
- goto gunzip_nomem3;
-
- strm->next_in = zbuf;
- strm->avail_in = len;
- strm->next_out = gunzip_buf;
- strm->avail_out = sz;
-
- rc = zlib_inflateInit2(strm, -MAX_WBITS);
- if (rc == Z_OK) {
- rc = zlib_inflate(strm, Z_FINISH);
- /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
- if (rc == Z_STREAM_END)
- rc = sz - strm->avail_out;
- else
- rc = -EINVAL;
- zlib_inflateEnd(strm);
- } else
- rc = -EINVAL;
-
- kfree(strm->workspace);
-gunzip_nomem3:
- kfree(strm);
-gunzip_nomem2:
- return rc;
-}
-
static void
load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
u32 rv2p_proc)
/* Load the Text area. */
offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
if (fw->gz_text) {
- u32 *text;
int j;
- text = vmalloc(FW_BUF_SIZE);
- if (!text)
- return -ENOMEM;
- rc = bnx2_gunzip(text, FW_BUF_SIZE, fw->gz_text, fw->gz_text_len);
- if (rc < 0) {
- vfree(text);
+ rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text,
+ fw->gz_text_len);
+ if (rc < 0)
return rc;
- }
+
for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
- REG_WR_IND(bp, offset, cpu_to_le32(text[j]));
+ REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
}
- vfree(text);
}
/* Load the Data area. */
/* Load the SBSS area. */
offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
- if (fw->sbss) {
+ if (fw->sbss_len) {
int j;
for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
- REG_WR_IND(bp, offset, fw->sbss[j]);
+ REG_WR_IND(bp, offset, 0);
}
}
/* Load the BSS area. */
offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
- if (fw->bss) {
+ if (fw->bss_len) {
int j;
for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
- REG_WR_IND(bp, offset, fw->bss[j]);
+ REG_WR_IND(bp, offset, 0);
}
}
text = vmalloc(FW_BUF_SIZE);
if (!text)
return -ENOMEM;
- rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
- if (rc < 0) {
- vfree(text);
+ rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1));
+ if (rc < 0)
goto init_cpu_err;
- }
+
load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
- rc = bnx2_gunzip(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
- if (rc < 0) {
- vfree(text);
+ rc = zlib_inflate_blob(text, FW_BUF_SIZE, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2));
+ if (rc < 0)
goto init_cpu_err;
- }
+
load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
- vfree(text);
/* Initialize the RX Processor. */
cpu_reg.mode = BNX2_RXP_CPU_MODE;
else
fw = &bnx2_rxp_fw_06;
+ fw->text = text;
rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
else
fw = &bnx2_txp_fw_06;
+ fw->text = text;
rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
else
fw = &bnx2_tpat_fw_06;
+ fw->text = text;
rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
else
fw = &bnx2_com_fw_06;
+ fw->text = text;
rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
fw = &bnx2_cp_fw_09;
+ fw->text = text;
rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
}
init_cpu_err:
+ vfree(text);
return rc;
}
return;
if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
- if (netif_running(bp->dev)) {
- val = BNX2_DRV_ACK_CAP_SIGNATURE |
- BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
- REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
- val);
- }
bp->phy_flags |= REMOTE_PHY_CAP_FLAG;
val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
bp->phy_port = PORT_FIBRE;
else
bp->phy_port = PORT_TP;
+
+ if (netif_running(bp->dev)) {
+ u32 sig;
+
+ if (val & BNX2_LINK_STATUS_LINK_UP) {
+ bp->link_up = 1;
+ netif_carrier_on(bp->dev);
+ } else {
+ bp->link_up = 0;
+ netif_carrier_off(bp->dev);
+ }
+ sig = BNX2_DRV_ACK_CAP_SIGNATURE |
+ BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
+ sig);
+ }
}
}
{
u32 val;
int i, rc = 0;
+ u8 old_port;
/* Wait for the current PCI transaction to complete before
* issuing a reset. */
return rc;
spin_lock_bh(&bp->phy_lock);
+ old_port = bp->phy_port;
bnx2_init_remote_phy(bp);
- if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ if ((bp->phy_flags & REMOTE_PHY_CAP_FLAG) && old_port != bp->phy_port)
bnx2_set_default_remote_link(bp);
spin_unlock_bh(&bp->phy_lock);
bnx2_set_mac_loopback(bp);
}
else if (loopback_mode == BNX2_PHY_LOOPBACK) {
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return 0;
+
bp->loopback = PHY_LOOPBACK;
bnx2_set_phy_loopback(bp);
}
{
u32 bmsr;
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+ if (bp->link_up)
+ return 0;
+ return -ENODEV;
+ }
spin_lock_bh(&bp->phy_lock);
bnx2_enable_bmsr1(bp);
bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
if (i != 2)
bp->fw_version[j++] = '.';
}
- if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
- BNX2_PORT_FEATURE_ASF_ENABLED) {
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE);
+ if (reg & BNX2_PORT_FEATURE_WOL_ENABLED)
+ bp->wol = 1;
+
+ if (reg & BNX2_PORT_FEATURE_ASF_ENABLED) {
bp->flags |= ASF_ENABLE_FLAG;
for (i = 0; i < 30; i++) {
bp->phy_port = PORT_TP;
if (bp->phy_flags & PHY_SERDES_FLAG) {
bp->phy_port = PORT_FIBRE;
- bp->flags |= NO_WOL_FLAG;
+ reg = REG_RD_IND(bp, bp->shmem_base +
+ BNX2_SHARED_HW_CFG_CONFIG);
+ if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) {
+ bp->flags |= NO_WOL_FLAG;
+ bp->wol = 0;
+ }
if (CHIP_NUM(bp) != CHIP_NUM_5706) {
bp->phy_addr = 2;
- reg = REG_RD_IND(bp, bp->shmem_base +
- BNX2_SHARED_HW_CFG_CONFIG);
if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
}
if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
(CHIP_ID(bp) == CHIP_ID_5708_B0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B1))
+ (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
bp->flags |= NO_WOL_FLAG;
+ bp->wol = 0;
+ }
if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
bp->tx_quick_cons_trip_int =