diff options
Diffstat (limited to 'drivers/net/cnic.c')
| -rw-r--r-- | drivers/net/cnic.c | 33 | 
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 7ff170cbc7d..302be4aa69d 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2760,6 +2760,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)  	u32 status_idx = (u16) *cp->kcq1.status_idx_ptr;  	int kcqe_cnt; +	/* status block index must be read before reading other fields */ +	rmb();  	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;  	while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { @@ -2770,6 +2772,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)  		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; @@ -2888,6 +2892,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)  	u32 last_status = *info->status_idx_ptr;  	int kcqe_cnt; +	/* status block index must be read before reading the KCQ */ +	rmb();  	while ((kcqe_cnt = cnic_get_kcqes(dev, info))) {  		service_kcqes(dev, kcqe_cnt); @@ -2898,6 +2904,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)  			break;  		last_status = *info->status_idx_ptr; +		/* status block index must be read before reading the KCQ */ +		rmb();  	}  	return last_status;  } @@ -2906,26 +2914,35 @@ static void cnic_service_bnx2x_bh(unsigned long data)  {  	struct cnic_dev *dev = (struct cnic_dev *) data;  	struct cnic_local *cp = dev->cnic_priv; -	u32 status_idx; +	u32 status_idx, new_status_idx;  	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))  		return; -	status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); +	while (1) { +		status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); -	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); +		CNIC_WR16(dev, cp->kcq1.io_addr, +			  cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); -	if (BNX2X_CHIP_IS_E2(cp->chip_id)) { -		status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); +		if (!BNX2X_CHIP_IS_E2(cp->chip_id)) { +			cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, +					   status_idx, IGU_INT_ENABLE, 1); +			break; +		} + +		new_status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); + +		if (new_status_idx != status_idx) +			continue;  		CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx +  			  MAX_KCQ_IDX);  		cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF,  				status_idx, IGU_INT_ENABLE, 1); -	} else { -		cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, -				   status_idx, IGU_INT_ENABLE, 1); + +		break;  	}  }  |