^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright 2017 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/sched/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "ocxl_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) int ocxl_context_alloc(struct ocxl_context **context, struct ocxl_afu *afu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct address_space *mapping)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) int pasid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct ocxl_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) ctx->afu = afu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) mutex_lock(&afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) pasid = idr_alloc(&afu->contexts_idr, ctx, afu->pasid_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) afu->pasid_base + afu->pasid_max, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (pasid < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) mutex_unlock(&afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return pasid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) afu->pasid_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) mutex_unlock(&afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ctx->pasid = pasid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ctx->status = OPENED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) mutex_init(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ctx->mapping = mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mutex_init(&ctx->mapping_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) init_waitqueue_head(&ctx->events_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) mutex_init(&ctx->xsl_error_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) mutex_init(&ctx->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) idr_init(&ctx->irq_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ctx->tidr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Keep a reference on the AFU to make sure it's valid for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * duration of the life of the context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ocxl_afu_get(afu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *context = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL_GPL(ocxl_context_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Callback for when a translation fault triggers an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * data: a pointer to the context which triggered the fault
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * addr: the address that triggered the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * dsisr: the value of the PPC64 dsisr register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void xsl_fault_error(void *data, u64 addr, u64 dsisr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct ocxl_context *ctx = (struct ocxl_context *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) mutex_lock(&ctx->xsl_error_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ctx->xsl_error.addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ctx->xsl_error.dsisr = dsisr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ctx->xsl_error.count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mutex_unlock(&ctx->xsl_error_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) wake_up_all(&ctx->events_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int ocxl_context_attach(struct ocxl_context *ctx, u64 amr, struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long pidr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) // Locks both status & tidr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) mutex_lock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ctx->status != OPENED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pidr = mm->context.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, pidr, ctx->tidr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) amr, mm, xsl_fault_error, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ctx->status = ATTACHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) mutex_unlock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) EXPORT_SYMBOL_GPL(ocxl_context_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static vm_fault_t map_afu_irq(struct vm_area_struct *vma, unsigned long address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u64 offset, struct ocxl_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u64 trigger_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int irq_id = ocxl_irq_offset_to_id(ctx, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) trigger_addr = ocxl_afu_irq_get_addr(ctx, irq_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!trigger_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return vmf_insert_pfn(vma, address, trigger_addr >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static vm_fault_t map_pp_mmio(struct vm_area_struct *vma, unsigned long address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u64 offset, struct ocxl_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u64 pp_mmio_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int pasid_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) vm_fault_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (offset >= ctx->afu->config.pp_mmio_stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mutex_lock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ctx->status != ATTACHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mutex_unlock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) pr_debug("%s: Context not attached, failing mmio mmap\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) pasid_off = ctx->pasid - ctx->afu->pasid_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pp_mmio_addr = ctx->afu->pp_mmio_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pasid_off * ctx->afu->config.pp_mmio_stride +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = vmf_insert_pfn(vma, address, pp_mmio_addr >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mutex_unlock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static vm_fault_t ocxl_mmap_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct vm_area_struct *vma = vmf->vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct ocxl_context *ctx = vma->vm_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) vm_fault_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) offset = vmf->pgoff << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_debug("%s: pasid %d address 0x%lx offset 0x%llx\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ctx->pasid, vmf->address, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (offset < ctx->afu->irq_base_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret = map_pp_mmio(vma, vmf->address, offset, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ret = map_afu_irq(vma, vmf->address, offset, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static const struct vm_operations_struct ocxl_vmops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .fault = ocxl_mmap_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int check_mmap_afu_irq(struct ocxl_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int irq_id = ocxl_irq_offset_to_id(ctx, vma->vm_pgoff << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* only one page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (vma_pages(vma) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* check offset validty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!ocxl_afu_irq_get_addr(ctx, irq_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * trigger page should only be accessible in write mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * It's a bit theoretical, as a page mmaped with only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * PROT_WRITE is currently readable, but it doesn't hurt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if ((vma->vm_flags & VM_READ) || (vma->vm_flags & VM_EXEC) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) !(vma->vm_flags & VM_WRITE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) vma->vm_flags &= ~(VM_MAYREAD | VM_MAYEXEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int check_mmap_mmio(struct ocxl_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if ((vma_pages(vma) + vma->vm_pgoff) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) (ctx->afu->config.pp_mmio_stride >> PAGE_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int ocxl_context_mmap(struct ocxl_context *ctx, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if ((vma->vm_pgoff << PAGE_SHIFT) < ctx->afu->irq_base_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) rc = check_mmap_mmio(ctx, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) rc = check_mmap_afu_irq(ctx, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) vma->vm_flags |= VM_IO | VM_PFNMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) vma->vm_ops = &ocxl_vmops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int ocxl_context_detach(struct ocxl_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct pci_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int afu_control_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) enum ocxl_context_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) mutex_lock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) status = ctx->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ctx->status = CLOSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) mutex_unlock(&ctx->status_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (status != ATTACHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dev = to_pci_dev(ctx->afu->fn->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) afu_control_pos = ctx->afu->config.dvsec_afu_control_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) mutex_lock(&ctx->afu->afu_control_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) rc = ocxl_config_terminate_pasid(dev, afu_control_pos, ctx->pasid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mutex_unlock(&ctx->afu->afu_control_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) trace_ocxl_terminate_pasid(ctx->pasid, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * If we timeout waiting for the AFU to terminate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * pasid, then it's dangerous to clean up the Process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Element entry in the SPA, as it may be referenced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * in the future by the AFU. In which case, we would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * checkstop because of an invalid PE access (FIR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * register 2, bit 42). So leave the PE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * defined. Caller shouldn't free the context so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * PASID remains allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * A link reset will be required to cleanup the AFU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * and the SPA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (rc == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) rc = ocxl_link_remove_pe(ctx->afu->fn->link, ctx->pasid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dev_warn(&dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) "Couldn't remove PE entry cleanly: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) EXPORT_SYMBOL_GPL(ocxl_context_detach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) void ocxl_context_detach_all(struct ocxl_afu *afu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct ocxl_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mutex_lock(&afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) idr_for_each_entry(&afu->contexts_idr, ctx, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ocxl_context_detach(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * We are force detaching - remove any active mmio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * mappings so userspace cannot interfere with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * card if it comes back. Easiest way to exercise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * this is to unbind and rebind the driver via sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * while it is in use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_lock(&ctx->mapping_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ctx->mapping)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unmap_mapping_range(ctx->mapping, 0, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mutex_unlock(&ctx->mapping_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mutex_unlock(&afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) void ocxl_context_free(struct ocxl_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mutex_lock(&ctx->afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ctx->afu->pasid_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) idr_remove(&ctx->afu->contexts_idr, ctx->pasid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) mutex_unlock(&ctx->afu->contexts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ocxl_afu_irq_free_all(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) idr_destroy(&ctx->irq_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* reference to the AFU taken in ocxl_context_alloc() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ocxl_afu_put(ctx->afu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) EXPORT_SYMBOL_GPL(ocxl_context_free);