cnic: Refactor and fix cnic_ready_to_close().
authorMichael Chan <mchan@broadcom.com>
Tue, 15 Jun 2010 08:57:02 +0000 (08:57 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Jun 2010 21:23:37 +0000 (14:23 -0700)
Combine RESET_RECEIVED and RESET_COMP logic and fix race condition
between these 2 events and cnic_cm_close().  In particular, we need
to (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) before we
update csk->state.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Eddie Wai <waie@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/cnic.c

index 48fdbceb218158e5a0532c264ccfd0640fde64d1..11eeded146d9be9c54ea427af2f9b8a6452f39ab 100644 (file)
@@ -3198,25 +3198,19 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev)
 
 static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
 {
-       if (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED) {
-               if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags))
-                       csk->state = opcode;
-       }
-       if ((opcode == csk->state) ||
-           (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED &&
-            csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)) {
-               if (!test_and_set_bit(SK_F_CLOSING, &csk->flags))
-                       return 1;
+       if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
+               /* Unsolicited RESET_COMP or RESET_RECEIVED */
+               opcode = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED;
+               csk->state = opcode;
        }
-       /* 57710+ only  workaround to handle unsolicited RESET_COMP
-        * which will be treated like a RESET RCVD notification
-        * which triggers the clean up procedure
+
+       /* 1. If event opcode matches the expected event in csk->state
+        * 2. If the expected event is CLOSE_COMP, we accept any event
         */
-       else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_COMP) {
-               if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
-                       csk->state = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED;
+       if (opcode == csk->state ||
+            csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) {
+               if (!test_and_set_bit(SK_F_CLOSING, &csk->flags))
                        return 1;
-               }
        }
        return 0;
 }