提交 107c3f4d 编写于 作者: M Michael Chan 提交者: David S. Miller

cnic: Prevent status block race conditions with hardware

The status block index is used to acknowledge interrupt events and must
be read before checking for the interrupt events, so we need to add rmb()
to guarantee that.
Signed-off-by: NMichael Chan <mchan@broadcom.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 1707be1b
...@@ -2760,6 +2760,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) ...@@ -2760,6 +2760,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
u32 status_idx = (u16) *cp->kcq1.status_idx_ptr; u32 status_idx = (u16) *cp->kcq1.status_idx_ptr;
int kcqe_cnt; int kcqe_cnt;
/* status block index must be read before reading other fields */
rmb();
cp->kwq_con_idx = *cp->kwq_con_idx_ptr; cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) {
...@@ -2770,6 +2772,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) ...@@ -2770,6 +2772,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
barrier(); barrier();
if (status_idx != *cp->kcq1.status_idx_ptr) { if (status_idx != *cp->kcq1.status_idx_ptr) {
status_idx = (u16) *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; cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
} else } else
break; break;
...@@ -2888,6 +2892,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) ...@@ -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; u32 last_status = *info->status_idx_ptr;
int kcqe_cnt; int kcqe_cnt;
/* status block index must be read before reading the KCQ */
rmb();
while ((kcqe_cnt = cnic_get_kcqes(dev, info))) { while ((kcqe_cnt = cnic_get_kcqes(dev, info))) {
service_kcqes(dev, kcqe_cnt); service_kcqes(dev, kcqe_cnt);
...@@ -2898,6 +2904,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) ...@@ -2898,6 +2904,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
break; break;
last_status = *info->status_idx_ptr; last_status = *info->status_idx_ptr;
/* status block index must be read before reading the KCQ */
rmb();
} }
return last_status; return last_status;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册