Commit 101c40c8 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

cnic: Fix race conditions with firmware

During iSCSI connection terminations, if the target is also terminating
at about the same time, the firmware may not complete the driver's
request to close or reset the connection.  This is fixed by handling
other events (instead of the expected completion event) as an indication
that the driver's request has been rejected.
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 93736656
...@@ -3767,6 +3767,12 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) ...@@ -3767,6 +3767,12 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
break; break;
case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED: case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
/* 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); cnic_cm_upcall(cp, csk, opcode);
break; break;
} }
...@@ -3821,12 +3827,14 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode) ...@@ -3821,12 +3827,14 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
} }
/* 1. If event opcode matches the expected event in csk->state /* 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 * 3. If the expected event is 0, meaning the connection was never
* never established, we accept the opcode from cm_abort. * never established, we accept the opcode from cm_abort.
*/ */
if (opcode == csk->state || csk->state == 0 || 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 (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
if (csk->state == 0) if (csk->state == 0)
csk->state = opcode; csk->state = opcode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment