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: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 2572eb4..a686a4c 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -6462,6 +6462,12 @@
 	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 @@
 #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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 	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);