// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include "arch/ops.h"
#if WITH_KERNEL_PCIE

#include <lib/counters.h>
#include <platform.h>
#include <zircon/rights.h>

#include <fbl/alloc_checker.h>
#include <kernel/auto_lock.h>
#include <object/interrupt_dispatcher.h>
#include <object/pci_device_dispatcher.h>
#include <object/pci_interrupt_dispatcher.h>

KCOUNTER(dispatcher_pci_interrupt_create_count, "dispatcher.pci_interrupt.create")
KCOUNTER(dispatcher_pci_interrupt_destroy_count, "dispatcher.pci_interrupt.destroy")

PciInterruptDispatcher::~PciInterruptDispatcher() {
  kcounter_add(dispatcher_pci_interrupt_destroy_count, 1);

  // Release our reference to our device.
  device_ = nullptr;
}

pcie_irq_handler_retval_t PciInterruptDispatcher::IrqThunk(const PcieDevice& dev, uint irq_id,
                                                           void* ctx) {
  DEBUG_ASSERT(ctx);
  auto thiz = reinterpret_cast<PciInterruptDispatcher*>(ctx);
  thiz->InterruptHandler();
  return PCIE_IRQRET_MASK;
}

zx_status_t PciInterruptDispatcher::Create(const fbl::RefPtr<PcieDevice>& device, uint32_t irq_id,
                                           bool maskable, zx_rights_t* out_rights,
                                           KernelHandle<InterruptDispatcher>* out_interrupt) {
  // Sanity check our args
  if (!device || !out_rights || !out_interrupt) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (!is_valid_interrupt(irq_id, 0)) {
    return ZX_ERR_INTERNAL;
  }

  // Attempt to allocate a new dispatcher wrapper.
  // Do not create a KernelHandle until all initialization has succeeded;
  // if an interrupt already exists on |vector| our on_zero_handles() would
  // tear down the existing interrupt when creation fails.
  fbl::AllocChecker ac;
  auto interrupt_dispatcher =
      fbl::AdoptRef(new (&ac) PciInterruptDispatcher(device, irq_id, maskable));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  Guard<Mutex> guard{interrupt_dispatcher->get_lock()};

  // The PcieDevice class contains a mutex that guards device access and can be
  // contended between the PciInterruptDispatcher and the protocol methods used
  // by the drivers downstream. For safe locking & scheduling considerations we
  // need to ensure the InterruptDispatcher's spinlock is not held when calling
  // into this dispatcher to unmask an interrupt. Masking is handled by the pci
  // bus driver itself during operation.
  zx_status_t status = interrupt_dispatcher->set_flags(INTERRUPT_UNMASK_PREWAIT_UNLOCKED);
  if (status != ZX_OK) {
    return status;
  }

  // Register the interrupt
  status = interrupt_dispatcher->RegisterInterruptHandler();
  if (status != ZX_OK) {
    return status;
  }

  // Everything seems to have gone well.  Make sure the interrupt is unmasked
  // (if it is maskable) then transfer our dispatcher reference to the
  // caller.
  if (maskable) {
    device->UnmaskIrq(irq_id);
  }
  out_interrupt->reset(ktl::move(interrupt_dispatcher));
  *out_rights = ZX_DEFAULT_PCI_INTERRUPT_RIGHTS;
  return ZX_OK;
}

// This is only called in the InterruptDispatcher::Destroy() path which does not
// hold the InterruptDispatcher spinlock. The interrupt is masked before the
// interrupt handler is unregistered and the InterruptDispatcher is freed.
void PciInterruptDispatcher::MaskInterrupt() {
  DEBUG_ASSERT(arch_num_spinlocks_held() == 0);
  // MaskInterrupt should never be called by the InterruptDispatcher.
  if (maskable_) {
    device_->MaskIrq(vector_);
  }
}

void PciInterruptDispatcher::UnmaskInterrupt() {
  DEBUG_ASSERT(arch_num_spinlocks_held() == 0);
  if (maskable_) {
    device_->UnmaskIrq(vector_);
  }
}

void PciInterruptDispatcher::DeactivateInterrupt() { }

PciInterruptDispatcher::PciInterruptDispatcher(const fbl::RefPtr<PcieDevice>& device,
                                               uint32_t vector, bool maskable)
    : device_(device), vector_(vector), maskable_(maskable) {
  kcounter_add(dispatcher_pci_interrupt_create_count, 1);
}

zx_status_t PciInterruptDispatcher::RegisterInterruptHandler() {
  return device_->RegisterIrqHandler(vector_, IrqThunk, this);
}

void PciInterruptDispatcher::UnregisterInterruptHandler() {
  device_->RegisterIrqHandler(vector_, nullptr, nullptr);
}

#endif  // if WITH_KERNEL_PCIE
