^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Adaptec AAC series RAID controller driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (c) Copyright 2001 Red Hat Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * based on the old aacraid driver that is..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Adaptec aacraid device driver for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2000-2010 Adaptec, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Module Name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * src.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Abstract: Hardware Device Interface for PMC SRC based controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "aacraid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int aac_src_get_sync_status(struct aac_dev *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct aac_msix_ctx *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct aac_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned long bellbits, bellbits_shifted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int isFastResponse, mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 index, handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ctx = (struct aac_msix_ctx *)dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) vector_no = ctx->vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (dev->msi_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) mode = AAC_INT_MODE_MSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (vector_no == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) bellbits = src_readl(dev, MUnit.ODR_MSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (bellbits & 0x40000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mode |= AAC_INT_MODE_AIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (bellbits & 0x1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) mode |= AAC_INT_MODE_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mode = AAC_INT_MODE_INTX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) bellbits = src_readl(dev, MUnit.ODR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (bellbits & PmDoorBellResponseSent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) bellbits = PmDoorBellResponseSent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) src_writel(dev, MUnit.ODR_C, bellbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) src_readl(dev, MUnit.ODR_C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) src_writel(dev, MUnit.ODR_C, bellbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) src_readl(dev, MUnit.ODR_C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (bellbits_shifted & DoorBellAifPending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mode |= AAC_INT_MODE_AIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) else if (bellbits_shifted & OUTBOUNDDOORBELL_0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) mode |= AAC_INT_MODE_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (mode & AAC_INT_MODE_SYNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long sflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct list_head *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int send_it = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) extern int aac_sync_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!aac_sync_mode && !dev->msi_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) src_writel(dev, MUnit.ODR_C, bellbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) src_readl(dev, MUnit.ODR_C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (dev->sync_fib) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (dev->sync_fib->callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dev->sync_fib->callback(dev->sync_fib->callback_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dev->sync_fib);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) spin_lock_irqsave(&dev->sync_fib->event_lock, sflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev->management_fib_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) complete(&dev->sync_fib->event_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) spin_unlock_irqrestore(&dev->sync_fib->event_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) spin_lock_irqsave(&dev->sync_lock, sflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!list_empty(&dev->sync_fib_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) entry = dev->sync_fib_list.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev->sync_fib = list_entry(entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct fib,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) fiblink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) list_del(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) send_it = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev->sync_fib = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) spin_unlock_irqrestore(&dev->sync_lock, sflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (send_it) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) (u32)dev->sync_fib->hw_fib_pa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (mode & AAC_INT_MODE_AIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* handle AIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (dev->sa_firmware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u32 events = src_readl(dev, MUnit.SCR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) aac_intr_normal(dev, events, 1, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) writel(events, &dev->IndexRegs->Mailbox[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) src_writel(dev, MUnit.IDR, 1 << 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (dev->aif_thread && dev->fsa_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) aac_intr_normal(dev, 0, 2, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) index = dev->host_rrq_idx[vector_no];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) isFastResponse = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* remove toggle bit (31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) handle = le32_to_cpu((dev->host_rrq[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) & 0x7fffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* check fast response bits (30, 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (handle & 0x40000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) isFastResponse = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) handle &= 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (handle == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) handle >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (dev->msi_enabled && dev->max_msix > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) atomic_dec(&dev->rrq_outstanding[vector_no]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) aac_intr_normal(dev, handle, 0, isFastResponse, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dev->host_rrq[index++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (index == (vector_no + 1) * dev->vector_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) index = vector_no * dev->vector_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dev->host_rrq_idx[vector_no] = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * aac_src_disable_interrupt - Disable interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void aac_src_disable_interrupt(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * aac_src_enable_interrupt_message - Enable interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void aac_src_enable_interrupt_message(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) aac_src_access_devreg(dev, AAC_ENABLE_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * src_sync_cmd - send a command and wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * @command: Command to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * @p1: first parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @p2: second parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @p3: third parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @p4: forth parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @p5: fifth parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @p6: sixth parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @status: adapter status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * @r1: first return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @r2: second return valu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @r3: third return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * @r4: forth return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * This routine will send a synchronous command to the adapter and wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * for its completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int src_sync_cmd(struct aac_dev *dev, u32 command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned long delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Write the command into Mailbox 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) writel(command, &dev->IndexRegs->Mailbox[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * Write the parameters into Mailboxes 1 - 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) writel(p1, &dev->IndexRegs->Mailbox[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) writel(p2, &dev->IndexRegs->Mailbox[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) writel(p3, &dev->IndexRegs->Mailbox[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) writel(p4, &dev->IndexRegs->Mailbox[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * Clear the synch command doorbell to start on a clean slate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Disable doorbell interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Force the completion of the mask register write before issuing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) src_readl(dev, MUnit.OIMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * Signal that there is a new synch command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if ((!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) !dev->in_soft_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (command == IOP_RESET_ALWAYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Wait up to 10 sec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) delay = 10*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Wait up to 5 minutes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) delay = 300*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) while (time_before(jiffies, start+delay)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) udelay(5); /* Delay 5 microseconds to let Mon960 get info. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Mon960 will set doorbell0 bit when it has completed the command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Clear the doorbell.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) aac_src_access_devreg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) AAC_CLEAR_SYNC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Yield the processor in case we are slow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (unlikely(ok != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Restore interrupt mask even though we timed out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Pull the synch status from Mailbox 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *status = readl(&dev->IndexRegs->Mailbox[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *r1 = readl(&dev->IndexRegs->Mailbox[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (r2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) *r2 = readl(&dev->IndexRegs->Mailbox[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *r3 = readl(&dev->IndexRegs->Mailbox[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (r4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *r4 = readl(&dev->IndexRegs->Mailbox[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (command == GET_COMM_PREFERRED_SETTINGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dev->max_msix =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) readl(&dev->IndexRegs->Mailbox[5]) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Clear the synch command doorbell.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * Restore interrupt mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * aac_src_interrupt_adapter - interrupt adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * Send an interrupt to the i960 and breakpoint it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void aac_src_interrupt_adapter(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) src_sync_cmd(dev, BREAKPOINT_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * aac_src_notify_adapter - send an event to the adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * @event: Event to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * Notify the i960 that something it probably cares about has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * happened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case AdapNormCmdQue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case HostNormRespNotFull:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) case AdapNormRespQue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case HostNormCmdNotFull:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case FastIo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case AdapPrintfDone:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * aac_src_start_adapter - activate adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Start up processing on an i960 based AAC adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static void aac_src_start_adapter(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) union aac_init *init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* reset host_rrq_idx first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) for (i = 0; i < dev->max_msix; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dev->host_rrq_idx[i] = i * dev->vector_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) atomic_set(&dev->rrq_outstanding[i], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) atomic_set(&dev->msix_counter, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) dev->fibs_pushed_no = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) init = dev->init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) init->r8.host_elapsed_seconds =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) cpu_to_le32(ktime_get_real_seconds());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) lower_32_bits(dev->init_pa),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) upper_32_bits(dev->init_pa),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) sizeof(struct _r8) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) (AAC_MAX_HRRQ - 1) * sizeof(struct _rrq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) init->r7.host_elapsed_seconds =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) cpu_to_le32(ktime_get_real_seconds());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) // We can only use a 32 bit address here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * aac_src_check_health
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * @dev: device to check if healthy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * Will attempt to determine if the specified adapter is alive and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * capable of handling requests, returning 0 if alive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static int aac_src_check_health(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) u32 status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Check to see if the board panic'd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (unlikely(status & KERNEL_PANIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto err_blink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * Check to see if the board failed any self tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (unlikely(status & SELF_TEST_FAILED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Check to see if the board failed any self tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (unlikely(status & MONITOR_PANIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * Wait for the adapter to be up and running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * Everything is OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) err_blink:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return (status >> 16) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static inline u32 aac_get_vector(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return atomic_inc_return(&dev->msix_counter)%dev->max_msix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * aac_src_deliver_message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @fib: fib to issue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Will send a fib, returning 0 if successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int aac_src_deliver_message(struct fib *fib)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct aac_dev *dev = fib->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) u32 fibsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) dma_addr_t address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct aac_fib_xporthdr *pFibX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int native_hba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) #if !defined(writeq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) u16 vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) atomic_inc(&q->numpending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) native_hba = (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (dev->msi_enabled && dev->max_msix > 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) (native_hba || fib->hw_fib_va->header.Command != AifRequest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) && dev->sa_firmware)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) vector_no = aac_get_vector(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) vector_no = fib->vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (native_hba) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct aac_hba_tm_req *tm_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) tm_req = (struct aac_hba_tm_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fib->hw_fib_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (tm_req->iu_type ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) HBA_IU_TYPE_SCSI_TM_REQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ((struct aac_hba_tm_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fib->hw_fib_va)->reply_qid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) = vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ((struct aac_hba_tm_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) fib->hw_fib_va)->request_id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) += (vector_no << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ((struct aac_hba_reset_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) fib->hw_fib_va)->reply_qid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) = vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ((struct aac_hba_reset_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) fib->hw_fib_va)->request_id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) += (vector_no << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ((struct aac_hba_cmd_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) fib->hw_fib_va)->reply_qid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) = vector_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ((struct aac_hba_cmd_req *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) fib->hw_fib_va)->request_id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) += (vector_no << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) fib->hw_fib_va->header.Handle += (vector_no << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) vector_no = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) atomic_inc(&dev->rrq_outstanding[vector_no]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (native_hba) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) address = fib->hw_fib_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) fibsize = (fib->hbacmd_size + 127) / 128 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (fibsize > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) fibsize = 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) address |= fibsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) #if defined(writeq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) src_writeq(dev, MUnit.IQN_L, (u64)address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) spin_lock_irqsave(&fib->dev->iq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) src_writel(dev, MUnit.IQN_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) upper_32_bits(address) & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) src_writel(dev, MUnit.IQN_L, address & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* Calculate the amount to the fibsize bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) fibsize = (le16_to_cpu(fib->hw_fib_va->header.Size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) + 127) / 128 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* New FIB header, 32-bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) address = fib->hw_fib_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) fib->hw_fib_va->header.StructType = FIB_MAGIC2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) fib->hw_fib_va->header.SenderFibAddress =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) cpu_to_le32((u32)address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) fib->hw_fib_va->header.u.TimeStamp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) WARN_ON(upper_32_bits(address) != 0L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* Calculate the amount to the fibsize bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) fibsize = (sizeof(struct aac_fib_xporthdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) le16_to_cpu(fib->hw_fib_va->header.Size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) + 127) / 128 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /* Fill XPORT header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) pFibX = (struct aac_fib_xporthdr *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ((unsigned char *)fib->hw_fib_va -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) sizeof(struct aac_fib_xporthdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) pFibX->Handle = fib->hw_fib_va->header.Handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) pFibX->HostAddress =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) cpu_to_le64((u64)fib->hw_fib_pa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) pFibX->Size = cpu_to_le32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) le16_to_cpu(fib->hw_fib_va->header.Size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) address = fib->hw_fib_pa -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) (u64)sizeof(struct aac_fib_xporthdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (fibsize > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) fibsize = 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) address |= fibsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) #if defined(writeq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) src_writeq(dev, MUnit.IQ_L, (u64)address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) spin_lock_irqsave(&fib->dev->iq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) src_writel(dev, MUnit.IQ_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) upper_32_bits(address) & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * aac_src_ioremap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @dev: device ioremap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @size: mapping resize request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int aac_src_ioremap(struct aac_dev *dev, u32 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) iounmap(dev->regs.src.bar1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) dev->regs.src.bar1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) iounmap(dev->regs.src.bar0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) dev->base = dev->regs.src.bar0 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) AAC_MIN_SRC_BAR1_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) dev->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (dev->regs.src.bar1 == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (dev->base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) iounmap(dev->regs.src.bar1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dev->regs.src.bar1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) dev->IndexRegs = &((struct src_registers __iomem *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dev->base)->u.tupelo.IndexRegs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * aac_srcv_ioremap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * @dev: device ioremap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * @size: mapping resize request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (!size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) iounmap(dev->regs.src.bar0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) dev->base = dev->regs.src.bar0 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) dev->regs.src.bar1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ioremap(pci_resource_start(dev->pdev, 2), AAC_MIN_SRCV_BAR1_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dev->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (dev->regs.src.bar1 == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (dev->base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) iounmap(dev->regs.src.bar1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) dev->regs.src.bar1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) dev->IndexRegs = &((struct src_registers __iomem *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev->base)->u.denali.IndexRegs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) void aac_set_intx_mode(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (dev->msi_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) aac_src_access_devreg(dev, AAC_ENABLE_INTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev->msi_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) msleep(5000); /* Delay 5 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void aac_clear_omr(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) u32 omr_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) omr_value = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Check for PCI Errors or Kernel Panic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if ((omr_value == INVALID_OMR) || (omr_value & KERNEL_PANIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) omr_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * Preserve MSIX Value if any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) src_writel(dev, MUnit.OMR, omr_value & AAC_INT_MODE_MSIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) __le32 supported_options3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!aac_fib_dump)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) supported_options3 = dev->supplement_adapter_info.supported_options3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (!(supported_options3 & AAC_OPTION_SUPPORTED3_IOP_RESET_FIB_DUMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) aac_adapter_sync_cmd(dev, IOP_RESET_FW_FIB_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static bool aac_is_ctrl_up_and_running(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) bool ctrl_up = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) unsigned long status, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) bool is_up = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (status == 0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (status & KERNEL_BOOTING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (time_after(jiffies, start+HZ*SOFT_RESET_TIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ctrl_up = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) is_up = status & KERNEL_UP_AND_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) } while (!is_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return ctrl_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static void aac_src_drop_io(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!dev->soft_reset_support)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) aac_adapter_sync_cmd(dev, DROP_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static void aac_notify_fw_of_iop_reset(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) NULL, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) aac_src_drop_io(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static void aac_send_iop_reset(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) aac_dump_fw_fib_iop_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) aac_notify_fw_of_iop_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) aac_set_intx_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) aac_clear_omr(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) msleep(5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static void aac_send_hardware_soft_reset(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) u_int32_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) aac_clear_omr(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) val = readl(((char *)(dev->base) + IBW_SWR_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) val |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) msleep_interruptible(20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) bool is_ctrl_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (bled < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto invalid_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (bled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) dev_err(&dev->pdev->dev, "adapter kernel panic'd %x.\n", bled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * When there is a BlinkLED, IOP_RESET has not effect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (bled >= 2 && dev->sa_firmware && reset_type & HW_IOP_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) reset_type &= ~HW_IOP_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_err(&dev->pdev->dev, "Controller reset type is %d\n", reset_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (reset_type & HW_IOP_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dev_info(&dev->pdev->dev, "Issuing IOP reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) aac_send_iop_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * Creates a delay or wait till up and running comes thru
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) is_ctrl_up = aac_is_ctrl_up_and_running(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (!is_ctrl_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dev_err(&dev->pdev->dev, "IOP reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) dev_info(&dev->pdev->dev, "IOP reset succeeded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) goto set_startup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (!dev->sa_firmware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dev_err(&dev->pdev->dev, "ARC Reset attempt failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (reset_type & HW_SOFT_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev_info(&dev->pdev->dev, "Issuing SOFT reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) aac_send_hardware_soft_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev->msi_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) is_ctrl_up = aac_is_ctrl_up_and_running(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!is_ctrl_up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dev_err(&dev->pdev->dev, "SOFT reset failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) dev_info(&dev->pdev->dev, "SOFT reset succeeded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) set_startup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (startup_timeout < 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) startup_timeout = 300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) invalid_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * aac_src_select_comm - Select communications method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * @dev: Adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * @comm: communications method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static int aac_src_select_comm(struct aac_dev *dev, int comm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) switch (comm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case AAC_COMM_MESSAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) dev->a_ops.adapter_intr = aac_src_intr_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) dev->a_ops.adapter_deliver = aac_src_deliver_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * aac_src_init - initialize an Cardinal Frey Bar card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * @dev: device to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) int aac_src_init(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) int instance = dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) const char *name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) dev->a_ops.adapter_ioremap = aac_src_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev->a_ops.adapter_comm = aac_src_select_comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (aac_adapter_ioremap(dev, dev->base_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) printk(KERN_WARNING "%s: unable to map adapter.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* Failure to reset here is an option ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev->a_ops.adapter_sync_cmd = src_sync_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (dev->init_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) dev->init_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * Check to see if the board panic'd while booting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (status & KERNEL_PANIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (aac_src_restart_adapter(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) aac_src_check_health(dev), IOP_HWSOFT_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * Check to see if the board failed any self tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (status & SELF_TEST_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) printk(KERN_ERR "%s%d: adapter self-test failed.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dev->name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * Check to see if the monitor panic'd while booting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (status & MONITOR_PANIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) printk(KERN_ERR "%s%d: adapter monitor panic.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) dev->name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * Wait for the adapter to be up and running. Wait up to 3 minutes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) while (!((status = src_readl(dev, MUnit.OMR)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) KERNEL_UP_AND_RUNNING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if ((restart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) time_after(jiffies, start+HZ*startup_timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) dev->name, instance, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (!restart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) time_after(jiffies, start + HZ *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ((startup_timeout > 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ? (startup_timeout - 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) : (startup_timeout / 2))))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (likely(!aac_src_restart_adapter(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) aac_src_check_health(dev), IOP_HWSOFT_RESET)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (restart && aac_commit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) aac_commit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * Fill in the common function dispatch table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) dev->a_ops.adapter_notify = aac_src_notify_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) dev->a_ops.adapter_sync_cmd = src_sync_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) dev->a_ops.adapter_check_health = aac_src_check_health;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dev->a_ops.adapter_restart = aac_src_restart_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) dev->a_ops.adapter_start = aac_src_start_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * First clear out all interrupts. Then enable the one's that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * can handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) aac_adapter_comm(dev, AAC_COMM_MESSAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) aac_adapter_disable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) src_writel(dev, MUnit.ODR_C, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (aac_init_adapter(dev) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dev->msi = !pci_enable_msi(dev->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev->aac_msix[0].vector_no = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dev->aac_msix[0].dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) IRQF_SHARED, "aacraid", &(dev->aac_msix[0])) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (dev->msi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) pci_disable_msi(dev->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) dev->dbg_base = pci_resource_start(dev->pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) dev->dbg_base_mapped = dev->regs.src.bar1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!dev->sync_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * Tell the adapter that all is configured, and it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * start accepting requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) aac_src_start_adapter(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) error_iounmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static int aac_src_wait_sync(struct aac_dev *dev, int *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) unsigned long start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) unsigned long usecs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int delay = 5 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) while (time_before(jiffies, start+delay)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * Delay 5 microseconds to let Mon960 get info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * Mon960 will set doorbell0 bit when it has completed the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * Clear: the doorbell.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) aac_src_access_devreg(dev, AAC_CLEAR_SYNC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) src_writel(dev, MUnit.ODR_C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * Yield the processor in case we are slow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) usecs = 1 * USEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) usleep_range(usecs, usecs + 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * Pull the synch status from Mailbox 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (status && !rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) status[0] = readl(&dev->IndexRegs->Mailbox[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) status[1] = readl(&dev->IndexRegs->Mailbox[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) status[2] = readl(&dev->IndexRegs->Mailbox[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) status[3] = readl(&dev->IndexRegs->Mailbox[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) status[4] = readl(&dev->IndexRegs->Mailbox[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * aac_src_soft_reset - perform soft reset to speed up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * Assumptions: That the controller is in a state where we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * bring it back to life with an init struct. We can only use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * fast sync commands, as the timeout is 5 seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * @dev: device to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static int aac_src_soft_reset(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) u32 status_omr = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) u32 status[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) int state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) char *state_str[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) "GET_ADAPTER_PROPERTIES Failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) "GET_ADAPTER_PROPERTIES timeout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) "SOFT_RESET not supported",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) "DROP_IO Failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) "DROP_IO timeout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) "Check Health failed"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (status_omr == INVALID_OMR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return 1; // pcie hosed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (!(status_omr & KERNEL_UP_AND_RUNNING))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 1; // not up and running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * We go into soft reset mode to allow us to handle response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dev->in_soft_reset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) dev->msi_enabled = status_omr & AAC_INT_MODE_MSIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /* Get adapter properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) rc = aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 0, 0, 0, status+0, status+1, status+2, status+3, status+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (aac_src_wait_sync(dev, status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (!(status[1] & le32_to_cpu(AAC_OPT_EXTENDED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) (status[4] & le32_to_cpu(AAC_EXTOPT_SOFT_RESET)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) rc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if ((status[1] & le32_to_cpu(AAC_OPT_EXTENDED)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) (status[4] & le32_to_cpu(AAC_EXTOPT_SA_FIRMWARE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) dev->sa_firmware = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) rc = aac_adapter_sync_cmd(dev, DROP_IO, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) status+0, status+1, status+2, status+3, status+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (aac_src_wait_sync(dev, status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) rc = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (status[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) dev_err(&dev->pdev->dev, "%s: %d outstanding I/O pending\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) __func__, status[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) rc = aac_src_check_health(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) dev->in_soft_reset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) dev->msi_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) dev_err(&dev->pdev->dev, "%s: %s status = %d", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) state_str[state], rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * aac_srcv_init - initialize an SRCv card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * @dev: device to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) int aac_srcv_init(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) int restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) int instance = dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) const char *name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dev->a_ops.adapter_comm = aac_src_select_comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dev->base_size = AAC_MIN_SRCV_BAR0_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (aac_adapter_ioremap(dev, dev->base_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) printk(KERN_WARNING "%s: unable to map adapter.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* Failure to reset here is an option ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) dev->a_ops.adapter_sync_cmd = src_sync_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (dev->init_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) dev->init_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (aac_src_soft_reset(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * Check to see if flash update is running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * Wait for the adapter to be up and running. Wait up to 5 minutes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (status & FLASH_UPD_PENDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (time_after(jiffies, start+HZ*FWUPD_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) printk(KERN_ERR "%s%d: adapter flash update failed.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) dev->name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) } while (!(status & FLASH_UPD_SUCCESS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) !(status & FLASH_UPD_FAILED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) /* Delay 10 seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * Because right now FW is doing a soft reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * do not read scratch pad register at this time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ssleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * Check to see if the board panic'd while booting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (status & KERNEL_PANIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (aac_src_restart_adapter(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) aac_src_check_health(dev), IOP_HWSOFT_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * Check to see if the board failed any self tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (status & SELF_TEST_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * Check to see if the monitor panic'd while booting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (status & MONITOR_PANIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * Wait for the adapter to be up and running. Wait up to 3 minutes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) status = src_readl(dev, MUnit.OMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (status == INVALID_OMR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if ((restart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) time_after(jiffies, start+HZ*startup_timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) dev->name, instance, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (!restart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) time_after(jiffies, start + HZ *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) ((startup_timeout > 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) ? (startup_timeout - 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) : (startup_timeout / 2))))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (likely(!aac_src_restart_adapter(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) aac_src_check_health(dev), IOP_HWSOFT_RESET)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) ++restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) } while (!(status & KERNEL_UP_AND_RUNNING));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (restart && aac_commit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) aac_commit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * Fill in the common function dispatch table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dev->a_ops.adapter_notify = aac_src_notify_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) dev->a_ops.adapter_sync_cmd = src_sync_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) dev->a_ops.adapter_check_health = aac_src_check_health;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) dev->a_ops.adapter_restart = aac_src_restart_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) dev->a_ops.adapter_start = aac_src_start_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * First clear out all interrupts. Then enable the one's that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * can handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) aac_adapter_comm(dev, AAC_COMM_MESSAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) aac_adapter_disable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) src_writel(dev, MUnit.ODR_C, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (aac_init_adapter(dev) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if ((dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (dev->msi_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (aac_acquire_irq(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) goto error_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) dev->dbg_base = pci_resource_start(dev->pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) dev->dbg_base_mapped = dev->regs.src.bar1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) aac_adapter_enable_int(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (!dev->sync_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * Tell the adapter that all is configured, and it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * start accepting requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) aac_src_start_adapter(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) error_iounmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) void aac_src_access_devreg(struct aac_dev *dev, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) u_int32_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) case AAC_ENABLE_INTERRUPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) MUnit.OIMR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) dev->OIMR = (dev->msi_enabled ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) AAC_INT_ENABLE_TYPE1_MSIX :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) AAC_INT_ENABLE_TYPE1_INTX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) case AAC_DISABLE_INTERRUPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) MUnit.OIMR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) dev->OIMR = AAC_INT_DISABLE_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) case AAC_ENABLE_MSIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /* set bit 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) val = src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) val |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) src_writel(dev, MUnit.IDR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /* unmask int. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) val = PMC_ALL_INTERRUPT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) src_writel(dev, MUnit.IOAR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) val = src_readl(dev, MUnit.OIMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) src_writel(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) MUnit.OIMR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) case AAC_DISABLE_MSIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* reset bit 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) val = src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) val &= ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) src_writel(dev, MUnit.IDR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) case AAC_CLEAR_AIF_BIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* set bit 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) val = src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) val |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) src_writel(dev, MUnit.IDR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) case AAC_CLEAR_SYNC_BIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) /* set bit 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) val = src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) val |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) src_writel(dev, MUnit.IDR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) case AAC_ENABLE_INTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) /* set bit 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) val = src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) val |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) src_writel(dev, MUnit.IDR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) src_readl(dev, MUnit.IDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /* unmask int. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) val = PMC_ALL_INTERRUPT_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) src_writel(dev, MUnit.IOAR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) src_readl(dev, MUnit.IOAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) val = src_readl(dev, MUnit.OIMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) src_writel(dev, MUnit.OIMR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) val & (~(PMC_GLOBAL_INT_BIT2)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static int aac_src_get_sync_status(struct aac_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) int msix_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) int legacy_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) msix_val = src_readl(dev, MUnit.ODR_MSI) & SRC_MSI_READ_MASK ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (!dev->msi_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * if Legacy int status indicates cmd is not complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * sample MSIx register to see if it indiactes cmd complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * if yes set the controller in MSIx mode and consider cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) legacy_val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (!(legacy_val & 1) && msix_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dev->msi_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return legacy_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) return msix_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }