diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/cnic.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/cnic.c | 668 |
1 files changed, 410 insertions, 258 deletions
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 818a573669e..8244e2b14bb 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -1,6 +1,6 @@ /* cnic.c: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2011 Broadcom Corporation + * Copyright (c) 2006-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,20 +40,23 @@ #include <net/ip6_checksum.h> #include <scsi/iscsi_if.h> +#define BCM_CNIC 1 #include "cnic_if.h" #include "bnx2.h" +#include "bnx2x/bnx2x.h" #include "bnx2x/bnx2x_reg.h" #include "bnx2x/bnx2x_fw_defs.h" #include "bnx2x/bnx2x_hsi.h" #include "../../../scsi/bnx2i/57xx_iscsi_constants.h" #include "../../../scsi/bnx2i/57xx_iscsi_hsi.h" +#include "../../../scsi/bnx2fc/bnx2fc_constants.h" #include "cnic.h" #include "cnic_defs.h" -#define DRV_MODULE_NAME "cnic" +#define CNIC_MODULE_NAME "cnic" -static char version[] __devinitdata = - "Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n"; +static char version[] = + "Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) " "Chen (zongxi@broadcom.com"); @@ -255,11 +258,16 @@ static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg) struct cnic_local *cp = dev->cnic_priv; struct cnic_eth_dev *ethdev = cp->ethdev; struct drv_ctl_info info; + struct fcoe_capabilities *fcoe_cap = + &info.data.register_data.fcoe_features; - if (reg) + if (reg) { info.cmd = DRV_CTL_ULP_REGISTER_CMD; - else + if (ulp_type == CNIC_ULP_FCOE && dev->fcoe_cap) + memcpy(fcoe_cap, dev->fcoe_cap, sizeof(*fcoe_cap)); + } else { info.cmd = DRV_CTL_ULP_UNREGISTER_CMD; + } info.data.ulp_type = ulp_type; ethdev->drv_ctl(dev->netdev, &info); @@ -285,6 +293,9 @@ static int cnic_get_l5_cid(struct cnic_local *cp, u32 cid, u32 *l5_cid) { u32 i; + if (!cp->ctx_tbl) + return -EINVAL; + for (i = 0; i < cp->max_cid_space; i++) { if (cp->ctx_tbl[i].cid == cid) { *l5_cid = i; @@ -331,7 +342,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type, while (retry < 3) { rc = 0; rcu_read_lock(); - ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]); + ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]); if (ulp_ops) rc = ulp_ops->iscsi_nl_send_msg( cp->ulp_handle[CNIC_ULP_ISCSI], @@ -380,7 +391,9 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type, if (cnic_in_use(csk) && test_bit(SK_F_CONNECT_START, &csk->flags)) { - memcpy(csk->ha, path_resp->mac_addr, 6); + csk->vlan_id = path_resp->vlan_id; + + memcpy(csk->ha, path_resp->mac_addr, ETH_ALEN); if (test_bit(SK_F_IPV6, &csk->flags)) memcpy(&csk->src_ip[0], &path_resp->src.v6_addr, sizeof(struct in6_addr)); @@ -423,7 +436,7 @@ static int cnic_offld_prep(struct cnic_sock *csk) static int cnic_close_prep(struct cnic_sock *csk) { clear_bit(SK_F_CONNECT_START, &csk->flags); - smp_mb__after_clear_bit(); + smp_mb__after_atomic(); if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) { while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags)) @@ -437,7 +450,7 @@ static int cnic_close_prep(struct cnic_sock *csk) static int cnic_abort_prep(struct cnic_sock *csk) { clear_bit(SK_F_CONNECT_START, &csk->flags); - smp_mb__after_clear_bit(); + smp_mb__after_atomic(); while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags)) msleep(1); @@ -531,7 +544,8 @@ int cnic_unregister_driver(int ulp_type) } if (atomic_read(&ulp_ops->ref_count) != 0) - netdev_warn(dev->netdev, "Failed waiting for ref count to go to zero\n"); + pr_warn("%s: Failed waiting for ref count to go to zero\n", + __func__); return 0; out_unlock: @@ -594,6 +608,10 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) pr_err("%s: Bad type %d\n", __func__, ulp_type); return -EINVAL; } + + if (ulp_type == CNIC_ULP_ISCSI) + cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + mutex_lock(&cnic_lock); if (rcu_dereference(cp->ulp_ops[ulp_type])) { RCU_INIT_POINTER(cp->ulp_ops[ulp_type], NULL); @@ -606,8 +624,8 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) } mutex_unlock(&cnic_lock); - if (ulp_type == CNIC_ULP_ISCSI) - cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); + if (ulp_type == CNIC_ULP_FCOE) + dev->fcoe_cap = NULL; synchronize_rcu(); @@ -710,7 +728,7 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma) for (i = 0; i < dma->num_pages; i++) { if (dma->pg_arr[i]) { - dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE, + dma_free_coherent(&dev->pcidev->dev, CNIC_PAGE_SIZE, dma->pg_arr[i], dma->pg_map_arr[i]); dma->pg_arr[i] = NULL; } @@ -769,7 +787,7 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma, for (i = 0; i < pages; i++) { dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev, - BCM_PAGE_SIZE, + CNIC_PAGE_SIZE, &dma->pg_map_arr[i], GFP_ATOMIC); if (dma->pg_arr[i] == NULL) @@ -778,8 +796,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma, if (!use_pg_tbl) return 0; - dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) & - ~(BCM_PAGE_SIZE - 1); + dma->pgtbl_size = ((pages * 8) + CNIC_PAGE_SIZE - 1) & + ~(CNIC_PAGE_SIZE - 1); dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size, &dma->pgtbl_map, GFP_ATOMIC); if (dma->pgtbl == NULL) @@ -809,10 +827,8 @@ static void cnic_free_context(struct cnic_dev *dev) } } -static void __cnic_free_uio(struct cnic_uio_dev *udev) +static void __cnic_free_uio_rings(struct cnic_uio_dev *udev) { - uio_unregister_device(&udev->cnic_uinfo); - if (udev->l2_buf) { dma_free_coherent(&udev->pdev->dev, udev->l2_buf_size, udev->l2_buf, udev->l2_buf_map); @@ -825,6 +841,14 @@ static void __cnic_free_uio(struct cnic_uio_dev *udev) udev->l2_ring = NULL; } +} + +static void __cnic_free_uio(struct cnic_uio_dev *udev) +{ + uio_unregister_device(&udev->cnic_uinfo); + + __cnic_free_uio_rings(udev); + pci_dev_put(udev->pdev); kfree(udev); } @@ -848,6 +872,8 @@ static void cnic_free_resc(struct cnic_dev *dev) if (udev) { udev->dev = NULL; cp->udev = NULL; + if (udev->uio_dev == -1) + __cnic_free_uio_rings(udev); } cnic_free_context(dev); @@ -873,11 +899,11 @@ static int cnic_alloc_context(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - if (CHIP_NUM(cp) == CHIP_NUM_5709) { + if (BNX2_CHIP(cp) == BNX2_CHIP_5709) { int i, k, arr_size; - cp->ctx_blk_size = BCM_PAGE_SIZE; - cp->cids_per_blk = BCM_PAGE_SIZE / 128; + cp->ctx_blk_size = CNIC_PAGE_SIZE; + cp->cids_per_blk = CNIC_PAGE_SIZE / 128; arr_size = BNX2_MAX_CID / cp->cids_per_blk * sizeof(struct cnic_ctx); cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL); @@ -909,7 +935,7 @@ static int cnic_alloc_context(struct cnic_dev *dev) for (i = 0; i < cp->ctx_blks; i++) { cp->ctx_arr[i].ctx = dma_alloc_coherent(&dev->pcidev->dev, - BCM_PAGE_SIZE, + CNIC_PAGE_SIZE, &cp->ctx_arr[i].mapping, GFP_KERNEL); if (cp->ctx_arr[i].ctx == NULL) @@ -982,21 +1008,50 @@ static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info, return 0; } +static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages) +{ + struct cnic_local *cp = udev->dev->cnic_priv; + + if (udev->l2_ring) + return 0; + + udev->l2_ring_size = pages * CNIC_PAGE_SIZE; + udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size, + &udev->l2_ring_map, + GFP_KERNEL | __GFP_COMP); + if (!udev->l2_ring) + return -ENOMEM; + + udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size; + udev->l2_buf_size = CNIC_PAGE_ALIGN(udev->l2_buf_size); + udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size, + &udev->l2_buf_map, + GFP_KERNEL | __GFP_COMP); + if (!udev->l2_buf) { + __cnic_free_uio_rings(udev); + return -ENOMEM; + } + + return 0; + +} + static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages) { struct cnic_local *cp = dev->cnic_priv; struct cnic_uio_dev *udev; - read_lock(&cnic_dev_lock); list_for_each_entry(udev, &cnic_udev_list, list) { if (udev->pdev == dev->pcidev) { udev->dev = dev; + if (__cnic_alloc_uio_rings(udev, pages)) { + udev->dev = NULL; + return -ENOMEM; + } cp->udev = udev; - read_unlock(&cnic_dev_lock); return 0; } } - read_unlock(&cnic_dev_lock); udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC); if (!udev) @@ -1006,33 +1061,18 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages) udev->dev = dev; udev->pdev = dev->pcidev; - udev->l2_ring_size = pages * BCM_PAGE_SIZE; - udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size, - &udev->l2_ring_map, - GFP_KERNEL | __GFP_COMP); - if (!udev->l2_ring) - goto err_udev; - udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size; - udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size); - udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size, - &udev->l2_buf_map, - GFP_KERNEL | __GFP_COMP); - if (!udev->l2_buf) - goto err_dma; + if (__cnic_alloc_uio_rings(udev, pages)) + goto err_udev; - write_lock(&cnic_dev_lock); list_add(&udev->list, &cnic_udev_list); - write_unlock(&cnic_dev_lock); pci_dev_get(udev->pdev); cp->udev = udev; return 0; - err_dma: - dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size, - udev->l2_ring, udev->l2_ring_map); + err_udev: kfree(udev); return -ENOMEM; @@ -1050,14 +1090,15 @@ static int cnic_init_uio(struct cnic_dev *dev) uinfo = &udev->cnic_uinfo; - uinfo->mem[0].addr = dev->netdev->base_addr; + uinfo->mem[0].addr = pci_resource_start(dev->pcidev, 0); uinfo->mem[0].internal_addr = dev->regview; - uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start; uinfo->mem[0].memtype = UIO_MEM_PHYS; if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) { + uinfo->mem[0].size = MB_GET_CID_ADDR(TX_TSS_CID + + TX_MAX_TSS_RINGS + 1); uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen & - PAGE_MASK; + CNIC_PAGE_MASK; if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9; else @@ -1065,8 +1106,10 @@ static int cnic_init_uio(struct cnic_dev *dev) uinfo->name = "bnx2_cnic"; } else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) { + uinfo->mem[0].size = pci_resource_len(dev->pcidev, 0); + uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk & - PAGE_MASK; + CNIC_PAGE_MASK; uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk); uinfo->name = "bnx2x_cnic"; @@ -1137,6 +1180,7 @@ error: static int cnic_alloc_bnx2x_context(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); int ctx_blk_size = cp->ethdev->ctx_blk_size; int total_mem, blks, i; @@ -1154,7 +1198,7 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev) cp->ctx_blks = blks; cp->ctx_blk_size = ctx_blk_size; - if (!BNX2X_CHIP_IS_57710(cp->chip_id)) + if (!CHIP_IS_E1(bp)) cp->ctx_align = 0; else cp->ctx_align = ctx_blk_size; @@ -1184,18 +1228,17 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev) static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_eth_dev *ethdev = cp->ethdev; u32 start_cid = ethdev->starting_cid; int i, j, n, ret, pages; struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info; - cp->iro_arr = ethdev->iro_arr; - cp->max_cid_space = MAX_ISCSI_TBL_SZ; cp->iscsi_start_cid = start_cid; cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { cp->max_cid_space += dev->max_fcoe_conn; cp->fcoe_init_cid = ethdev->fcoe_init_cid; if (!cp->fcoe_init_cid) @@ -1220,14 +1263,14 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) for (i = MAX_ISCSI_TBL_SZ; i < cp->max_cid_space; i++) cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_FCOE; - pages = PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) / - PAGE_SIZE; + pages = CNIC_PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) / + CNIC_PAGE_SIZE; ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0); if (ret) return -ENOMEM; - n = PAGE_SIZE / CNIC_KWQ16_DATA_SIZE; + n = CNIC_PAGE_SIZE / CNIC_KWQ16_DATA_SIZE; for (i = 0, j = 0; i < cp->max_cid_space; i++) { long off = CNIC_KWQ16_DATA_SIZE * (i % n); @@ -1243,13 +1286,13 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) if (ret) goto error; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + if (CNIC_SUPPORTS_FCOE(bp)) { ret = cnic_alloc_kcq(dev, &cp->kcq2, true); if (ret) goto error; } - pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE; + pages = CNIC_PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / CNIC_PAGE_SIZE; ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0); if (ret) goto error; @@ -1258,6 +1301,9 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) if (ret) goto error; + if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI) + return 0; + cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk; cp->l2_rx_ring_size = 15; @@ -1334,6 +1380,7 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid, u32 type, union l5cm_specific_data *l5_data) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct l5cm_spe kwqe; struct kwqe_16 *kwq[1]; u16 type_16; @@ -1341,10 +1388,10 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid, kwqe.hdr.conn_and_cmd_data = cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) | - BNX2X_HW_CID(cp, cid))); + BNX2X_HW_CID(bp, cid))); type_16 = (type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE; - type_16 |= (cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) & + type_16 |= (bp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) & SPE_HDR_FUNCTION_ID; kwqe.hdr.type = cpu_to_le16(type_16); @@ -1379,12 +1426,34 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type, rcu_read_unlock(); } +static void cnic_bnx2x_set_tcp_options(struct cnic_dev *dev, int time_stamps, + int en_tcp_dack) +{ + struct bnx2x *bp = netdev_priv(dev->netdev); + u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN; + u16 tstorm_flags = 0; + + if (time_stamps) { + xstorm_flags |= XSTORM_L5CM_TCP_FLAGS_TS_ENABLED; + tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_TS_ENABLED; + } + if (en_tcp_dack) + tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_DELAYED_ACK_EN; + + CNIC_WR8(dev, BAR_XSTRORM_INTMEM + + XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(bp->pfid), xstorm_flags); + + CNIC_WR16(dev, BAR_TSTRORM_INTMEM + + TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(bp->pfid), tstorm_flags); +} + static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe; int hq_bds, pages; - u32 pfid = cp->pfid; + u32 pfid = bp->pfid; cp->num_iscsi_tasks = req1->num_tasks_per_conn; cp->num_ccells = req1->num_ccells_per_conn; @@ -1393,8 +1462,8 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) cp->r2tq_size = cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS * BNX2X_ISCSI_R2TQE_SIZE; cp->hq_size = cp->num_ccells * BNX2X_ISCSI_HQ_BD_SIZE; - pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE; - hq_bds = pages * (PAGE_SIZE / BNX2X_ISCSI_HQ_BD_SIZE); + pages = CNIC_PAGE_ALIGN(cp->hq_size) / CNIC_PAGE_SIZE; + hq_bds = pages * (CNIC_PAGE_SIZE / BNX2X_ISCSI_HQ_BD_SIZE); cp->num_cqs = req1->num_cqs; if (!dev->max_iscsi_conn) @@ -1404,9 +1473,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(pfid), req1->rq_num_wqes); CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid), - PAGE_SIZE); + CNIC_PAGE_SIZE); CNIC_WR8(dev, BAR_TSTRORM_INTMEM + - TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT); + TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS); CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid), req1->num_tasks_per_conn); @@ -1416,9 +1485,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfid), req1->rq_buffer_size); CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(pfid), - PAGE_SIZE); + CNIC_PAGE_SIZE); CNIC_WR8(dev, BAR_USTRORM_INTMEM + - USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT); + USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS); CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid), req1->num_tasks_per_conn); @@ -1431,9 +1500,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) /* init Xstorm RAM */ CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid), - PAGE_SIZE); + CNIC_PAGE_SIZE); CNIC_WR8(dev, BAR_XSTRORM_INTMEM + - XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT); + XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS); CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid), req1->num_tasks_per_conn); @@ -1446,9 +1515,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) /* init Cstorm RAM */ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid), - PAGE_SIZE); + CNIC_PAGE_SIZE); CNIC_WR8(dev, BAR_CSTRORM_INTMEM + - CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT); + CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS); CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid), req1->num_tasks_per_conn); @@ -1457,14 +1526,18 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(pfid), hq_bds); + cnic_bnx2x_set_tcp_options(dev, + req1->flags & ISCSI_KWQE_INIT1_TIME_STAMPS_ENABLE, + req1->flags & ISCSI_KWQE_INIT1_DELAYED_ACK_ENABLE); + return 0; } static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe) { struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe; - struct cnic_local *cp = dev->cnic_priv; - u32 pfid = cp->pfid; + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 pfid = bp->pfid; struct iscsi_kcqe kcqe; struct kcqe *cqes[1]; @@ -1546,18 +1619,18 @@ static int cnic_alloc_bnx2x_conn_resc(struct cnic_dev *dev, u32 l5_cid) } ctx->cid = cid; - pages = PAGE_ALIGN(cp->task_array_size) / PAGE_SIZE; + pages = CNIC_PAGE_ALIGN(cp->task_array_size) / CNIC_PAGE_SIZE; ret = cnic_alloc_dma(dev, &iscsi->task_array_info, pages, 1); if (ret) goto error; - pages = PAGE_ALIGN(cp->r2tq_size) / PAGE_SIZE; + pages = CNIC_PAGE_ALIGN(cp->r2tq_size) / CNIC_PAGE_SIZE; ret = cnic_alloc_dma(dev, &iscsi->r2tq_info, pages, 1); if (ret) goto error; - pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE; + pages = CNIC_PAGE_ALIGN(cp->hq_size) / CNIC_PAGE_SIZE; ret = cnic_alloc_dma(dev, &iscsi->hq_info, pages, 1); if (ret) goto error; @@ -1603,6 +1676,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[], u32 num) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct iscsi_kwqe_conn_offload1 *req1 = (struct iscsi_kwqe_conn_offload1 *) wqes[0]; struct iscsi_kwqe_conn_offload2 *req2 = @@ -1611,11 +1685,11 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[], struct cnic_context *ctx = &cp->ctx_tbl[req1->iscsi_conn_id]; struct cnic_iscsi *iscsi = ctx->proto.iscsi; u32 cid = ctx->cid; - u32 hw_cid = BNX2X_HW_CID(cp, cid); + u32 hw_cid = BNX2X_HW_CID(bp, cid); struct iscsi_context *ictx; struct regpair context_addr; int i, j, n = 2, n_max; - u8 port = CNIC_PORT(cp); + u8 port = BP_PORT(bp); ctx->ctx_flags = 0; if (!req2->num_additional_wqes) @@ -1669,8 +1743,8 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[], XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T; ictx->xstorm_st_context.common.ethernet.reserved_vlan_type = ETH_P_8021Q; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) && - cp->port_mode == CHIP_2_PORT_MODE) { + if (BNX2X_CHIP_IS_E2_PLUS(bp) && + bp->common.chip_port_mode == CHIP_2_PORT_MODE) { port = 0; } @@ -1682,7 +1756,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[], ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE; /* TSTORM requires the base address of RQ DB & not PTE */ ictx->tstorm_st_context.iscsi.rq_db_phy_addr.lo = - req2->rq_page_table_addr_lo & PAGE_MASK; + req2->rq_page_table_addr_lo & CNIC_PAGE_MASK; ictx->tstorm_st_context.iscsi.rq_db_phy_addr.hi = req2->rq_page_table_addr_hi; ictx->tstorm_st_context.iscsi.iscsi_conn_id = req1->iscsi_conn_id; @@ -1764,7 +1838,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[], /* CSTORM and USTORM initialization is different, CSTORM requires * CQ DB base & not PTE addr */ ictx->cstorm_st_context.cq_db_base.lo = - req1->cq_page_table_addr_lo & PAGE_MASK; + req1->cq_page_table_addr_lo & CNIC_PAGE_MASK; ictx->cstorm_st_context.cq_db_base.hi = req1->cq_page_table_addr_hi; ictx->cstorm_st_context.iscsi_conn_id = req1->iscsi_conn_id; ictx->cstorm_st_context.cq_proc_en_bit_map = (1 << cp->num_cqs) - 1; @@ -1791,6 +1865,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], struct iscsi_kwqe_conn_offload1 *req1; struct iscsi_kwqe_conn_offload2 *req2; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_context *ctx; struct iscsi_kcqe kcqe; struct kcqe *cqes[1]; @@ -1844,7 +1919,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], } kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS; - kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp, cp->ctx_tbl[l5_cid].cid); + kcqe.iscsi_conn_context_id = BNX2X_HW_CID(bp, cp->ctx_tbl[l5_cid].cid); done: cqes[0] = (struct kcqe *) &kcqe; @@ -1880,6 +1955,7 @@ static int cnic_bnx2x_iscsi_update(struct cnic_dev *dev, struct kwqe *kwqe) static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; union l5cm_specific_data l5_data; int ret; @@ -1888,7 +1964,7 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid) init_waitqueue_head(&ctx->waitq); ctx->wait_cond = 0; memset(&l5_data, 0, sizeof(l5_data)); - hw_cid = BNX2X_HW_CID(cp, ctx->cid); + hw_cid = BNX2X_HW_CID(bp, ctx->cid); ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL, hw_cid, NONE_CONNECTION_TYPE, &l5_data); @@ -1985,9 +2061,6 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev, xstorm_buf->pseudo_header_checksum = swab16(~csum_ipv6_magic(&src_ip, &dst_ip, 0, IPPROTO_TCP, 0)); - if (!(kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK)) - tstorm_buf->params |= - L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE; if (kwqe3->ka_timeout) { tstorm_buf->ka_enable = 1; tstorm_buf->ka_timeout = kwqe3->ka_timeout; @@ -1999,8 +2072,8 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev, static void cnic_init_bnx2x_mac(struct cnic_dev *dev) { - struct cnic_local *cp = dev->cnic_priv; - u32 pfid = cp->pfid; + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 pfid = bp->pfid; u8 *mac = dev->mac_addr; CNIC_WR8(dev, BAR_XSTRORM_INTMEM + @@ -2033,28 +2106,11 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev) mac[0]); } -static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts) -{ - struct cnic_local *cp = dev->cnic_priv; - u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN; - u16 tstorm_flags = 0; - - if (tcp_ts) { - xstorm_flags |= XSTORM_L5CM_TCP_FLAGS_TS_ENABLED; - tstorm_flags |= TSTORM_L5CM_TCP_FLAGS_TS_ENABLED; - } - - CNIC_WR8(dev, BAR_XSTRORM_INTMEM + - XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags); - - CNIC_WR16(dev, BAR_TSTRORM_INTMEM + - TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags); -} - static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[], u32 num, int *work) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct l4_kwq_connect_req1 *kwqe1 = (struct l4_kwq_connect_req1 *) wqes[0]; struct l4_kwq_connect_req3 *kwqe3; @@ -2123,10 +2179,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[], cnic_init_storm_conn_bufs(dev, kwqe1, kwqe3, conn_buf); CNIC_WR16(dev, BAR_XSTRORM_INTMEM + - XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id); - - cnic_bnx2x_set_tcp_timestamp(dev, - kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_TIME_STAMP); + XSTORM_ISCSI_LOCAL_VLAN_OFFSET(bp->pfid), csk->vlan_id); ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT, kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data); @@ -2195,11 +2248,12 @@ static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe) struct fcoe_stat_ramrod_params *fcoe_stat; union l5cm_specific_data l5_data; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); int ret; u32 cid; req = (struct fcoe_kwqe_stat *) kwqe; - cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid); + cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid); fcoe_stat = cnic_get_kwqe_16_data(cp, BNX2X_FCOE_L5_CID_BASE, &l5_data); if (!fcoe_stat) @@ -2218,6 +2272,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[], { int ret; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 cid; struct fcoe_init_ramrod_params *fcoe_init; struct fcoe_kwqe_init1 *req1; @@ -2262,7 +2317,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[], fcoe_init->sb_id = HC_INDEX_FCOE_EQ_CONS; cp->kcq2.sw_prod_idx = 0; - cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid); + cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid); ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid, FCOE_CONNECTION_TYPE, &l5_data); *work = 3; @@ -2275,6 +2330,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], int ret = 0; u32 cid = -1, l5_cid; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct fcoe_kwqe_conn_offload1 *req1; struct fcoe_kwqe_conn_offload2 *req2; struct fcoe_kwqe_conn_offload3 *req3; @@ -2317,7 +2373,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], fctx = cnic_get_bnx2x_ctx(dev, cid, 1, &ctx_addr); if (fctx) { - u32 hw_cid = BNX2X_HW_CID(cp, cid); + u32 hw_cid = BNX2X_HW_CID(bp, cid); u32 val; val = CDU_RSRVD_VALUE_TYPE_A(hw_cid, CDU_REGION_NUMBER_XCM_AG, @@ -2341,7 +2397,7 @@ static int cnic_bnx2x_fcoe_ofld1(struct cnic_dev *dev, struct kwqe *wqes[], memcpy(&fcoe_offload->offload_kwqe3, req3, sizeof(*req3)); memcpy(&fcoe_offload->offload_kwqe4, req4, sizeof(*req4)); - cid = BNX2X_HW_CID(cp, cid); + cid = BNX2X_HW_CID(bp, cid); ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_OFFLOAD_CONN, cid, FCOE_CONNECTION_TYPE, &l5_data); if (!ret) @@ -2499,13 +2555,14 @@ static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe) struct fcoe_kwqe_destroy *req; union l5cm_specific_data l5_data; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); int ret; u32 cid; cnic_bnx2x_delete_wait(dev, MAX_ISCSI_TBL_SZ); req = (struct fcoe_kwqe_destroy *) kwqe; - cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid); + cid = BNX2X_HW_CID(bp, cp->fcoe_init_cid); memset(&l5_data, 0, sizeof(l5_data)); ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid, @@ -2521,25 +2578,47 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe) u32 cid; u32 opcode = KWQE_OPCODE(kwqe->kwqe_op_flag); u32 layer_code = kwqe->kwqe_op_flag & KWQE_LAYER_MASK; + u32 kcqe_op; int ulp_type; cid = kwqe->kwqe_info0; memset(&kcqe, 0, sizeof(kcqe)); - if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) { + if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_FCOE) { + u32 l5_cid = 0; + + ulp_type = CNIC_ULP_FCOE; + if (opcode == FCOE_KWQE_OPCODE_DISABLE_CONN) { + struct fcoe_kwqe_conn_enable_disable *req; + + req = (struct fcoe_kwqe_conn_enable_disable *) kwqe; + kcqe_op = FCOE_KCQE_OPCODE_DISABLE_CONN; + cid = req->context_id; + l5_cid = req->conn_id; + } else if (opcode == FCOE_KWQE_OPCODE_DESTROY) { + kcqe_op = FCOE_KCQE_OPCODE_DESTROY_FUNC; + } else { + return; + } + kcqe.kcqe_op_flag = kcqe_op << KCQE_FLAGS_OPCODE_SHIFT; + kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_FCOE; + kcqe.kcqe_info1 = FCOE_KCQE_COMPLETION_STATUS_PARITY_ERROR; + kcqe.kcqe_info2 = cid; + kcqe.kcqe_info0 = l5_cid; + + } else if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) { ulp_type = CNIC_ULP_ISCSI; if (opcode == ISCSI_KWQE_OPCODE_UPDATE_CONN) cid = kwqe->kwqe_info1; kcqe.kcqe_op_flag = (opcode + 0x10) << KCQE_FLAGS_OPCODE_SHIFT; kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_ISCSI; - kcqe.kcqe_info1 = ISCSI_KCQE_COMPLETION_STATUS_NIC_ERROR; + kcqe.kcqe_info1 = ISCSI_KCQE_COMPLETION_STATUS_PARITY_ERR; kcqe.kcqe_info2 = cid; cnic_get_l5_cid(cp, BNX2X_SW_CID(cid), &kcqe.kcqe_info0); } else if (layer_code == KWQE_FLAGS_LAYER_MASK_L4) { struct l4_kcq *l4kcqe = (struct l4_kcq *) &kcqe; - u32 kcqe_op; ulp_type = CNIC_ULP_L4; if (opcode == L4_KWQE_OPCODE_VALUE_CONNECT1) @@ -2553,14 +2632,14 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe) kcqe.kcqe_op_flag = (kcqe_op << KCQE_FLAGS_OPCODE_SHIFT) | KCQE_FLAGS_LAYER_MASK_L4; - l4kcqe->status = L4_KCQE_COMPLETION_STATUS_NIC_ERROR; + l4kcqe->status = L4_KCQE_COMPLETION_STATUS_PARITY_ERROR; l4kcqe->cid = cid; cnic_get_l5_cid(cp, BNX2X_SW_CID(cid), &l4kcqe->conn_id); } else { return; } - cqes[0] = (struct kcqe *) &kcqe; + cqes[0] = &kcqe; cnic_reply_bnx2x_kcqes(dev, ulp_type, cqes, 1); } @@ -2640,7 +2719,7 @@ static int cnic_submit_bnx2x_iscsi_kwqes(struct cnic_dev *dev, static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev, struct kwqe *wqes[], u32 num_wqes) { - struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); int i, work, ret; u32 opcode; struct kwqe *kwqe; @@ -2648,7 +2727,7 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev, if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) return -EAGAIN; /* bnx2 is down */ - if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) + if (!BNX2X_CHIP_IS_E2_PLUS(bp)) return -EINVAL; for (i = 0; i < num_wqes; ) { @@ -2686,9 +2765,17 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev, opcode); break; } - if (ret < 0) + if (ret < 0) { netdev_err(dev->netdev, "KWQE(0x%x) failed\n", opcode); + + /* Possibly bnx2x parity error, send completion + * to ulp drivers with error code to speed up + * cleanup and reset recovery. + */ + if (ret == -EIO || ret == -EAGAIN) + cnic_bnx2x_kwqe_err(dev, kwqe); + } i += work; } return 0; @@ -2820,7 +2907,7 @@ static int cnic_l2_completion(struct cnic_local *cp) u16 hw_cons, sw_cons; struct cnic_uio_dev *udev = cp->udev; union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (udev->l2_ring + (2 * CNIC_PAGE_SIZE)); u32 cmd; int comp = 0; @@ -2956,8 +3043,8 @@ static irqreturn_t cnic_irq(int irq, void *dev_instance) static inline void cnic_ack_bnx2x_int(struct cnic_dev *dev, u8 id, u8 storm, u16 index, u8 op, u8 update) { - struct cnic_local *cp = dev->cnic_priv; - u32 hc_addr = (HC_REG_COMMAND_REG + CNIC_PORT(cp) * 32 + + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp) * 32 + COMMAND_REG_INT_ACK); struct igu_ack_register igu_ack; @@ -3003,6 +3090,22 @@ static void cnic_ack_bnx2x_e2_msix(struct cnic_dev *dev) IGU_INT_DISABLE, 0); } +static void cnic_arm_bnx2x_msix(struct cnic_dev *dev, u32 idx) +{ + struct cnic_local *cp = dev->cnic_priv; + + cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, CSTORM_ID, idx, + IGU_INT_ENABLE, 1); +} + +static void cnic_arm_bnx2x_e2_msix(struct cnic_dev *dev, u32 idx) +{ + struct cnic_local *cp = dev->cnic_priv; + + cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, idx, + IGU_INT_ENABLE, 1); +} + static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) { u32 last_status = *info->status_idx_ptr; @@ -3028,6 +3131,7 @@ static void cnic_service_bnx2x_bh(unsigned long data) { struct cnic_dev *dev = (struct cnic_dev *) data; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 status_idx, new_status_idx; if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) @@ -3039,9 +3143,8 @@ static void cnic_service_bnx2x_bh(unsigned long data) CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); - if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { - cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, - status_idx, IGU_INT_ENABLE, 1); + if (!CNIC_SUPPORTS_FCOE(bp)) { + cp->arm_int(dev, status_idx); break; } @@ -3137,7 +3240,8 @@ static int cnic_copy_ulp_stats(struct cnic_dev *dev, int ulp_type) int rc; mutex_lock(&cnic_lock); - ulp_ops = cnic_ulp_tbl_prot(ulp_type); + ulp_ops = rcu_dereference_protected(cp->ulp_ops[ulp_type], + lockdep_is_held(&cnic_lock)); if (ulp_ops && ulp_ops->cnic_get_stats) rc = ulp_ops->cnic_get_stats(cp->ulp_handle[ulp_type]); else @@ -3180,6 +3284,9 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) u32 l5_cid; struct cnic_local *cp = dev->cnic_priv; + if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) + break; + if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) { struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; @@ -3502,6 +3609,7 @@ static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid, csk1->rcv_buf = DEF_RCV_BUF; csk1->snd_buf = DEF_SND_BUF; csk1->seed = DEF_SEED; + csk1->tcp_flags = 0; *csk = csk1; return 0; @@ -3534,7 +3642,7 @@ static int cnic_cm_destroy(struct cnic_sock *csk) csk_hold(csk); clear_bit(SK_F_INUSE, &csk->flags); - smp_mb__after_clear_bit(); + smp_mb__after_atomic(); while (atomic_read(&csk->ref_count) != 1) msleep(1); cnic_cm_cleanup(csk); @@ -3757,12 +3865,17 @@ static int cnic_cm_abort(struct cnic_sock *csk) return cnic_cm_abort_req(csk); /* Getting here means that we haven't started connect, or - * connect was not successful. + * connect was not successful, or it has been reset by the target. */ cp->close_conn(csk, opcode); - if (csk->state != opcode) + if (csk->state != opcode) { + /* Wait for remote reset sequence to complete */ + while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) + msleep(1); + return -EALREADY; + } return 0; } @@ -3776,6 +3889,10 @@ static int cnic_cm_close(struct cnic_sock *csk) csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP; return cnic_cm_close_req(csk); } else { + /* Wait for remote reset sequence to complete */ + while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) + msleep(1); + return -EALREADY; } return 0; @@ -3901,18 +4018,33 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE: if (l4kcqe->status == 0) set_bit(SK_F_OFFLD_COMPLETE, &csk->flags); + else if (l4kcqe->status == + L4_KCQE_COMPLETION_STATUS_PARITY_ERROR) + set_bit(SK_F_HW_ERR, &csk->flags); - smp_mb__before_clear_bit(); + smp_mb__before_atomic(); clear_bit(SK_F_OFFLD_SCHED, &csk->flags); cnic_cm_upcall(cp, csk, opcode); break; + case L5CM_RAMROD_CMD_ID_CLOSE: { + struct iscsi_kcqe *l5kcqe = (struct iscsi_kcqe *) kcqe; + + if (l4kcqe->status != 0 || l5kcqe->completion_status != 0) { + netdev_warn(dev->netdev, "RAMROD CLOSE compl with status 0x%x completion status 0x%x\n", + l4kcqe->status, l5kcqe->completion_status); + opcode = L4_KCQE_OPCODE_VALUE_CLOSE_COMP; + /* Fall through */ + } else { + break; + } + } case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED: case L4_KCQE_OPCODE_VALUE_CLOSE_COMP: case L4_KCQE_OPCODE_VALUE_RESET_COMP: case L5CM_RAMROD_CMD_ID_SEARCHER_DELETE: case L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD: - if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_NIC_ERROR) + if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_PARITY_ERROR) set_bit(SK_F_HW_ERR, &csk->flags); cp->close_conn(csk, opcode); @@ -3963,7 +4095,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev) if (!cp->csk_tbl) return -ENOMEM; - port_id = random32(); + port_id = prandom_u32(); port_id %= CNIC_LOCAL_PORT_RANGE; if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE, CNIC_LOCAL_PORT_MIN, port_id)) { @@ -4023,7 +4155,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev) { u32 seed; - seed = random32(); + seed = prandom_u32(); cnic_ctx_wr(dev, 45, 0, seed); return 0; } @@ -4091,12 +4223,12 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev) static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev) { - struct cnic_local *cp = dev->cnic_priv; - u32 pfid = cp->pfid; - u32 port = CNIC_PORT(cp); + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 pfid = bp->pfid; + u32 port = BP_PORT(bp); cnic_init_bnx2x_mac(dev); - cnic_bnx2x_set_tcp_timestamp(dev, 1); + cnic_bnx2x_set_tcp_options(dev, 0, 1); CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfid), 0); @@ -4210,8 +4342,6 @@ static int cnic_cm_shutdown(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; int i; - cp->stop_cm(dev); - if (!cp->csk_tbl) return 0; @@ -4243,7 +4373,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid) int ret = 0, i; u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0; - if (CHIP_NUM(cp) != CHIP_NUM_5709) + if (BNX2_CHIP(cp) != BNX2_CHIP_5709) return 0; for (i = 0; i < cp->ctx_blks; i++) { @@ -4251,7 +4381,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid) u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk; u32 val; - memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE); + memset(cp->ctx_arr[i].ctx, 0, CNIC_PAGE_SIZE); CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0, (cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit); @@ -4393,7 +4523,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) u32 cid_addr, tx_cid, sb_id; u32 val, offset0, offset1, offset2, offset3; int i; - struct tx_bd *txbd; + struct bnx2_tx_bd *txbd; dma_addr_t buf_map, ring_map = udev->l2_ring_map; struct status_block *s_blk = cp->status_blk.gen; @@ -4411,7 +4541,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) cp->tx_cons = *cp->tx_cons_ptr; cid_addr = GET_CID_ADDR(tx_cid); - if (CHIP_NUM(cp) == CHIP_NUM_5709) { + if (BNX2_CHIP(cp) == BNX2_CHIP_5709) { u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40; for (i = 0; i < PHY_CTX_SIZE; i += 4) @@ -4439,7 +4569,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) txbd = udev->l2_ring; buf_map = udev->l2_buf_map; - for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) { + for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i++, txbd++) { txbd->tx_bd_haddr_hi = (u64) buf_map >> 32; txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } @@ -4459,7 +4589,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) struct cnic_uio_dev *udev = cp->udev; u32 cid_addr, sb_id, val, coal_reg, coal_val; int i; - struct rx_bd *rxbd; + struct bnx2_rx_bd *rxbd; struct status_block *s_blk = cp->status_blk.gen; dma_addr_t ring_map = udev->l2_ring_map; @@ -4495,8 +4625,8 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id); cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val); - rxbd = udev->l2_ring + BCM_PAGE_SIZE; - for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { + rxbd = udev->l2_ring + CNIC_PAGE_SIZE; + for (i = 0; i < BNX2_MAX_RX_DESC_CNT; i++, rxbd++) { dma_addr_t buf_map; int n = (i % cp->l2_rx_ring_size) + 1; @@ -4506,11 +4636,11 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32; rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } - val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32; + val = (u64) (ring_map + CNIC_PAGE_SIZE) >> 32; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); rxbd->rx_bd_haddr_hi = val; - val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff; + val = (u64) (ring_map + CNIC_PAGE_SIZE) & 0xffffffff; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); rxbd->rx_bd_haddr_lo = val; @@ -4556,7 +4686,7 @@ static void cnic_set_bnx2_mac(struct cnic_dev *dev) CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val); val = 4 | BNX2_RPM_SORT_USER2_BC_EN; - if (CHIP_NUM(cp) != CHIP_NUM_5709) + if (BNX2_CHIP(cp) != BNX2_CHIP_5709) val |= BNX2_RPM_SORT_USER2_PROM_VLAN; CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0); @@ -4576,10 +4706,10 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) val = CNIC_RD(dev, BNX2_MQ_CONFIG); val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; - if (BCM_PAGE_BITS > 12) + if (CNIC_PAGE_BITS > 12) val |= (12 - 8) << 4; else - val |= (BCM_PAGE_BITS - 8) << 4; + val |= (CNIC_PAGE_BITS - 8) << 4; CNIC_WR(dev, BNX2_MQ_CONFIG, val); @@ -4602,20 +4732,20 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) cp->kwq_con_idx = 0; set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags); - if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708) + if (BNX2_CHIP(cp) == BNX2_CHIP_5706 || BNX2_CHIP(cp) == BNX2_CHIP_5708) cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15; else cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index; /* Initialize the kernel work queue context. */ val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE | - (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; + (CNIC_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val); - val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16; + val = (CNIC_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val); - val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT; + val = ((CNIC_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val); val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32); @@ -4629,19 +4759,19 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) cp->kcq1.sw_prod_idx = 0; cp->kcq1.hw_prod_idx_ptr = - (u16 *) &sblk->status_completion_producer_index; + &sblk->status_completion_producer_index; - cp->kcq1.status_idx_ptr = (u16 *) &sblk->status_idx; + cp->kcq1.status_idx_ptr = &sblk->status_idx; /* Initialize the kernel complete queue context. */ val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE | - (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; + (CNIC_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val); - val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16; + val = (CNIC_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val); - val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT; + val = ((CNIC_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val); val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32); @@ -4657,9 +4787,9 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id); cp->kcq1.hw_prod_idx_ptr = - (u16 *) &msblk->status_completion_producer_index; - cp->kcq1.status_idx_ptr = (u16 *) &msblk->status_idx; - cp->kwq_con_idx_ptr = (u16 *) &msblk->status_cmd_consumer_index; + &msblk->status_completion_producer_index; + cp->kcq1.status_idx_ptr = &msblk->status_idx; + cp->kwq_con_idx_ptr = &msblk->status_cmd_consumer_index; cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb); cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb); @@ -4695,6 +4825,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) return err; } + ethdev->drv_state |= CNIC_DRV_STATE_HANDLES_IRQ; + return 0; } @@ -4737,6 +4869,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev, u16 sb_id, u8 sb_index, u8 disable) { + struct bnx2x *bp = netdev_priv(dev->netdev); u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) + @@ -4754,6 +4887,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev, static void cnic_enable_bnx2x_int(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u8 sb_id = cp->status_blk_num; CNIC_WR8(dev, BAR_CSTRORM_INTMEM + @@ -4772,6 +4906,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, struct client_init_ramrod_data *data) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_uio_dev *udev = cp->udev; union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring; dma_addr_t buf_map, ring_map = udev->l2_ring_map; @@ -4780,11 +4915,14 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, u32 cli = cp->ethdev->iscsi_l2_client_id; u32 val; - memset(txbd, 0, BCM_PAGE_SIZE); + memset(txbd, 0, CNIC_PAGE_SIZE); buf_map = udev->l2_buf_map; - for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) { + for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i += 3, txbd += 3) { struct eth_tx_start_bd *start_bd = &txbd->start_bd; + struct eth_tx_parse_bd_e1x *pbd_e1x = + &((txbd + 1)->parse_bd_e1x); + struct eth_tx_parse_bd_e2 *pbd_e2 = &((txbd + 1)->parse_bd_e2); struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd); start_bd->addr_hi = cpu_to_le32((u64) buf_map >> 32); @@ -4794,10 +4932,15 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, start_bd->nbytes = cpu_to_le16(0x10); start_bd->nbd = cpu_to_le16(3); start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; - start_bd->general_data = (UNICAST_ADDRESS << - ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT); + start_bd->general_data &= ~ETH_TX_START_BD_PARSE_NBDS; start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT); + if (BNX2X_CHIP_IS_E2_PLUS(bp)) + pbd_e2->parsing_data = (UNICAST_ADDRESS << + ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT); + else + pbd_e1x->global_data = (UNICAST_ADDRESS << + ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT); } val = (u64) ring_map >> 32; @@ -4829,15 +4972,16 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, struct client_init_ramrod_data *data) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_uio_dev *udev = cp->udev; struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring + - BCM_PAGE_SIZE); + CNIC_PAGE_SIZE); struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (udev->l2_ring + (2 * CNIC_PAGE_SIZE)); struct host_sp_status_block *sb = cp->bnx2x_def_status_blk; int i; u32 cli = cp->ethdev->iscsi_l2_client_id; - int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli); + int cl_qzone_id = BNX2X_CL_QZONE_ID(bp, cli); u32 val; dma_addr_t ring_map = udev->l2_ring_map; @@ -4846,7 +4990,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, data->general.activate_flg = 1; data->general.sp_client_id = cli; data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14); - data->general.func_id = cp->pfid; + data->general.func_id = bp->pfid; for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) { dma_addr_t buf_map; @@ -4857,20 +5001,20 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff); } - val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32; + val = (u64) (ring_map + CNIC_PAGE_SIZE) >> 32; rxbd->addr_hi = cpu_to_le32(val); data->rx.bd_page_base.hi = cpu_to_le32(val); - val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff; + val = (u64) (ring_map + CNIC_PAGE_SIZE) & 0xffffffff; rxbd->addr_lo = cpu_to_le32(val); data->rx.bd_page_base.lo = cpu_to_le32(val); rxcqe += BNX2X_MAX_RCQ_DESC_CNT; - val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32; + val = (u64) (ring_map + (2 * CNIC_PAGE_SIZE)) >> 32; rxcqe->addr_hi = cpu_to_le32(val); data->rx.cqe_page_base.hi = cpu_to_le32(val); - val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff; + val = (u64) (ring_map + (2 * CNIC_PAGE_SIZE)) & 0xffffffff; rxcqe->addr_lo = cpu_to_le32(val); data->rx.cqe_page_base.lo = cpu_to_le32(val); @@ -4895,13 +5039,14 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - u32 pfid = cp->pfid; + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 pfid = bp->pfid; cp->kcq1.io_addr = BAR_CSTRORM_INTMEM + CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0); cp->kcq1.sw_prod_idx = 0; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { struct host_hc_status_block_e2 *sb = cp->status_blk.gen; cp->kcq1.hw_prod_idx_ptr = @@ -4917,7 +5062,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) &sb->sb.running_index[SM_RX_ID]; } - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { struct host_hc_status_block_e2 *sb = cp->status_blk.gen; cp->kcq2.io_addr = BAR_USTRORM_INTMEM + @@ -4933,32 +5078,16 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) static int cnic_start_bnx2x_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_eth_dev *ethdev = cp->ethdev; - int func = CNIC_FUNC(cp), ret; + int func, ret; u32 pfid; dev->stats_addr = ethdev->addr_drv_info_to_mcp; - cp->port_mode = CHIP_PORT_MODE_NONE; - - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { - u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR); - - if (!(val & 1)) - val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN); - else - val = (val >> 1) & 1; + cp->func = bp->pf_num; - if (val) { - cp->port_mode = CHIP_4_PORT_MODE; - cp->pfid = func >> 1; - } else { - cp->port_mode = CHIP_2_PORT_MODE; - cp->pfid = func & 0x6; - } - } else { - cp->pfid = func; - } - pfid = cp->pfid; + func = CNIC_FUNC(cp); + pfid = bp->pfid; ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ, cp->iscsi_start_cid, 0); @@ -4966,7 +5095,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) if (ret) return -ENOMEM; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl, dev->max_fcoe_conn, cp->fcoe_start_cid, 0); @@ -5018,12 +5147,14 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) if (ret) return ret; + ethdev->drv_state |= CNIC_DRV_STATE_HANDLES_IRQ; return 0; } static void cnic_init_rings(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_uio_dev *udev = cp->udev; if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags)) @@ -5046,12 +5177,12 @@ static void cnic_init_rings(struct cnic_dev *dev) rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT; barrier(); - cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli); + cl_qzone_id = BNX2X_CL_QZONE_ID(bp, cli); off = BAR_USTRORM_INTMEM + - (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? + (BNX2X_CHIP_IS_E2_PLUS(bp) ? USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) : - USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli)); + USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), cli)); for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++) CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]); @@ -5084,7 +5215,9 @@ static void cnic_init_rings(struct cnic_dev *dev) "iSCSI CLIENT_SETUP did not complete\n"); cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1); cnic_ring_ctl(dev, cid, cli, 1); - *cid_ptr = cid; + *cid_ptr = cid >> 4; + *(cid_ptr + 1) = cid * bp->db_size; + *(cid_ptr + 2) = UIO_USE_TX_DOORBELL; } } @@ -5129,8 +5262,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev) msleep(10); } clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags); - rx_ring = udev->l2_ring + BCM_PAGE_SIZE; - memset(rx_ring, 0, BCM_PAGE_SIZE); + rx_ring = udev->l2_ring + CNIC_PAGE_SIZE; + memset(rx_ring, 0, CNIC_PAGE_SIZE); } static int cnic_register_netdev(struct cnic_dev *dev) @@ -5149,6 +5282,13 @@ static int cnic_register_netdev(struct cnic_dev *dev) if (err) netdev_err(dev->netdev, "register_cnic failed\n"); + /* Read iSCSI config again. On some bnx2x device, iSCSI config + * can change after firmware is downloaded. + */ + dev->max_iscsi_conn = ethdev->max_iscsi_conn; + if (ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI) + dev->max_iscsi_conn = 0; + return err; } @@ -5224,11 +5364,31 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev) static void cnic_stop_bnx2x_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 hc_index = HC_INDEX_ISCSI_EQ_CONS; + u32 sb_id = cp->status_blk_num; + u32 idx_off, syn_off; cnic_free_irq(dev); + + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { + idx_off = offsetof(struct hc_status_block_e2, index_values) + + (hc_index * sizeof(u16)); + + syn_off = CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hc_index, sb_id); + } else { + idx_off = offsetof(struct hc_status_block_e1x, index_values) + + (hc_index * sizeof(u16)); + + syn_off = CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hc_index, sb_id); + } + CNIC_WR16(dev, BAR_CSTRORM_INTMEM + syn_off, 0); + CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(sb_id) + + idx_off, 0); + *cp->kcq1.hw_prod_idx_ptr = 0; CNIC_WR(dev, BAR_CSTRORM_INTMEM + - CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0); + CSTORM_ISCSI_EQ_CONS_OFFSET(bp->pfid, 0), 0); CNIC_WR16(dev, cp->kcq1.io_addr, 0); cnic_free_resc(dev); } @@ -5242,11 +5402,13 @@ static void cnic_stop_hw(struct cnic_dev *dev) /* Need to wait for the ring shutdown event to complete * before clearing the CNIC_UP flag. */ - while (cp->udev->uio_dev != -1 && i < 15) { + while (cp->udev && cp->udev->uio_dev != -1 && i < 15) { msleep(100); i++; } cnic_shutdown_rings(dev); + cp->stop_cm(dev); + cp->ethdev->drv_state &= ~CNIC_DRV_STATE_HANDLES_IRQ; clear_bit(CNIC_F_CNIC_UP, &dev->flags); RCU_INIT_POINTER(cp->ulp_ops[CNIC_ULP_L4], NULL); synchronize_rcu(); @@ -5281,11 +5443,9 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev, alloc_size = sizeof(struct cnic_dev) + sizeof(struct cnic_local); - cdev = kzalloc(alloc_size , GFP_KERNEL); - if (cdev == NULL) { - netdev_err(dev, "allocate dev struct failure\n"); + cdev = kzalloc(alloc_size, GFP_KERNEL); + if (cdev == NULL) return NULL; - } cdev->netdev = dev; cdev->cnic_priv = (char *)cdev + sizeof(struct cnic_dev); @@ -5310,14 +5470,12 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) struct pci_dev *pdev; struct cnic_dev *cdev; struct cnic_local *cp; + struct bnx2 *bp = netdev_priv(dev); struct cnic_eth_dev *ethdev = NULL; - struct cnic_eth_dev *(*probe)(struct net_device *) = NULL; - probe = symbol_get(bnx2_cnic_probe); - if (probe) { - ethdev = (*probe)(dev); - symbol_put(bnx2_cnic_probe); - } + if (bp->cnic_probe) + ethdev = (bp->cnic_probe)(dev); + if (!ethdev) return NULL; @@ -5372,14 +5530,12 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) struct pci_dev *pdev; struct cnic_dev *cdev; struct cnic_local *cp; + struct bnx2x *bp = netdev_priv(dev); struct cnic_eth_dev *ethdev = NULL; - struct cnic_eth_dev *(*probe)(struct net_device *) = NULL; - probe = symbol_get(bnx2x_cnic_probe); - if (probe) { - ethdev = (*probe)(dev); - symbol_put(bnx2x_cnic_probe); - } + if (bp->cnic_probe) + ethdev = bp->cnic_probe(dev); + if (!ethdev) return NULL; @@ -5406,14 +5562,15 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)) cdev->max_iscsi_conn = ethdev->max_iscsi_conn; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) && - !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE)) + if (CNIC_SUPPORTS_FCOE(bp)) { cdev->max_fcoe_conn = ethdev->max_fcoe_conn; + cdev->max_fcoe_exchanges = ethdev->max_fcoe_exchanges; + } if (cdev->max_fcoe_conn > BNX2X_FCOE_NUM_CONNECTIONS) cdev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS; - memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6); + memcpy(cdev->mac_addr, ethdev->iscsi_mac, ETH_ALEN); cp->cnic_ops = &cnic_bnx2x_ops; cp->start_hw = cnic_start_bnx2x_hw; @@ -5425,10 +5582,13 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) cp->stop_cm = cnic_cm_stop_bnx2x_hw; cp->enable_int = cnic_enable_bnx2x_int; cp->disable_int_sync = cnic_disable_bnx2x_int_sync; - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) + if (BNX2X_CHIP_IS_E2_PLUS(bp)) { cp->ack_int = cnic_ack_bnx2x_e2_msix; - else + cp->arm_int = cnic_arm_bnx2x_e2_msix; + } else { cp->ack_int = cnic_ack_bnx2x_msix; + cp->arm_int = cnic_arm_bnx2x_msix; + } cp->close_conn = cnic_close_bnx2x_conn; return cdev; } @@ -5460,35 +5620,40 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event, { int if_type; - rcu_read_lock(); for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { struct cnic_ulp_ops *ulp_ops; void *ctx; - ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); - if (!ulp_ops || !ulp_ops->indicate_netevent) + mutex_lock(&cnic_lock); + ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], + lockdep_is_held(&cnic_lock)); + if (!ulp_ops || !ulp_ops->indicate_netevent) { + mutex_unlock(&cnic_lock); continue; + } ctx = cp->ulp_handle[if_type]; + set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); + mutex_unlock(&cnic_lock); + ulp_ops->indicate_netevent(ctx, event, vlan_id); + + clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); } - rcu_read_unlock(); } -/** - * netdev event handler - */ +/* netdev event handler */ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *netdev = ptr; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct cnic_dev *dev; int new_dev = 0; dev = cnic_from_netdev(netdev); - if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) { + if (!dev && event == NETDEV_REGISTER) { /* Check for the hot-plug device */ dev = is_cnic_dev(netdev); if (dev) { @@ -5504,7 +5669,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, else if (event == NETDEV_UNREGISTER) cnic_ulp_exit(dev); - if (event == NETDEV_UP || (new_dev && netif_running(netdev))) { + if (event == NETDEV_UP) { if (cnic_register_netdev(dev) != 0) { cnic_put(dev); goto done; @@ -5553,21 +5718,8 @@ static struct notifier_block cnic_netdev_notifier = { static void cnic_release(void) { - struct cnic_dev *dev; struct cnic_uio_dev *udev; - while (!list_empty(&cnic_dev_list)) { - dev = list_entry(cnic_dev_list.next, struct cnic_dev, list); - if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) { - cnic_ulp_stop(dev); - cnic_stop_hw(dev); - } - - cnic_ulp_exit(dev); - cnic_unregister_netdev(dev); - list_del_init(&dev->list); - cnic_free_dev(dev); - } while (!list_empty(&cnic_udev_list)) { udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev, list); |
