wifi: mac80211: recalc min chandef for new STA links
[platform/kernel/linux-starfive.git] / net / rxrpc / conn_client.c
index 3c9eeb5..bdb335c 100644 (file)
@@ -40,6 +40,8 @@ __read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ;
 DEFINE_IDR(rxrpc_client_conn_ids);
 static DEFINE_SPINLOCK(rxrpc_conn_id_lock);
 
+static void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle);
+
 /*
  * Get a connection ID and epoch for a client connection from the global pool.
  * The connection struct pointer is then recorded in the idr radix tree.  The
@@ -123,6 +125,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp,
                bundle->params = *cp;
                rxrpc_get_peer(bundle->params.peer);
                refcount_set(&bundle->ref, 1);
+               atomic_set(&bundle->active, 1);
                spin_lock_init(&bundle->channel_lock);
                INIT_LIST_HEAD(&bundle->waiting_calls);
        }
@@ -149,7 +152,7 @@ void rxrpc_put_bundle(struct rxrpc_bundle *bundle)
 
        dead = __refcount_dec_and_test(&bundle->ref, &r);
 
-       _debug("PUT B=%x %d", d, r);
+       _debug("PUT B=%x %d", d, r - 1);
        if (dead)
                rxrpc_free_bundle(bundle);
 }
@@ -338,6 +341,7 @@ found_bundle_free:
        rxrpc_free_bundle(candidate);
 found_bundle:
        rxrpc_get_bundle(bundle);
+       atomic_inc(&bundle->active);
        spin_unlock(&local->client_bundles_lock);
        _leave(" = %u [found]", bundle->debug_id);
        return bundle;
@@ -435,6 +439,7 @@ static void rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle, gfp_t gfp)
                        if (old)
                                trace_rxrpc_client(old, -1, rxrpc_client_replace);
                        candidate->bundle_shift = shift;
+                       atomic_inc(&bundle->active);
                        bundle->conns[i] = candidate;
                        for (j = 0; j < RXRPC_MAXCALLS; j++)
                                set_bit(shift + j, &bundle->avail_chans);
@@ -725,6 +730,7 @@ granted_channel:
        smp_rmb();
 
 out_put_bundle:
+       rxrpc_deactivate_bundle(bundle);
        rxrpc_put_bundle(bundle);
 out:
        _leave(" = %d", ret);
@@ -900,9 +906,8 @@ out:
 static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)
 {
        struct rxrpc_bundle *bundle = conn->bundle;
-       struct rxrpc_local *local = bundle->params.local;
        unsigned int bindex;
-       bool need_drop = false, need_put = false;
+       bool need_drop = false;
        int i;
 
        _enter("C=%x", conn->debug_id);
@@ -921,15 +926,22 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)
        }
        spin_unlock(&bundle->channel_lock);
 
-       /* If there are no more connections, remove the bundle */
-       if (!bundle->avail_chans) {
-               _debug("maybe unbundle");
-               spin_lock(&local->client_bundles_lock);
+       if (need_drop) {
+               rxrpc_deactivate_bundle(bundle);
+               rxrpc_put_connection(conn);
+       }
+}
 
-               for (i = 0; i < ARRAY_SIZE(bundle->conns); i++)
-                       if (bundle->conns[i])
-                               break;
-               if (i == ARRAY_SIZE(bundle->conns) && !bundle->params.exclusive) {
+/*
+ * Drop the active count on a bundle.
+ */
+static void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle)
+{
+       struct rxrpc_local *local = bundle->params.local;
+       bool need_put = false;
+
+       if (atomic_dec_and_lock(&bundle->active, &local->client_bundles_lock)) {
+               if (!bundle->params.exclusive) {
                        _debug("erase bundle");
                        rb_erase(&bundle->local_node, &local->client_bundles);
                        need_put = true;
@@ -939,10 +951,6 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)
                if (need_put)
                        rxrpc_put_bundle(bundle);
        }
-
-       if (need_drop)
-               rxrpc_put_connection(conn);
-       _leave("");
 }
 
 /*