Skip to content

Commit

Permalink
cnic: Prevent status block race conditions with hardware
Browse files Browse the repository at this point in the history
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: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and David S. Miller committed Mar 2, 2011
1 parent 1707be1 commit 107c3f4
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/net/cnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down

0 comments on commit 107c3f4

Please sign in to comment.