Commit a01e28f6 authored by Dasaratharaman Chandramouli's avatar Dasaratharaman Chandramouli Committed by Greg Kroah-Hartman

Intel MIC Host Driver Interrupt/SMPT support.

This patch enables the following features:
a) MSIx, MSI and legacy interrupt support.
b) System Memory Page Table(SMPT) support. SMPT enables system memory
   access from the card. On X100 devices the host can program 32 SMPT
   registers each capable of accessing 16GB of system memory
   address space from X100 devices. The registers can thereby be used
   to access a cumulative 512GB of system memory address space from
   X100 devices at any point in time.

Co-author: Sudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarCaz Yokoyama <Caz.Yokoyama@intel.com>
Signed-off-by: default avatarDasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>
Signed-off-by: default avatarNikhil Rao <nikhil.rao@intel.com>
Signed-off-by: default avatarHarshavardhan R Kharche <harshavardhan.r.kharche@intel.com>
Signed-off-by: default avatarSudeep Dutt <sudeep.dutt@intel.com>
Acked-by: default avatarYaozu (Eddie) Dong <eddie.dong@intel.com>
Reviewed-by: default avatarPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b170d8ce
......@@ -6,3 +6,5 @@ obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
mic_host-objs := mic_main.o
mic_host-objs += mic_x100.o
mic_host-objs += mic_sysfs.o
mic_host-objs += mic_smpt.o
mic_host-objs += mic_intr.o
......@@ -21,6 +21,10 @@
#ifndef _MIC_DEVICE_H_
#define _MIC_DEVICE_H_
#include <linux/idr.h>
#include "mic_intr.h"
/* The maximum number of MIC devices supported in a single host system. */
#define MIC_MAX_NUM_DEVS 256
......@@ -53,6 +57,12 @@ enum mic_stepping {
* @stepping: Stepping ID.
* @attr_group: Pointer to list of sysfs attribute groups.
* @sdev: Device for sysfs entries.
* @mic_mutex: Mutex for synchronizing access to mic_device.
* @intr_ops: HW specific interrupt operations.
* @smpt_ops: Hardware specific SMPT operations.
* @smpt: MIC SMPT information.
* @intr_info: H/W specific interrupt information.
* @irq_info: The OS specific irq information
*/
struct mic_device {
struct mic_mw mmio;
......@@ -63,6 +73,12 @@ struct mic_device {
enum mic_stepping stepping;
const struct attribute_group **attr_group;
struct device *sdev;
struct mutex mic_mutex;
struct mic_hw_intr_ops *intr_ops;
struct mic_smpt_ops *smpt_ops;
struct mic_smpt_info *smpt;
struct mic_intr_info *intr_info;
struct mic_irq_info irq_info;
};
/**
......@@ -71,12 +87,17 @@ struct mic_device {
* @mmio_bar: MMIO bar resource number.
* @read_spad: Read from scratch pad register.
* @write_spad: Write to scratch pad register.
* @send_intr: Send an interrupt for a particular doorbell on the card.
* @ack_interrupt: Hardware specific operations to ack the h/w on
* receipt of an interrupt.
*/
struct mic_hw_ops {
u8 aper_bar;
u8 mmio_bar;
u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
void (*send_intr)(struct mic_device *mdev, int doorbell);
u32 (*ack_interrupt)(struct mic_device *mdev);
};
/**
......
This diff is collapsed.
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC Host driver.
*
*/
#ifndef _MIC_INTR_H_
#define _MIC_INTR_H_
/*
* The minimum number of msix vectors required for normal operation.
* 3 for virtio network, console and block devices.
* 1 for card shutdown notifications.
*/
#define MIC_MIN_MSIX 4
#define MIC_NUM_OFFSETS 32
/**
* mic_intr_source - The type of source that will generate
* the interrupt.The number of types needs to be in sync with
* MIC_NUM_INTR_TYPES
*
* MIC_INTR_DB: The source is a doorbell
* MIC_INTR_DMA: The source is a DMA channel
* MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
* MIC_NUM_INTR_TYPES: Total number of interrupt sources.
*/
enum mic_intr_type {
MIC_INTR_DB = 0,
MIC_INTR_DMA,
MIC_INTR_ERR,
MIC_NUM_INTR_TYPES
};
/**
* struct mic_intr_info - Contains h/w specific interrupt sources
* information.
*
* @intr_start_idx: Contains the starting indexes of the
* interrupt types.
* @intr_len: Contains the length of the interrupt types.
*/
struct mic_intr_info {
u16 intr_start_idx[MIC_NUM_INTR_TYPES];
u16 intr_len[MIC_NUM_INTR_TYPES];
};
/**
* struct mic_irq_info - OS specific irq information
*
* @next_avail_src: next available doorbell that can be assigned.
* @msix_entries: msix entries allocated while setting up MSI-x
* @mic_msi_map: The MSI/MSI-x mapping information.
* @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
* @cb_ida: callback ID allocator to track the callbacks registered.
* @mic_intr_lock: spinlock to protect the interrupt callback list.
* @cb_list: Array of callback lists one for each source.
*/
struct mic_irq_info {
int next_avail_src;
struct msix_entry *msix_entries;
u32 *mic_msi_map;
u16 num_vectors;
struct ida cb_ida;
spinlock_t mic_intr_lock;
struct list_head *cb_list;
};
/**
* struct mic_intr_cb - Interrupt callback structure.
*
* @func: The callback function
* @data: Private data of the requester.
* @cb_id: The callback id. Identifies this callback.
* @list: list head pointing to the next callback structure.
*/
struct mic_intr_cb {
irqreturn_t (*func) (int irq, void *data);
void *data;
int cb_id;
struct list_head list;
};
/**
* struct mic_irq - opaque pointer used as cookie
*/
struct mic_irq;
/* Forward declaration */
struct mic_device;
/**
* struct mic_hw_intr_ops: MIC HW specific interrupt operations
* @intr_init: Initialize H/W specific interrupt information.
* @enable_interrupts: Enable interrupts from the hardware.
* @disable_interrupts: Disable interrupts from the hardware.
* @program_msi_to_src_map: Update MSI mapping registers with
* irq information.
* @read_msi_to_src_map: Read MSI mapping registers containing
* irq information.
*/
struct mic_hw_intr_ops {
void (*intr_init)(struct mic_device *mdev);
void (*enable_interrupts)(struct mic_device *mdev);
void (*disable_interrupts)(struct mic_device *mdev);
void (*program_msi_to_src_map) (struct mic_device *mdev,
int idx, int intr_src, bool set);
u32 (*read_msi_to_src_map) (struct mic_device *mdev,
int idx);
};
int mic_next_db(struct mic_device *mdev);
struct mic_irq *mic_request_irq(struct mic_device *mdev,
irqreturn_t (*func)(int irq, void *data),
const char *name, void *data, int intr_src,
enum mic_intr_type type);
void mic_free_irq(struct mic_device *mdev,
struct mic_irq *cookie, void *data);
int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
void mic_intr_restore(struct mic_device *mdev);
#endif
......@@ -23,13 +23,13 @@
* 2) Enable per vring interrupt support.
*/
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "../common/mic_device.h"
#include "mic_device.h"
#include "mic_x100.h"
#include "mic_smpt.h"
static const char mic_driver_name[] = "mic";
......@@ -75,6 +75,8 @@ static void mic_ops_init(struct mic_device *mdev)
switch (mdev->family) {
case MIC_FAMILY_X100:
mdev->ops = &mic_x100_ops;
mdev->intr_ops = &mic_x100_intr_ops;
mdev->smpt_ops = &mic_x100_smpt_ops;
break;
default:
break;
......@@ -132,6 +134,8 @@ mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
mdev->stepping = pdev->revision;
mic_ops_init(mdev);
mic_sysfs_init(mdev);
mutex_init(&mdev->mic_mutex);
mdev->irq_info.next_avail_src = 0;
}
/**
......@@ -201,6 +205,18 @@ static int mic_probe(struct pci_dev *pdev,
goto unmap_mmio;
}
mdev->intr_ops->intr_init(mdev);
rc = mic_setup_interrupts(mdev, pdev);
if (rc) {
dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
goto unmap_aper;
}
rc = mic_smpt_init(mdev);
if (rc) {
dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
goto free_interrupts;
}
pci_set_drvdata(pdev, mdev);
mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
......@@ -210,9 +226,13 @@ static int mic_probe(struct pci_dev *pdev,
rc = PTR_ERR(mdev->sdev);
dev_err(&pdev->dev,
"device_create_with_groups failed rc %d\n", rc);
goto unmap_aper;
goto smpt_uninit;
}
return 0;
smpt_uninit:
mic_smpt_uninit(mdev);
free_interrupts:
mic_free_interrupts(mdev, pdev);
unmap_aper:
iounmap(mdev->aper.va);
unmap_mmio:
......@@ -246,6 +266,8 @@ static void mic_remove(struct pci_dev *pdev)
return;
device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
mic_smpt_uninit(mdev);
mic_free_interrupts(mdev, pdev);
iounmap(mdev->mmio.va);
iounmap(mdev->aper.va);
pci_release_regions(pdev);
......
This diff is collapsed.
/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Intel MIC Host driver.
*
*/
#ifndef MIC_SMPT_H
#define MIC_SMPT_H
/**
* struct mic_smpt_ops - MIC HW specific SMPT operations.
* @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
* @set: Set the value for a particular SMPT entry.
*/
struct mic_smpt_ops {
void (*init)(struct mic_device *mdev);
void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8 index);
};
/**
* struct mic_smpt - MIC SMPT entry information.
* @dma_addr: Base DMA address for this SMPT entry.
* @ref_count: Number of active mappings for this SMPT entry in bytes.
*/
struct mic_smpt {
dma_addr_t dma_addr;
s64 ref_count;
};
/**
* struct mic_smpt_hw_info - MIC SMPT hardware specific information.
* @num_reg: Number of SMPT registers.
* @page_shift: System memory page shift.
* @page_size: System memory page size.
* @base: System address base.
*/
struct mic_smpt_hw_info {
u8 num_reg;
u8 page_shift;
u64 page_size;
u64 base;
};
/**
* struct mic_smpt_info - MIC SMPT information.
* @entry: Array of SMPT entries.
* @smpt_lock: Spin lock protecting access to SMPT data structures.
* @info: Hardware specific SMPT information.
* @ref_count: Number of active SMPT mappings (for debug).
* @map_count: Number of SMPT mappings created (for debug).
* @unmap_count: Number of SMPT mappings destroyed (for debug).
*/
struct mic_smpt_info {
struct mic_smpt *entry;
spinlock_t smpt_lock;
struct mic_smpt_hw_info info;
s64 ref_count;
s64 map_count;
s64 unmap_count;
};
dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
void mic_unmap_single(struct mic_device *mdev,
dma_addr_t mic_addr, size_t size);
dma_addr_t mic_map(struct mic_device *mdev,
dma_addr_t dma_addr, size_t size);
void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size);
/**
* mic_map_error - Check a MIC address for errors.
*
* @mdev: pointer to mic_device instance.
*
* returns Whether there was an error during mic_map..(..) APIs.
*/
static inline bool mic_map_error(dma_addr_t mic_addr)
{
return !mic_addr;
}
int mic_smpt_init(struct mic_device *mdev);
void mic_smpt_uninit(struct mic_device *mdev);
void mic_smpt_restore(struct mic_device *mdev);
#endif
......@@ -24,6 +24,7 @@
#include "../common/mic_device.h"
#include "mic_device.h"
#include "mic_x100.h"
#include "mic_smpt.h"
/**
* mic_x100_write_spad - write to the scratchpad register
......@@ -67,9 +68,255 @@ mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
return val;
}
/**
* mic_x100_enable_interrupts - Enable interrupts.
* @mdev: pointer to mic_device instance
*/
static void mic_x100_enable_interrupts(struct mic_device *mdev)
{
u32 reg;
struct mic_mw *mw = &mdev->mmio;
u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
reg = mic_mmio_read(mw, sice0);
reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
mic_mmio_write(mw, reg, sice0);
/*
* Enable auto-clear when enabling interrupts. Applicable only for
* MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
*/
if (mdev->irq_info.num_vectors > 1) {
reg = mic_mmio_read(mw, siac0);
reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
MIC_X100_SBOX_DMA_BITS(0xff);
mic_mmio_write(mw, reg, siac0);
}
}
/**
* mic_x100_disable_interrupts - Disable interrupts.
* @mdev: pointer to mic_device instance
*/
static void mic_x100_disable_interrupts(struct mic_device *mdev)
{
u32 reg;
struct mic_mw *mw = &mdev->mmio;
u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;
reg = mic_mmio_read(mw, sice0);
mic_mmio_write(mw, reg, sicc0);
if (mdev->irq_info.num_vectors > 1) {
reg = mic_mmio_read(mw, siac0);
reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
MIC_X100_SBOX_DMA_BITS(0xff));
mic_mmio_write(mw, reg, siac0);
}
}
/**
* mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
* @mdev: pointer to mic_device instance
*/
static void mic_x100_send_sbox_intr(struct mic_device *mdev,
int doorbell)
{
struct mic_mw *mw = &mdev->mmio;
u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
u32 apicicr_low = mic_mmio_read(mw,
MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
/* for MIC we need to make sure we "hit" the send_icr bit (13) */
apicicr_low = (apicicr_low | (1 << 13));
/* Ensure that the interrupt is ordered w.r.t. previous stores. */
wmb();
mic_mmio_write(mw, apicicr_low,
MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}
/**
* mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
* @mdev: pointer to mic_device instance
*/
static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
int doorbell)
{
int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
/* Ensure that the interrupt is ordered w.r.t. previous stores. */
wmb();
mic_mmio_write(&mdev->mmio, 0,
MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
}
/**
* __mic_x100_send_intr - Send interrupt to MIC.
* @mdev: pointer to mic_device instance
* @doorbell: doorbell number.
*/
static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
{
int rdmasr_db;
if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
mic_x100_send_sbox_intr(mdev, doorbell);
} else {
rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ +
MIC_X100_RDMASR_IRQ_BASE;
mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
}
}
/**
* mic_ack_interrupt - Device specific interrupt handling.
* @mdev: pointer to mic_device instance
*
* Returns: bitmask of doorbell events triggered.
*/
static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
{
u32 reg = 0;
struct mic_mw *mw = &mdev->mmio;
u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
/* Clear pending bit array. */
if (MIC_A0_STEP == mdev->stepping)
mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
MIC_X100_SBOX_MSIXPBACR);
if (mdev->irq_info.num_vectors <= 1) {
reg = mic_mmio_read(mw, sicr0);
if (unlikely(!reg))
goto done;
mic_mmio_write(mw, reg, sicr0);
}
if (mdev->stepping >= MIC_B0_STEP)
mdev->intr_ops->enable_interrupts(mdev);
done:
return reg;
}
/**
* mic_x100_hw_intr_init - Initialize h/w specific interrupt
* information.
* @mdev: pointer to mic_device instance
*/
static void mic_x100_hw_intr_init(struct mic_device *mdev)
{
mdev->intr_info = (struct mic_intr_info *) mic_x100_intr_init;
}
/**
* mic_x100_read_msi_to_src_map - read from the MSI mapping registers
* @mdev: pointer to mic_device instance
* @idx: index to the mapping register, 0 based
*
* This function allows reading of the 32bit MSI mapping register.
*
* RETURNS: The value in the register.
*/
static u32
mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
{
return mic_mmio_read(&mdev->mmio,
MIC_X100_SBOX_BASE_ADDRESS +
MIC_X100_SBOX_MXAR0 + idx * 4);
}
/**
* mic_x100_program_msi_to_src_map - program the MSI mapping registers
* @mdev: pointer to mic_device instance
* @idx: index to the mapping register, 0 based
* @offset: The bit offset in the register that needs to be updated.
* @set: boolean specifying if the bit in the specified offset needs
* to be set or cleared.
*
* RETURNS: None.
*/
static void
mic_x100_program_msi_to_src_map(struct mic_device *mdev,
int idx, int offset, bool set)
{
unsigned long reg;
struct mic_mw *mw = &mdev->mmio;
u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
MIC_X100_SBOX_MXAR0 + idx * 4;
reg = mic_mmio_read(mw, mxar);
if (set)
__set_bit(offset, &reg);
else
__clear_bit(offset, &reg);
mic_mmio_write(mw, reg, mxar);
}
/**
* mic_x100_smpt_set - Update an SMPT entry with a DMA address.
* @mdev: pointer to mic_device instance
*
* RETURNS: none.
*/
static void
mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8 index)
{
#define SNOOP_ON (0 << 0)
#define SNOOP_OFF (1 << 0)
/*
* Sbox Smpt Reg Bits:
* Bits 31:2 Host address
* Bits 1 RSVD
* Bits 0 No snoop
*/
#define BUILD_SMPT(NO_SNOOP, HOST_ADDR) \
(u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
dma_addr >> mdev->smpt->info.page_shift);
mic_mmio_write(&mdev->mmio, smpt_reg_val,
MIC_X100_SBOX_BASE_ADDRESS +
MIC_X100_SBOX_SMPT00 + (4 * index));
}
/**
* mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
* @mdev: pointer to mic_device instance
*
* RETURNS: none.
*/
static void mic_x100_smpt_hw_init(struct mic_device *mdev)
{
struct mic_smpt_hw_info *info = &mdev->smpt->info;
info->num_reg = 32;
info->page_shift = 34;
info->page_size = (1ULL << info->page_shift);
info->base = 0x8000000000ULL;
}
struct mic_smpt_ops mic_x100_smpt_ops = {
.init = mic_x100_smpt_hw_init,
.set = mic_x100_smpt_set,
};
struct mic_hw_ops mic_x100_ops = {
.aper_bar = MIC_X100_APER_BAR,
.mmio_bar = MIC_X100_MMIO_BAR,
.read_spad = mic_x100_read_spad,
.write_spad = mic_x100_write_spad,
.send_intr = mic_x100_send_intr,
.ack_interrupt = mic_x100_ack_interrupt,
};
struct mic_hw_intr_ops mic_x100_intr_ops = {
.intr_init = mic_x100_hw_intr_init,
.enable_interrupts = mic_x100_enable_interrupts,
.disable_interrupts = mic_x100_disable_interrupts,
.program_msi_to_src_map = mic_x100_program_msi_to_src_map,
.read_msi_to_src_map = mic_x100_read_msi_to_src_map,
};
......@@ -42,6 +42,45 @@
#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
#define MIC_X100_SBOX_SPAD0 0x0000AB20
#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
#define MIC_X100_SBOX_APICICR0 0x0000A9D0
#define MIC_X100_SBOX_SICR0 0x00009004
#define MIC_X100_SBOX_SICE0 0x0000900C
#define MIC_X100_SBOX_SICC0 0x00009010
#define MIC_X100_SBOX_SIAC0 0x00009014
#define MIC_X100_SBOX_MSIXPBACR 0x00009084
#define MIC_X100_SBOX_MXAR0 0x00009044
#define MIC_X100_SBOX_SMPT00 0x00003100
#define MIC_X100_SBOX_RDMASR0 0x0000B180
#define MIC_X100_DOORBELL_IDX_START 0
#define MIC_X100_NUM_DOORBELL 4
#define MIC_X100_DMA_IDX_START 8
#define MIC_X100_NUM_DMA 8
#define MIC_X100_ERR_IDX_START 30
#define MIC_X100_NUM_ERR 1
#define MIC_X100_NUM_SBOX_IRQ 8
#define MIC_X100_NUM_RDMASR_IRQ 8
#define MIC_X100_RDMASR_IRQ_BASE 17
static const u16 mic_x100_intr_init[] = {
MIC_X100_DOORBELL_IDX_START,
MIC_X100_DMA_IDX_START,
MIC_X100_ERR_IDX_START,
MIC_X100_NUM_DOORBELL,
MIC_X100_NUM_DMA,
MIC_X100_NUM_ERR,
};
extern struct mic_hw_ops mic_x100_ops;
extern struct mic_smpt_ops mic_x100_smpt_ops;
extern struct mic_hw_intr_ops mic_x100_intr_ops;
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment