Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2bff63f authored by Dmitry Kravkov's avatar Dmitry Kravkov Committed by David S. Miller
Browse files

bnx2x, cnic: Fix SPQ return credit



Return proper L2 and L5 SPQ (slow path queue) credits.  Previously, all
SPQ events were counted as L5 types.

Signed-off-by: default avatarDmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d6214d7a
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
@@ -1369,19 +1369,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)

	bnx2x_set_eth_mac(bp, 1);

#ifdef BCM_CNIC
	/* Set iSCSI L2 MAC */
	mutex_lock(&bp->cnic_mutex);
	if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) {
		bnx2x_set_iscsi_eth_mac_addr(bp, 1);
		bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
		bnx2x_init_sb(bp, bp->cnic_sb_mapping,
			      BNX2X_VF_ID_INVALID, false,
			      CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
	}
	mutex_unlock(&bp->cnic_mutex);
#endif

	if (bp->port.pmf)
		bnx2x_initial_phy_init(bp, load_mode);

+69 −17
Original line number Diff line number Diff line
@@ -6462,6 +6462,12 @@ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
	return rc;
}

/* must be called prioir to any HW initializations */
static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
{
	return L2_ILT_LINES(bp);
}

void bnx2x_ilt_set_info(struct bnx2x *bp)
{
	struct ilt_client_info *ilt_client;
@@ -9347,19 +9353,53 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
#endif

	spin_lock_bh(&bp->spq_lock);
	BUG_ON(bp->cnic_spq_pending < count);
	bp->cnic_spq_pending -= count;

	for (; bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending;
	     bp->cnic_spq_pending++) {

		if (!bp->cnic_kwq_pending)
	for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) {
		u16 type =  (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
				& SPE_HDR_CONN_TYPE) >>
				SPE_HDR_CONN_TYPE_SHIFT;

		/* Set validation for iSCSI L2 client before sending SETUP
		 *  ramrod
		 */
		if (type == ETH_CONNECTION_TYPE) {
			u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
					     hdr.conn_and_cmd_data) >>
				SPE_HDR_CMD_ID_SHIFT) & 0xff;

			if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
				bnx2x_set_ctx_validation(&bp->context.
						vcxt[BNX2X_ISCSI_ETH_CID].eth,
					HW_CID(bp, BNX2X_ISCSI_ETH_CID));
		}

		/* There may be not more than 8 L2 and COMMON SPEs and not more
		 * than 8 L5 SPEs in the air.
		 */
		if ((type == NONE_CONNECTION_TYPE) ||
		    (type == ETH_CONNECTION_TYPE)) {
			if (!atomic_read(&bp->spq_left))
				break;
			else
				atomic_dec(&bp->spq_left);
		} else if (type == ISCSI_CONNECTION_TYPE) {
			if (bp->cnic_spq_pending >=
			    bp->cnic_eth_dev.max_kwqe_pending)
				break;
			else
				bp->cnic_spq_pending++;
		} else {
			BNX2X_ERR("Unknown SPE type: %d\n", type);
			bnx2x_panic();
			break;
		}

		spe = bnx2x_sp_get_next(bp);
		*spe = *bp->cnic_kwq_cons;

		bp->cnic_kwq_pending--;

		DP(NETIF_MSG_TIMER, "pending on SPQ %d, on KWQ %d count %d\n",
		   bp->cnic_spq_pending, bp->cnic_kwq_pending, count);

@@ -9464,7 +9504,7 @@ static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid)
	ctl.data.comp.cid = cid;

	bnx2x_cnic_ctl_send_bh(bp, &ctl);
	bnx2x_cnic_sp_post(bp, 1);
	bnx2x_cnic_sp_post(bp, 0);
}

static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
@@ -9481,8 +9521,8 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
		break;
	}

	case DRV_CTL_COMPLETION_CMD: {
		int count = ctl->data.comp.comp_count;
	case DRV_CTL_RET_L5_SPQ_CREDIT_CMD: {
		int count = ctl->data.credit.credit_count;

		bnx2x_cnic_sp_post(bp, count);
		break;
@@ -9528,6 +9568,14 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
		bnx2x_set_iscsi_eth_mac_addr(bp, 0);
		break;
	}
	case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
		int count = ctl->data.credit.credit_count;

		smp_mb__before_atomic_inc();
		atomic_add(count, &bp->spq_left);
		smp_mb__after_atomic_inc();
		break;
	}

	default:
		BNX2X_ERR("unknown command %x\n", ctl->cmd);
@@ -9592,13 +9640,8 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
	cp->drv_state = CNIC_DRV_STATE_REGD;
	cp->iro_arr = bp->iro_arr;

	bnx2x_init_sb(bp, bp->cnic_sb_mapping,
		      BNX2X_VF_ID_INVALID, false,
		      CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));

	bnx2x_setup_cnic_irq_info(bp);
	bnx2x_set_iscsi_eth_mac_addr(bp, 1);
	bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;

	rcu_assign_pointer(bp->cnic_ops, ops);

	return 0;
