diff --git a/drivers/infiniband/hw/efa/Makefile b/drivers/infiniband/hw/efa/Makefile index 6e83083af0bc..a6a433b0ba2f 100644 --- a/drivers/infiniband/hw/efa/Makefile +++ b/drivers/infiniband/hw/efa/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -# Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved. # # Makefile for Amazon Elastic Fabric Adapter (EFA) device driver. # obj-$(CONFIG_INFINIBAND_EFA) += efa.o -efa-y := efa_com_cmd.o efa_com.o efa_main.o efa_verbs.o +efa-y := efa_com_cmd.o efa_ah_cache.o efa_com.o efa_main.o efa_verbs.o diff --git a/drivers/infiniband/hw/efa/efa_ah_cache.c b/drivers/infiniband/hw/efa/efa_ah_cache.c new file mode 100644 index 000000000000..39d0d2e97589 --- /dev/null +++ b/drivers/infiniband/hw/efa/efa_ah_cache.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * Copyright 2026 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#include + +#include "efa_ah_cache.h" + +static const struct rhashtable_params ah_cache_params = { + .key_len = sizeof(struct efa_ah_cache_key), + .key_offset = offsetof(struct efa_ah_cache_entry, key), + .head_offset = offsetof(struct efa_ah_cache_entry, linkage), +}; + +int efa_ah_cache_init(struct efa_ah_cache *ah_cache) +{ + int err; + + mutex_init(&ah_cache->lock); + err = rhashtable_init(&ah_cache->hashtable, &ah_cache_params); + if (err) + mutex_destroy(&ah_cache->lock); + + return err; +} + +static void efa_ah_cache_entry_free(void *ptr, void *arg) +{ + struct efa_ah_cache_entry *entry = ptr; + + WARN_ON(entry->usecnt); + mutex_destroy(&entry->lock); + kfree(entry); +} + +void efa_ah_cache_destroy(struct efa_ah_cache *ah_cache) +{ + rhashtable_free_and_destroy(&ah_cache->hashtable, efa_ah_cache_entry_free, NULL); + mutex_destroy(&ah_cache->lock); +} diff --git a/drivers/infiniband/hw/efa/efa_ah_cache.h b/drivers/infiniband/hw/efa/efa_ah_cache.h new file mode 100644 index 000000000000..1d1fadb591cf --- /dev/null +++ b/drivers/infiniband/hw/efa/efa_ah_cache.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright 2026 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#ifndef _EFA_AH_CACHE_H_ +#define _EFA_AH_CACHE_H_ + +#include +#include + +#define EFA_AH_GID_SIZE 16 + +struct efa_ah_cache_key { + u8 gid[EFA_AH_GID_SIZE]; + u16 pd; +}; + +struct efa_ah_cache_entry { + struct efa_ah_cache_key key; + u16 ah; + unsigned int usecnt; + refcount_t refcount; + struct rhash_head linkage; + struct mutex lock; /* Serializes device commands per cache entry */ +}; + +struct efa_ah_cache { + struct rhashtable hashtable; + struct mutex lock; /* Protects AH cache hashtable */ +}; + +int efa_ah_cache_init(struct efa_ah_cache *ah_cache); +void efa_ah_cache_destroy(struct efa_ah_cache *ah_cache); + +#endif /* _EFA_AH_CACHE_H_ */ diff --git a/drivers/infiniband/hw/efa/efa_com.c b/drivers/infiniband/hw/efa/efa_com.c index 7cc3f4af0bb9..7097d1c2f23d 100644 --- a/drivers/infiniband/hw/efa/efa_com.c +++ b/drivers/infiniband/hw/efa/efa_com.c @@ -724,6 +724,8 @@ void efa_com_admin_destroy(struct efa_com_dev *edev) size = aenq->depth * sizeof(*aenq->entries); dma_free_coherent(edev->dmadev, size, aenq->entries, aenq->dma_addr); + + efa_ah_cache_destroy(&edev->ah_cache); } /** @@ -782,6 +784,12 @@ int efa_com_admin_init(struct efa_com_dev *edev, return -ENODEV; } + err = efa_ah_cache_init(&edev->ah_cache); + if (err) { + ibdev_err(edev->efa_dev, "Failed to init AH cache\n"); + return err; + } + aq->depth = EFA_ADMIN_QUEUE_DEPTH; aq->dmadev = edev->dmadev; @@ -794,7 +802,7 @@ int efa_com_admin_init(struct efa_com_dev *edev, err = efa_com_init_comp_ctxt(aq); if (err) - return err; + goto err_destroy_ah_cache; err = efa_com_admin_init_sq(edev); if (err) @@ -832,6 +840,8 @@ int efa_com_admin_init(struct efa_com_dev *edev, aq->sq.entries, aq->sq.dma_addr); err_destroy_comp_ctxt: devm_kfree(edev->dmadev, aq->comp_ctx); +err_destroy_ah_cache: + efa_ah_cache_destroy(&edev->ah_cache); return err; } diff --git a/drivers/infiniband/hw/efa/efa_com.h b/drivers/infiniband/hw/efa/efa_com.h index f8c692b0e092..599db9d583bf 100644 --- a/drivers/infiniband/hw/efa/efa_com.h +++ b/drivers/infiniband/hw/efa/efa_com.h @@ -14,6 +14,7 @@ #include +#include "efa_ah_cache.h" #include "efa_common_defs.h" #include "efa_admin_defs.h" #include "efa_admin_cmds_defs.h" @@ -113,6 +114,8 @@ struct efa_com_dev { u32 supported_features; u32 dma_addr_bits; + struct efa_ah_cache ah_cache; + u32 dev_api_ver; struct efa_com_mmio_read mmio_read; };