summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/macsec.c8
-rw-r--r--include/net/macsec.h4
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index ef5ac634f916..e7ad24f1ea5b 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -176,9 +176,10 @@ static void macsec_rxsc_put(struct macsec_rx_sc *sc)
call_rcu(&sc->rcu_head, free_rx_sc_rcu);
}
-static void free_rxsa(struct rcu_head *head)
+static void free_rxsa_work(struct work_struct *work)
{
- struct macsec_rx_sa *sa = container_of(head, struct macsec_rx_sa, rcu);
+ struct macsec_rx_sa *sa =
+ container_of(to_rcu_work(work), struct macsec_rx_sa, destroy_work);
crypto_free_aead(sa->key.tfm);
free_percpu(sa->stats);
@@ -188,7 +189,7 @@ static void free_rxsa(struct rcu_head *head)
static void macsec_rxsa_put(struct macsec_rx_sa *sa)
{
if (refcount_dec_and_test(&sa->refcnt))
- call_rcu(&sa->rcu, free_rxsa);
+ queue_rcu_work(macsec_wq, &sa->destroy_work);
}
static struct macsec_tx_sa *macsec_txsa_get(struct macsec_tx_sa __rcu *ptr)
@@ -1409,6 +1410,7 @@ static int init_rx_sa(struct macsec_rx_sa *rx_sa, char *sak, int key_len,
rx_sa->next_pn = 1;
refcount_set(&rx_sa->refcnt, 1);
spin_lock_init(&rx_sa->lock);
+ INIT_RCU_WORK(&rx_sa->destroy_work, free_rxsa_work);
return 0;
}
diff --git a/include/net/macsec.h b/include/net/macsec.h
index bc7de5b53e54..0980ef36fbf0 100644
--- a/include/net/macsec.h
+++ b/include/net/macsec.h
@@ -9,6 +9,7 @@
#include <linux/u64_stats_sync.h>
#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
#include <uapi/linux/if_link.h>
#include <uapi/linux/if_macsec.h>
@@ -123,6 +124,7 @@ struct macsec_dev_stats {
* @key: key structure
* @ssci: short secure channel identifier
* @stats: per-SA stats
+ * @destroy_work: deferred work to free the SA in process context after RCU grace period
*/
struct macsec_rx_sa {
struct macsec_key key;
@@ -136,7 +138,7 @@ struct macsec_rx_sa {
bool active;
struct macsec_rx_sa_stats __percpu *stats;
struct macsec_rx_sc *sc;
- struct rcu_head rcu;
+ struct rcu_work destroy_work;
};
struct pcpu_rx_sc_stats {