@@ -9636,14 +9679,23 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
	cp->io_base2 = bp->doorbells;
	cp->max_kwqe_pending = 8;
	cp->ctx_blk_size = CDU_ILT_PAGE_SZ;
	cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) + 1;
	cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) +
			     bnx2x_cid_ilt_lines(bp);
	cp->ctx_tbl_len = CNIC_ILT_LINES;
	cp->starting_cid = BCM_CNIC_CID_START;
	cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
	cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
	cp->drv_ctl = bnx2x_drv_ctl;
	cp->drv_register_cnic = bnx2x_register_cnic;
	cp->drv_unregister_cnic = bnx2x_unregister_cnic;

	cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID;
	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;

	DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
			 "starting cid %d\n",
	   cp->ctx_blk_size,
	   cp->ctx_tbl_offset,
	   cp->ctx_tbl_len,
	   cp->starting_cid);
	return cp;
}
EXPORT_SYMBOL(bnx2x_cnic_probe);
+10 −8
Original line number Diff line number Diff line
@@ -242,14 +242,14 @@ static int cnic_in_use(struct cnic_sock *csk)
	return test_bit(SK_F_INUSE, &csk->flags);
}

static void cnic_kwq_completion(struct cnic_dev *dev, u32 count)
static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
{
	struct cnic_local *cp = dev->cnic_priv;
	struct cnic_eth_dev *ethdev = cp->ethdev;
	struct drv_ctl_info info;

	info.cmd = DRV_CTL_COMPLETION_CMD;
	info.data.comp.comp_count = count;
	info.cmd = cmd;
	info.data.credit.credit_count = count;
	ethdev->drv_ctl(dev->netdev, &info);
}

@@ -2069,7 +2069,7 @@ static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
static void service_kcqes(struct cnic_dev *dev, int num_cqes)
{
	struct cnic_local *cp = dev->cnic_priv;
	int i, j;
	int i, j, comp = 0;

	i = 0;
	j = 1;
@@ -2080,7 +2080,7 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes)
		u32 kcqe_layer = kcqe_op_flag & KCQE_FLAGS_LAYER_MASK;

		if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
			cnic_kwq_completion(dev, 1);
			comp++;

		while (j < num_cqes) {
			u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
@@ -2089,7 +2089,7 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes)
				break;

			if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
				cnic_kwq_completion(dev, 1);
				comp++;
			j++;
		}

@@ -2119,6 +2119,8 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes)
		i += j;
		j = 1;
	}
	if (unlikely(comp))
		cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
}

static u16 cnic_bnx2_next_idx(u16 idx)
@@ -4246,7 +4248,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
			netdev_err(dev->netdev,
				"iSCSI CLIENT_SETUP did not complete\n");
		cnic_kwq_completion(dev, 1);
		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1);
	}
}
@@ -4283,7 +4285,7 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
		if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
			netdev_err(dev->netdev,
				"iSCSI CLIENT_HALT did not complete\n");
		cnic_kwq_completion(dev, 1);
		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);

		memset(&l5_data, 0, sizeof(l5_data));
		type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+12 −9
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H

#define CNIC_MODULE_VERSION	"2.1.3"
#define CNIC_MODULE_RELDATE	"June 24, 2010"
#define CNIC_MODULE_VERSION	"2.2.5"
#define CNIC_MODULE_RELDATE	"September 29, 2010"

#define CNIC_ULP_RDMA		0
#define CNIC_ULP_ISCSI		1
@@ -80,18 +80,15 @@ struct kcqe {
#define DRV_CTL_IO_RD_CMD		0x102
#define DRV_CTL_CTX_WR_CMD		0x103
#define DRV_CTL_CTXTBL_WR_CMD		0x104
#define DRV_CTL_COMPLETION_CMD		0x105
#define DRV_CTL_RET_L5_SPQ_CREDIT_CMD	0x105
#define DRV_CTL_START_L2_CMD		0x106
#define DRV_CTL_STOP_L2_CMD		0x107
#define DRV_CTL_RET_L2_SPQ_CREDIT_CMD	0x10c

struct cnic_ctl_completion {
	u32	cid;
};

struct drv_ctl_completion {
	u32	comp_count;
};

struct cnic_ctl_info {
	int	cmd;
	union {
@@ -100,6 +97,10 @@ struct cnic_ctl_info {
	} data;
};

struct drv_ctl_spq_credit {
	u32	credit_count;
};

struct drv_ctl_io {
	u32		cid_addr;
	u32		offset;
@@ -115,7 +116,7 @@ struct drv_ctl_l2_ring {
struct drv_ctl_info {
	int	cmd;
	union {
		struct drv_ctl_completion comp;
		struct drv_ctl_spq_credit credit;
		struct drv_ctl_io io;
		struct drv_ctl_l2_ring ring;
		char bytes[MAX_DRV_CTL_DATA];
@@ -162,7 +163,9 @@ struct cnic_eth_dev {
	u32		max_iscsi_conn;
	u32		max_fcoe_conn;
	u32		max_rdma_conn;
	u32		reserved0[2];
	u32		fcoe_init_cid;
	u16		iscsi_l2_client_id;
	u16		iscsi_l2_cid;

	int		num_irq;
	struct cnic_irq	irq_arr[MAX_CNIC_VEC];