diff options
Diffstat (limited to 'drivers/net/cnic.c')
| -rw-r--r-- | drivers/net/cnic.c | 412 | 
1 files changed, 222 insertions, 190 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 11a92afdf982..94a2e541006d 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -1,6 +1,6 @@  /* cnic.c: Broadcom CNIC core network driver.   * - * Copyright (c) 2006-2010 Broadcom Corporation + * Copyright (c) 2006-2011 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 @@ -28,6 +28,7 @@  #include <linux/ethtool.h>  #include <linux/if_vlan.h>  #include <linux/prefetch.h> +#include <linux/random.h>  #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)  #define BCM_VLAN 1  #endif @@ -327,7 +328,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,  		msleep(100);  		retry++;  	} -	return 0; +	return rc;  }  static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8); @@ -605,11 +606,12 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)  }  EXPORT_SYMBOL(cnic_unregister_driver); -static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id) +static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id, +			    u32 next)  {  	id_tbl->start = start_id;  	id_tbl->max = size; -	id_tbl->next = 0; +	id_tbl->next = next;  	spin_lock_init(&id_tbl->lock);  	id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);  	if (!id_tbl->table) @@ -835,7 +837,6 @@ static void cnic_free_resc(struct cnic_dev *dev)  	cp->ctx_blks = 0;  	cnic_free_dma(dev, &cp->gbl_buf_info); -	cnic_free_dma(dev, &cp->conn_buf_info);  	cnic_free_dma(dev, &cp->kwq_info);  	cnic_free_dma(dev, &cp->kwq_16_data_info);  	cnic_free_dma(dev, &cp->kcq2.dma); @@ -899,24 +900,56 @@ static int cnic_alloc_context(struct cnic_dev *dev)  	return 0;  } -static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info) +static u16 cnic_bnx2_next_idx(u16 idx) +{ +	return idx + 1; +} + +static u16 cnic_bnx2_hw_idx(u16 idx) +{ +	return idx; +} + +static u16 cnic_bnx2x_next_idx(u16 idx)  { -	int err, i, is_bnx2 = 0; +	idx++; +	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT) +		idx++; + +	return idx; +} + +static u16 cnic_bnx2x_hw_idx(u16 idx) +{ +	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT) +		idx++; +	return idx; +} + +static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info, +			  bool use_pg_tbl) +{ +	int err, i, use_page_tbl = 0;  	struct kcqe **kcq; -	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) -		is_bnx2 = 1; +	if (use_pg_tbl) +		use_page_tbl = 1; -	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, is_bnx2); +	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, use_page_tbl);  	if (err)  		return err;  	kcq = (struct kcqe **) info->dma.pg_arr;  	info->kcq = kcq; -	if (is_bnx2) +	info->next_idx = cnic_bnx2_next_idx; +	info->hw_idx = cnic_bnx2_hw_idx; +	if (use_pg_tbl)  		return 0; +	info->next_idx = cnic_bnx2x_next_idx; +	info->hw_idx = cnic_bnx2x_hw_idx; +  	for (i = 0; i < KCQ_PAGE_CNT; i++) {  		struct bnx2x_bd_chain_next *next =  			(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT]; @@ -1059,7 +1092,7 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)  		goto error;  	cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr; -	ret = cnic_alloc_kcq(dev, &cp->kcq1); +	ret = cnic_alloc_kcq(dev, &cp->kcq1, true);  	if (ret)  		goto error; @@ -1139,25 +1172,17 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)  	cp->iro_arr = ethdev->iro_arr; -	cp->max_cid_space = MAX_ISCSI_TBL_SZ + BNX2X_FCOE_NUM_CONNECTIONS; +	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(cp->chip_id)) { +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {  		cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;  		cp->fcoe_init_cid = ethdev->fcoe_init_cid;  		if (!cp->fcoe_init_cid)  			cp->fcoe_init_cid = 0x10;  	} -	if (start_cid < BNX2X_ISCSI_START_CID) { -		u32 delta = BNX2X_ISCSI_START_CID - start_cid; - -		cp->iscsi_start_cid = BNX2X_ISCSI_START_CID; -		cp->fcoe_start_cid += delta; -		cp->max_cid_space += delta; -	} -  	cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,  				GFP_KERNEL);  	if (!cp->iscsi_tbl) @@ -1195,22 +1220,16 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)  			j++;  	} -	ret = cnic_alloc_kcq(dev, &cp->kcq1); +	ret = cnic_alloc_kcq(dev, &cp->kcq1, false);  	if (ret)  		goto error; -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { -		ret = cnic_alloc_kcq(dev, &cp->kcq2); +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { +		ret = cnic_alloc_kcq(dev, &cp->kcq2, true);  		if (ret)  			goto error;  	} -	pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS * -			   BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE; -	ret = cnic_alloc_dma(dev, &cp->conn_buf_info, pages, 1); -	if (ret) -		goto error; -  	pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;  	ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);  	if (ret) @@ -1577,6 +1596,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],  	struct iscsi_context *ictx;  	struct regpair context_addr;  	int i, j, n = 2, n_max; +	u8 port = CNIC_PORT(cp);  	ctx->ctx_flags = 0;  	if (!req2->num_additional_wqes) @@ -1628,6 +1648,17 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],  		XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA;  	ictx->xstorm_st_context.iscsi.flags.flags |=  		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) { + +		port = 0; +	} +	ictx->xstorm_st_context.common.flags = +		1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT; +	ictx->xstorm_st_context.common.flags = +		port << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT;  	ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;  	/* TSTORM requires the base address of RQ DB & not PTE */ @@ -1843,8 +1874,11 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)  	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,  				  hw_cid, NONE_CONNECTION_TYPE, &l5_data); -	if (ret == 0) +	if (ret == 0) {  		wait_event(ctx->waitq, ctx->wait_cond); +		if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags))) +			return -EBUSY; +	}  	return ret;  } @@ -1879,8 +1913,10 @@ static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)  skip_cfc_delete:  	cnic_free_bnx2x_conn_resc(dev, l5_cid); -	atomic_dec(&cp->iscsi_conn); -	clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); +	if (!ret) { +		atomic_dec(&cp->iscsi_conn); +		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); +	}  destroy_reply:  	memset(&kcqe, 0, sizeof(kcqe)); @@ -1939,8 +1975,6 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,  		tstorm_buf->ka_interval = kwqe3->ka_interval;  		tstorm_buf->ka_max_probe_count = kwqe3->ka_max_probe_count;  	} -	tstorm_buf->rcv_buf = kwqe3->rcv_buf; -	tstorm_buf->snd_buf = kwqe3->snd_buf;  	tstorm_buf->max_rt_time = 0xffffffff;  } @@ -1969,15 +2003,14 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)  		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,  		 mac[4]);  	CNIC_WR8(dev, BAR_TSTRORM_INTMEM + -		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]); +		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);  	CNIC_WR8(dev, BAR_TSTRORM_INTMEM + -		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1, +		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,  		 mac[2]);  	CNIC_WR8(dev, BAR_TSTRORM_INTMEM + -		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2, -		 mac[1]); +		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[1]);  	CNIC_WR8(dev, BAR_TSTRORM_INTMEM + -		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3, +		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,  		 mac[0]);  } @@ -2156,7 +2189,7 @@ static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)  	memset(fcoe_stat, 0, sizeof(*fcoe_stat));  	memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req)); -	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT, cid, +	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT_FUNC, cid,  				  FCOE_CONNECTION_TYPE, &l5_data);  	return ret;  } @@ -2201,12 +2234,9 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],  	memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));  	memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));  	memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3)); -	fcoe_init->eq_addr.lo = cp->kcq2.dma.pg_map_arr[0] & 0xffffffff; -	fcoe_init->eq_addr.hi = (u64) cp->kcq2.dma.pg_map_arr[0] >> 32; -	fcoe_init->eq_next_page_addr.lo = -		cp->kcq2.dma.pg_map_arr[1] & 0xffffffff; -	fcoe_init->eq_next_page_addr.hi = -		(u64) cp->kcq2.dma.pg_map_arr[1] >> 32; +	fcoe_init->eq_pbl_base.lo = cp->kcq2.dma.pgtbl_map & 0xffffffff; +	fcoe_init->eq_pbl_base.hi = (u64) cp->kcq2.dma.pgtbl_map >> 32; +	fcoe_init->eq_pbl_size = cp->kcq2.dma.num_pages;  	fcoe_init->sb_num = cp->status_blk_num;  	fcoe_init->eq_prod = MAX_KCQ_IDX; @@ -2214,7 +2244,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],  	cp->kcq2.sw_prod_idx = 0;  	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid); -	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT, cid, +	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,  				  FCOE_CONNECTION_TYPE, &l5_data);  	*work = 3;  	return ret; @@ -2418,6 +2448,30 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)  	return ret;  } +static void cnic_bnx2x_delete_wait(struct cnic_dev *dev, u32 start_cid) +{ +	struct cnic_local *cp = dev->cnic_priv; +	u32 i; + +	for (i = start_cid; i < cp->max_cid_space; i++) { +		struct cnic_context *ctx = &cp->ctx_tbl[i]; +		int j; + +		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) +			msleep(10); + +		for (j = 0; j < 5; j++) { +			if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) +				break; +			msleep(20); +		} + +		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) +			netdev_warn(dev->netdev, "CID %x not deleted\n", +				   ctx->cid); +	} +} +  static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)  {  	struct fcoe_kwqe_destroy *req; @@ -2426,11 +2480,13 @@ static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)  	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);  	memset(&l5_data, 0, sizeof(l5_data)); -	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY, cid, +	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,  				  FCOE_CONNECTION_TYPE, &l5_data);  	return ret;  } @@ -2511,7 +2567,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_NUM(cp->chip_id) == BNX2X_CHIP_NUM_57710) +	if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))  		return -EINVAL;  	for (i = 0; i < num_wqes; ) { @@ -2651,32 +2707,6 @@ end:  		cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);  } -static u16 cnic_bnx2_next_idx(u16 idx) -{ -	return idx + 1; -} - -static u16 cnic_bnx2_hw_idx(u16 idx) -{ -	return idx; -} - -static u16 cnic_bnx2x_next_idx(u16 idx) -{ -	idx++; -	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT) -		idx++; - -	return idx; -} - -static u16 cnic_bnx2x_hw_idx(u16 idx) -{ -	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT) -		idx++; -	return idx; -} -  static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)  {  	struct cnic_local *cp = dev->cnic_priv; @@ -2687,12 +2717,12 @@ static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)  	i = ri = last = info->sw_prod_idx;  	ri &= MAX_KCQ_IDX;  	hw_prod = *info->hw_prod_idx_ptr; -	hw_prod = cp->hw_idx(hw_prod); +	hw_prod = info->hw_idx(hw_prod);  	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {  		kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];  		cp->completed_kcq[kcqe_cnt++] = kcqe; -		i = cp->next_idx(i); +		i = info->next_idx(i);  		ri = i & MAX_KCQ_IDX;  		if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {  			last_cnt = kcqe_cnt; @@ -2778,13 +2808,10 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)  		/* Tell compiler that status_blk fields can change. */  		barrier(); -		if (status_idx != *cp->kcq1.status_idx_ptr) { -			status_idx = (u16) *cp->kcq1.status_idx_ptr; -			/* status block index must be read first */ -			rmb(); -			cp->kwq_con_idx = *cp->kwq_con_idx_ptr; -		} else -			break; +		status_idx = (u16) *cp->kcq1.status_idx_ptr; +		/* status block index must be read first */ +		rmb(); +		cp->kwq_con_idx = *cp->kwq_con_idx_ptr;  	}  	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx); @@ -2908,8 +2935,6 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)  		/* Tell compiler that sblk fields can change. */  		barrier(); -		if (last_status == *info->status_idx_ptr) -			break;  		last_status = *info->status_idx_ptr;  		/* status block index must be read before reading the KCQ */ @@ -2933,7 +2958,7 @@ 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(cp->chip_id)) { +		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);  			break; @@ -3052,13 +3077,21 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)  		break;  	}  	case CNIC_CTL_COMPLETION_CMD: { -		u32 cid = BNX2X_SW_CID(info->data.comp.cid); +		struct cnic_ctl_completion *comp = &info->data.comp; +		u32 cid = BNX2X_SW_CID(comp->cid);  		u32 l5_cid;  		struct cnic_local *cp = dev->cnic_priv;  		if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) {  			struct cnic_context *ctx = &cp->ctx_tbl[l5_cid]; +			if (unlikely(comp->error)) { +				set_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags); +				netdev_err(dev->netdev, +					   "CID %x CFC delete comp error %x\n", +					   cid, comp->error); +			} +  			ctx->wait_cond = 1;  			wake_up(&ctx->waitq);  		} @@ -3772,7 +3805,13 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)  		break;  	case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED: -		cnic_cm_upcall(cp, csk, opcode); +		/* after we already sent CLOSE_REQ */ +		if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) && +		    !test_bit(SK_F_OFFLD_COMPLETE, &csk->flags) && +		    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) +			cp->close_conn(csk, L4_KCQE_OPCODE_VALUE_RESET_COMP); +		else +			cnic_cm_upcall(cp, csk, opcode);  		break;  	}  	csk_put(csk); @@ -3803,14 +3842,17 @@ static void cnic_cm_free_mem(struct cnic_dev *dev)  static int cnic_cm_alloc_mem(struct cnic_dev *dev)  {  	struct cnic_local *cp = dev->cnic_priv; +	u32 port_id;  	cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,  			      GFP_KERNEL);  	if (!cp->csk_tbl)  		return -ENOMEM; +	port_id = random32(); +	port_id %= CNIC_LOCAL_PORT_RANGE;  	if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE, -			     CNIC_LOCAL_PORT_MIN)) { +			     CNIC_LOCAL_PORT_MIN, port_id)) {  		cnic_cm_free_mem(dev);  		return -ENOMEM;  	} @@ -3826,12 +3868,14 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)  	}  	/* 1. If event opcode matches the expected event in csk->state -	 * 2. If the expected event is CLOSE_COMP, we accept any event +	 * 2. If the expected event is CLOSE_COMP or RESET_COMP, we accept any +	 *    event  	 * 3. If the expected event is 0, meaning the connection was never  	 *    never established, we accept the opcode from cm_abort.  	 */  	if (opcode == csk->state || csk->state == 0 || -	    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) { +	    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP || +	    csk->state == L4_KCQE_OPCODE_VALUE_RESET_COMP) {  		if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {  			if (csk->state == 0)  				csk->state = opcode; @@ -3865,7 +3909,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)  {  	u32 seed; -	get_random_bytes(&seed, 4); +	seed = random32();  	cnic_ctx_wr(dev, 45, 0, seed);  	return 0;  } @@ -3912,7 +3956,6 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode)  static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)  {  	struct cnic_local *cp = dev->cnic_priv; -	int i;  	if (!cp->ctx_tbl)  		return; @@ -3920,16 +3963,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)  	if (!netif_running(dev->netdev))  		return; -	for (i = 0; i < cp->max_cid_space; i++) { -		struct cnic_context *ctx = &cp->ctx_tbl[i]; - -		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) -			msleep(10); - -		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) -			netdev_warn(dev->netdev, "CID %x not deleted\n", -				   ctx->cid); -	} +	cnic_bnx2x_delete_wait(dev, 0);  	cancel_delayed_work(&cp->delete_task);  	flush_workqueue(cnic_wq); @@ -3992,6 +4026,7 @@ static void cnic_delete_task(struct work_struct *work)  	for (i = 0; i < cp->max_cid_space; i++) {  		struct cnic_context *ctx = &cp->ctx_tbl[i]; +		int err;  		if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||  		    !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags)) @@ -4005,13 +4040,15 @@ static void cnic_delete_task(struct work_struct *work)  		if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))  			continue; -		cnic_bnx2x_destroy_ramrod(dev, i); +		err = cnic_bnx2x_destroy_ramrod(dev, i);  		cnic_free_bnx2x_conn_resc(dev, i); -		if (ctx->ulp_proto_id == CNIC_ULP_ISCSI) -			atomic_dec(&cp->iscsi_conn); +		if (!err) { +			if (ctx->ulp_proto_id == CNIC_ULP_ISCSI) +				atomic_dec(&cp->iscsi_conn); -		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); +			clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags); +		}  	}  	if (need_resched) @@ -4218,14 +4255,6 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev)  		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);  } -static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev) -{ -	u32 max_conn; - -	max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN); -	dev->max_iscsi_conn = max_conn; -} -  static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)  {  	struct cnic_local *cp = dev->cnic_priv; @@ -4291,7 +4320,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)  	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);  	cnic_ctx_wr(dev, cid_addr, offset1, val); -	txbd = (struct tx_bd *) udev->l2_ring; +	txbd = udev->l2_ring;  	buf_map = udev->l2_buf_map;  	for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) { @@ -4350,7 +4379,7 @@ 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 = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE); +	rxbd = udev->l2_ring + BCM_PAGE_SIZE;  	for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {  		dma_addr_t buf_map;  		int n = (i % cp->l2_rx_ring_size) + 1; @@ -4550,8 +4579,6 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)  		return err;  	} -	cnic_get_bnx2_iscsi_info(dev); -  	return 0;  } @@ -4617,7 +4644,7 @@ static void cnic_enable_bnx2x_int(struct cnic_dev *dev)  			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +  			offsetof(struct hc_status_block_data_e1x, index_data) +  			sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS + -			offsetof(struct hc_index_data, timeout), 64 / 12); +			offsetof(struct hc_index_data, timeout), 64 / 4);  	cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);  } @@ -4633,7 +4660,6 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,  	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;  	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk; -	int port = CNIC_PORT(cp);  	int i;  	u32 cli = cp->ethdev->iscsi_l2_client_id;  	u32 val; @@ -4674,10 +4700,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,  	/* reset xstorm per client statistics */  	if (cli < MAX_STAT_COUNTER_ID) { -		val = BAR_XSTRORM_INTMEM + -		      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -		for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) -			CNIC_WR(dev, val + i * 4, 0); +		data->general.statistics_zero_flg = 1; +		data->general.statistics_en_flg = 1; +		data->general.statistics_counter_id = cli;  	}  	cp->tx_cons_ptr = @@ -4695,7 +4720,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,  				(udev->l2_ring + (2 * BCM_PAGE_SIZE));  	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;  	int i; -	int port = CNIC_PORT(cp);  	u32 cli = cp->ethdev->iscsi_l2_client_id;  	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);  	u32 val; @@ -4703,10 +4727,10 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,  	/* General data */  	data->general.client_id = cli; -	data->general.statistics_en_flg = 1; -	data->general.statistics_counter_id = cli;  	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;  	for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {  		dma_addr_t buf_map; @@ -4740,23 +4764,12 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,  	data->rx.status_block_id = BNX2X_DEF_SB_ID;  	data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT; -	data->rx.bd_buff_size =	cpu_to_le16(cp->l2_single_buf_size); -	data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14); +	data->rx.max_bytes_on_bd = cpu_to_le16(cp->l2_single_buf_size);  	data->rx.outer_vlan_removal_enable_flg = 1; - -	/* reset tstorm and ustorm per client statistics */ -	if (cli < MAX_STAT_COUNTER_ID) { -		val = BAR_TSTRORM_INTMEM + -		      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -		for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) -			CNIC_WR(dev, val + i * 4, 0); - -		val = BAR_USTRORM_INTMEM + -		      USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -		for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++) -			CNIC_WR(dev, val + i * 4, 0); -	} +	data->rx.silent_vlan_removal_flg = 1; +	data->rx.silent_vlan_value = 0; +	data->rx.silent_vlan_mask = 0xffff;  	cp->rx_cons_ptr =  		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS]; @@ -4772,7 +4785,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)  			   CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);  	cp->kcq1.sw_prod_idx = 0; -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {  		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;  		cp->kcq1.hw_prod_idx_ptr = @@ -4788,7 +4801,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)  			&sb->sb.running_index[SM_RX_ID];  	} -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {  		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;  		cp->kcq2.io_addr = BAR_USTRORM_INTMEM + @@ -4805,10 +4818,12 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)  {  	struct cnic_local *cp = dev->cnic_priv;  	struct cnic_eth_dev *ethdev = cp->ethdev; -	int func = CNIC_FUNC(cp), ret, i; +	int func = CNIC_FUNC(cp), ret;  	u32 pfid; -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { +	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)) @@ -4816,25 +4831,28 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)  		else  			val = (val >> 1) & 1; -		if (val) +		if (val) { +			cp->port_mode = CHIP_4_PORT_MODE;  			cp->pfid = func >> 1; -		else +		} else { +			cp->port_mode = CHIP_2_PORT_MODE;  			cp->pfid = func & 0x6; +		}  	} else {  		cp->pfid = func;  	}  	pfid = cp->pfid;  	ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ, -			       cp->iscsi_start_cid); +			       cp->iscsi_start_cid, 0);  	if (ret)  		return -ENOMEM; -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {  		ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,  					BNX2X_FCOE_NUM_CONNECTIONS, -					cp->fcoe_start_cid); +					cp->fcoe_start_cid, 0);  		if (ret)  			return -ENOMEM; @@ -4868,15 +4886,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)  		CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),  		HC_INDEX_ISCSI_EQ_CONS); -	for (i = 0; i < cp->conn_buf_info.num_pages; i++) { -		CNIC_WR(dev, BAR_TSTRORM_INTMEM + -			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i), -			cp->conn_buf_info.pgtbl[2 * i]); -		CNIC_WR(dev, BAR_TSTRORM_INTMEM + -			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4, -			cp->conn_buf_info.pgtbl[(2 * i) + 1]); -	} -  	CNIC_WR(dev, BAR_USTRORM_INTMEM +  		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),  		cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff); @@ -4915,7 +4924,7 @@ static void cnic_init_rings(struct cnic_dev *dev)  		struct client_init_ramrod_data *data;  		union l5cm_specific_data l5_data;  		struct ustorm_eth_rx_producers rx_prods = {0}; -		u32 off, i; +		u32 off, i, *cid_ptr;  		rx_prods.bd_prod = 0;  		rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT; @@ -4924,7 +4933,7 @@ static void cnic_init_rings(struct cnic_dev *dev)  		cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);  		off = BAR_USTRORM_INTMEM + -			(BNX2X_CHIP_IS_E2(cp->chip_id) ? +			(BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?  			 USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :  			 USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli)); @@ -4934,6 +4943,7 @@ static void cnic_init_rings(struct cnic_dev *dev)  		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);  		data = udev->l2_buf; +		cid_ptr = udev->l2_buf + 12;  		memset(data, 0, sizeof(*data)); @@ -4958,12 +4968,15 @@ 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;  	}  }  static void cnic_shutdown_rings(struct cnic_dev *dev)  {  	struct cnic_local *cp = dev->cnic_priv; +	struct cnic_uio_dev *udev = cp->udev; +	void *rx_ring;  	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))  		return; @@ -4971,7 +4984,6 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)  	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {  		cnic_shutdown_bnx2_rx_ring(dev);  	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) { -		struct cnic_local *cp = dev->cnic_priv;  		u32 cli = cp->ethdev->iscsi_l2_client_id;  		u32 cid = cp->ethdev->iscsi_l2_cid;  		union l5cm_specific_data l5_data; @@ -5001,6 +5013,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);  }  static int cnic_register_netdev(struct cnic_dev *dev) @@ -5217,6 +5231,8 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)  	cdev->pcidev = pdev;  	cp->chip_id = ethdev->chip_id; +	cdev->max_iscsi_conn = ethdev->max_iscsi_conn; +  	cp->cnic_ops = &cnic_bnx2_ops;  	cp->start_hw = cnic_start_bnx2_hw;  	cp->stop_hw = cnic_stop_bnx2_hw; @@ -5228,8 +5244,6 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)  	cp->enable_int = cnic_enable_bnx2_int;  	cp->disable_int_sync = cnic_disable_bnx2_int_sync;  	cp->close_conn = cnic_close_bnx2_conn; -	cp->next_idx = cnic_bnx2_next_idx; -	cp->hw_idx = cnic_bnx2_hw_idx;  	return cdev;  cnic_err: @@ -5274,7 +5288,7 @@ 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(cp->chip_id) && +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&  	    !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))  		cdev->max_fcoe_conn = ethdev->max_fcoe_conn; @@ -5290,13 +5304,11 @@ 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(cp->chip_id)) +	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))  		cp->ack_int = cnic_ack_bnx2x_e2_msix;  	else  		cp->ack_int = cnic_ack_bnx2x_msix;  	cp->close_conn = cnic_close_bnx2x_conn; -	cp->next_idx = cnic_bnx2x_next_idx; -	cp->hw_idx = cnic_bnx2x_hw_idx;  	return cdev;  } @@ -5322,6 +5334,27 @@ static struct cnic_dev *is_cnic_dev(struct net_device *dev)  	return cdev;  } +static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event, +			      u16 vlan_id) +{ +	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) +			continue; + +		ctx = cp->ulp_handle[if_type]; + +		ulp_ops->indicate_netevent(ctx, event, vlan_id); +	} +	rcu_read_unlock(); +} +  /**   * netdev event handler   */ @@ -5330,12 +5363,11 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,  {  	struct net_device *netdev = ptr;  	struct cnic_dev *dev; -	int if_type;  	int new_dev = 0;  	dev = cnic_from_netdev(netdev); -	if (!dev && (event == NETDEV_REGISTER || event == NETDEV_UP)) { +	if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {  		/* Check for the hot-plug device */  		dev = is_cnic_dev(netdev);  		if (dev) { @@ -5351,7 +5383,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) { +		if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {  			if (cnic_register_netdev(dev) != 0) {  				cnic_put(dev);  				goto done; @@ -5360,20 +5392,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,  				cnic_ulp_start(dev);  		} -		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) -				continue; - -			ctx = cp->ulp_handle[if_type]; - -			ulp_ops->indicate_netevent(ctx, event); -		} -		rcu_read_unlock(); +		cnic_rcv_netevent(cp, event, 0);  		if (event == NETDEV_GOING_DOWN) {  			cnic_ulp_stop(dev); @@ -5389,6 +5408,19 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,  			goto done;  		}  		cnic_put(dev); +	} else { +		struct net_device *realdev; +		u16 vid; + +		vid = cnic_get_vlan(netdev, &realdev); +		if (realdev) { +			dev = cnic_from_netdev(realdev); +			if (dev) { +				vid |= VLAN_TAG_PRESENT; +				cnic_rcv_netevent(dev->cnic_priv, event, vid); +				cnic_put(dev); +			} +		}  	}  done:  	return NOTIFY_DONE;  |