Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: - three fixes for 3.15 that didn't make it in time - limited Octeon 3 support. - paravirtualization support - improvment to platform support for Netlogix SOCs. - add support for powering down the Malta eval board in software - add many instructions to the in-kernel microassembler. - add support for the BPF JIT. - minor cleanups of the BCM47xx code. - large cleanup of math emu code resulting in significant code size reduction, better readability of the code and more accurate emulation. - improvments to the MIPS CPS code. - support C3 power status for the R4k count/compare clock device. - improvments to the GIO support for older SGI workstations. - increase number of supported CPUs to 256; this can be reached on certain embedded multithreaded ccNUMA configurations. - various small cleanups, updates and fixes * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (173 commits) MIPS: IP22/IP28: Improve GIO support MIPS: Octeon: Add twsi interrupt initialization for OCTEON 3XXX, 5XXX, 63XX DEC: Document the R4k MB ASIC mini interrupt controller DEC: Add self as the maintainer MIPS: Add microMIPS MSA support. MIPS: Replace calls to obsolete strict_strto call with kstrto* equivalents. MIPS: Replace obsolete strict_strto call with kstrto MIPS: BFP: Simplify code slightly. MIPS: Call find_vma with the mmap_sem held MIPS: Fix 'write_msa_##' inline macro. MIPS: Fix MSA toolchain support detection. mips: Update the email address of Geert Uytterhoeven MIPS: Add minimal defconfig for mips_paravirt MIPS: Enable build for new system 'paravirt' MIPS: paravirt: Add pci controller for virtio MIPS: Add code for new system 'paravirt' MIPS: Add functions for hypervisor call MIPS: OCTEON: Add OCTEON3 to __get_cpu_type MIPS: Add function get_ebase_cpunum MIPS: Add minimal support for OCTEON3 to c-r4k.c ...
这个提交包含在:
@@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
|
||||
obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
|
||||
obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
|
||||
obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
|
||||
|
||||
obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
|
||||
#
|
||||
# These are still pretty much in the old state, watch, go blind.
|
||||
#
|
||||
|
@@ -68,6 +68,7 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned char reg_val;
|
||||
u32 reg_val32;
|
||||
u16 reg_val16;
|
||||
/* PIIX PIRQC[A:D] irq mappings */
|
||||
static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = {
|
||||
0, 0, 0, 3,
|
||||
@@ -107,6 +108,11 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
|
||||
pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_val);
|
||||
reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT;
|
||||
pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val);
|
||||
|
||||
/* Enable response to special cycles */
|
||||
pci_read_config_word(pdev, PCI_COMMAND, ®_val16);
|
||||
pci_write_config_word(pdev, PCI_COMMAND,
|
||||
reg_val16 | PCI_COMMAND_SPECIAL);
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include <asm/octeon/cvmx-npi-defs.h>
|
||||
#include <asm/octeon/cvmx-pci-defs.h>
|
||||
#include <asm/octeon/cvmx-npei-defs.h>
|
||||
#include <asm/octeon/cvmx-sli-defs.h>
|
||||
#include <asm/octeon/cvmx-pexp-defs.h>
|
||||
#include <asm/octeon/pci-octeon.h>
|
||||
|
||||
@@ -162,6 +163,11 @@ msi_irq_allocated:
|
||||
msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
|
||||
msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
|
||||
break;
|
||||
case OCTEON_DMA_BAR_TYPE_PCIE2:
|
||||
/* When using PCIe2, Bar 0 is based at 0 */
|
||||
msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff;
|
||||
msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32;
|
||||
break;
|
||||
default:
|
||||
panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type");
|
||||
}
|
||||
|
@@ -56,8 +56,8 @@
|
||||
#include <asm/netlogic/xlp-hal/bridge.h>
|
||||
|
||||
#define XLP_MSIVEC_PER_LINK 32
|
||||
#define XLP_MSIXVEC_TOTAL 32
|
||||
#define XLP_MSIXVEC_PER_LINK 8
|
||||
#define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32)
|
||||
#define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8)
|
||||
|
||||
/* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
|
||||
static inline int nlm_link_msiirq(int link, int msivec)
|
||||
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec)
|
||||
return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
|
||||
}
|
||||
|
||||
/* get the link MSI vector from irq number */
|
||||
static inline int nlm_irq_msivec(int irq)
|
||||
{
|
||||
return irq % XLP_MSIVEC_PER_LINK;
|
||||
return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
|
||||
}
|
||||
|
||||
/* get the link from the irq number */
|
||||
static inline int nlm_irq_msilink(int irq)
|
||||
{
|
||||
return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) /
|
||||
XLP_MSIVEC_PER_LINK;
|
||||
int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
|
||||
|
||||
return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
|
||||
XLP_MSIVEC_PER_LINK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only 32 MSI-X vectors are possible because there are only 32 PIC
|
||||
* interrupts for MSI. We split them statically and use 8 MSI-X vectors
|
||||
* per link - this keeps the allocation and lookup simple.
|
||||
* For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
|
||||
* there are only 32 PIC interrupts for MSI. We split them statically
|
||||
* and use 8 MSI-X vectors per link - this keeps the allocation and
|
||||
* lookup simple.
|
||||
* On XLP 9xx, there are 32 vectors per link, and the interrupts are
|
||||
* not routed thru PIC, so we can use all 128 MSI-X vectors.
|
||||
*/
|
||||
static inline int nlm_link_msixirq(int link, int bit)
|
||||
{
|
||||
return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
|
||||
}
|
||||
|
||||
/* get the link MSI vector from irq number */
|
||||
static inline int nlm_irq_msixvec(int irq)
|
||||
{
|
||||
return irq % XLP_MSIXVEC_TOTAL; /* works when given xirq */
|
||||
return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
|
||||
}
|
||||
|
||||
static inline int nlm_irq_msixlink(int irq)
|
||||
/* get the link from MSIX vec */
|
||||
static inline int nlm_irq_msixlink(int msixvec)
|
||||
{
|
||||
return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK;
|
||||
return msixvec / XLP_MSIXVEC_PER_LINK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d)
|
||||
vec = nlm_irq_msivec(d->irq);
|
||||
spin_lock_irqsave(&md->msi_lock, flags);
|
||||
md->msi_enabled_mask |= 1u << vec;
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
|
||||
if (cpu_is_xlp9xx())
|
||||
nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
|
||||
md->msi_enabled_mask);
|
||||
else
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
|
||||
spin_unlock_irqrestore(&md->msi_lock, flags);
|
||||
}
|
||||
|
||||
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d)
|
||||
vec = nlm_irq_msivec(d->irq);
|
||||
spin_lock_irqsave(&md->msi_lock, flags);
|
||||
md->msi_enabled_mask &= ~(1u << vec);
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
|
||||
if (cpu_is_xlp9xx())
|
||||
nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
|
||||
md->msi_enabled_mask);
|
||||
else
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
|
||||
spin_unlock_irqrestore(&md->msi_lock, flags);
|
||||
}
|
||||
|
||||
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d)
|
||||
xlp_msi_disable(d);
|
||||
|
||||
/* Ack MSI on bridge */
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
|
||||
if (cpu_is_xlp9xx())
|
||||
nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
|
||||
else
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
|
||||
|
||||
/* Ack at eirr and PIC */
|
||||
ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
|
||||
nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
|
||||
if (cpu_is_xlp9xx())
|
||||
nlm_pic_ack(md->node->picbase,
|
||||
PIC_9XX_IRT_PCIE_LINK_INDEX(link));
|
||||
else
|
||||
nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
|
||||
}
|
||||
|
||||
static struct irq_chip xlp_msi_chip = {
|
||||
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = {
|
||||
};
|
||||
|
||||
/*
|
||||
* The MSI-X interrupt handling is different from MSI, there are 32
|
||||
* MSI-X interrupts generated by the PIC and each of these correspond
|
||||
* to a MSI-X vector (0-31) that can be assigned.
|
||||
* XLP8XX/4XX/3XX/2XX:
|
||||
* The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
|
||||
* interrupts generated by the PIC and each of these correspond to a MSI-X
|
||||
* vector (0-31) that can be assigned.
|
||||
*
|
||||
* We divide the MSI-X vectors to 8 per link and do a per-link
|
||||
* allocation
|
||||
* We divide the MSI-X vectors to 8 per link and do a per-link allocation
|
||||
*
|
||||
* XLP9XX:
|
||||
* 32 MSI-X vectors are available per link, and the interrupts are not routed
|
||||
* thru the PIC. PIC ack not needed.
|
||||
*
|
||||
* Enable and disable done using standard MSI functions.
|
||||
*/
|
||||
static void xlp_msix_mask_ack(struct irq_data *d)
|
||||
{
|
||||
struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
|
||||
struct xlp_msi_data *md;
|
||||
int link, msixvec;
|
||||
uint32_t status_reg, bit;
|
||||
|
||||
msixvec = nlm_irq_msixvec(d->irq);
|
||||
link = nlm_irq_msixlink(d->irq);
|
||||
link = nlm_irq_msixlink(msixvec);
|
||||
mask_msi_irq(d);
|
||||
md = irq_data_get_irq_handler_data(d);
|
||||
|
||||
/* Ack MSI on bridge */
|
||||
nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec);
|
||||
if (cpu_is_xlp9xx()) {
|
||||
status_reg = PCIE_9XX_MSIX_STATUSX(link);
|
||||
bit = msixvec % XLP_MSIXVEC_PER_LINK;
|
||||
} else {
|
||||
status_reg = PCIE_MSIX_STATUS;
|
||||
bit = msixvec;
|
||||
}
|
||||
nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
|
||||
|
||||
/* Ack at eirr and PIC */
|
||||
ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
|
||||
nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec));
|
||||
if (!cpu_is_xlp9xx())
|
||||
nlm_pic_ack(md->node->picbase,
|
||||
PIC_IRT_PCIE_MSIX_INDEX(msixvec));
|
||||
}
|
||||
|
||||
static struct irq_chip xlp_msix_chip = {
|
||||
@@ -219,10 +258,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200; /* MSI Interrupt enable */
|
||||
nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
|
||||
if (cpu_is_xlp9xx()) {
|
||||
val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200; /* MSI Interrupt enable */
|
||||
nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
|
||||
}
|
||||
} else {
|
||||
val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200;
|
||||
nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
|
||||
}
|
||||
}
|
||||
|
||||
val = nlm_read_reg(lnkbase, 0x1); /* CMD */
|
||||
@@ -269,9 +316,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
|
||||
|
||||
spin_lock_irqsave(&md->msi_lock, flags);
|
||||
if (md->msi_alloc_mask == 0) {
|
||||
/* switch the link IRQ to MSI range */
|
||||
xlp_config_link_msi(lnkbase, lirq, msiaddr);
|
||||
irt = PIC_IRT_PCIE_LINK_INDEX(link);
|
||||
/* switch the link IRQ to MSI range */
|
||||
if (cpu_is_xlp9xx())
|
||||
irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
|
||||
else
|
||||
irt = PIC_IRT_PCIE_LINK_INDEX(link);
|
||||
nlm_setup_pic_irq(node, lirq, lirq, irt);
|
||||
nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
|
||||
node * nlm_threads_per_node(), 1 /*en */);
|
||||
@@ -311,10 +361,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
|
||||
val |= 0x80000000U;
|
||||
nlm_write_reg(lnkbase, 0x2C, val);
|
||||
}
|
||||
val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200; /* MSI Interrupt enable */
|
||||
nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
|
||||
|
||||
if (cpu_is_xlp9xx()) {
|
||||
val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200; /* MSI Interrupt enable */
|
||||
nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
|
||||
}
|
||||
} else {
|
||||
val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
|
||||
if ((val & 0x200) == 0) {
|
||||
val |= 0x200; /* MSI Interrupt enable */
|
||||
nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
|
||||
}
|
||||
}
|
||||
|
||||
val = nlm_read_reg(lnkbase, 0x1); /* CMD */
|
||||
@@ -329,10 +388,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
|
||||
val |= (1 << 8) | lirq;
|
||||
nlm_write_pci_reg(lnkbase, 0xf, val);
|
||||
|
||||
/* MSI-X addresses */
|
||||
nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8);
|
||||
nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
|
||||
(msixaddr + MSI_ADDR_SZ) >> 8);
|
||||
if (cpu_is_xlp9xx()) {
|
||||
/* MSI-X addresses */
|
||||
nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
|
||||
msixaddr >> 8);
|
||||
nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
|
||||
(msixaddr + MSI_ADDR_SZ) >> 8);
|
||||
} else {
|
||||
/* MSI-X addresses */
|
||||
nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
|
||||
msixaddr >> 8);
|
||||
nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
|
||||
(msixaddr + MSI_ADDR_SZ) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -369,6 +437,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
|
||||
|
||||
xirq += t;
|
||||
msixvec = nlm_irq_msixvec(xirq);
|
||||
|
||||
msg.address_hi = msixaddr >> 32;
|
||||
msg.address_lo = msixaddr & 0xffffffff;
|
||||
msg.data = 0xc00 | msixvec;
|
||||
@@ -409,7 +478,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
|
||||
{
|
||||
struct nlm_soc_info *nodep;
|
||||
struct xlp_msi_data *md;
|
||||
int irq, i, irt, msixvec;
|
||||
int irq, i, irt, msixvec, val;
|
||||
|
||||
pr_info("[%d %d] Init node PCI IRT\n", node, link);
|
||||
nodep = nlm_get_node(node);
|
||||
@@ -430,19 +499,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
|
||||
irq_set_handler_data(i, md);
|
||||
}
|
||||
|
||||
for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) {
|
||||
/* Initialize MSI-X irts to generate one interrupt per link */
|
||||
msixvec = link * XLP_MSIXVEC_PER_LINK + i;
|
||||
irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
|
||||
nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link),
|
||||
node * nlm_threads_per_node(), 1 /* enable */);
|
||||
for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
|
||||
if (cpu_is_xlp9xx()) {
|
||||
val = ((node * nlm_threads_per_node()) << 7 |
|
||||
PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
|
||||
nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
|
||||
(link * XLP_MSIXVEC_PER_LINK)), val);
|
||||
} else {
|
||||
/* Initialize MSI-X irts to generate one interrupt
|
||||
* per link
|
||||
*/
|
||||
msixvec = link * XLP_MSIXVEC_PER_LINK + i;
|
||||
irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
|
||||
nlm_pic_init_irt(nodep->picbase, irt,
|
||||
PIC_PCIE_MSIX_IRQ(link),
|
||||
node * nlm_threads_per_node(), 1);
|
||||
}
|
||||
|
||||
/* Initialize MSI-X extended irq space for the link */
|
||||
irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
|
||||
irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
|
||||
irq_set_handler_data(irq, md);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nlm_dispatch_msi(int node, int lirq)
|
||||
@@ -454,7 +532,11 @@ void nlm_dispatch_msi(int node, int lirq)
|
||||
link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
|
||||
irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
|
||||
md = irq_get_handler_data(irqbase);
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
|
||||
if (cpu_is_xlp9xx())
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
|
||||
md->msi_enabled_mask;
|
||||
else
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
|
||||
md->msi_enabled_mask;
|
||||
while (status) {
|
||||
i = __ffs(status);
|
||||
@@ -472,10 +554,14 @@ void nlm_dispatch_msix(int node, int lirq)
|
||||
link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
|
||||
irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
|
||||
md = irq_get_handler_data(irqbase);
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
|
||||
if (cpu_is_xlp9xx())
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
|
||||
else
|
||||
status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
|
||||
|
||||
/* narrow it down to the MSI-x vectors for our link */
|
||||
status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
|
||||
if (!cpu_is_xlp9xx())
|
||||
status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
|
||||
((1 << XLP_MSIXVEC_PER_LINK) - 1);
|
||||
|
||||
while (status) {
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
|
||||
*
|
||||
* Much of the code is derived from the original DDB5074 port by
|
||||
* Geert Uytterhoeven <geert@sonycom.com>
|
||||
* Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@@ -11,7 +11,7 @@
|
||||
* Define the pci_ops for TX3927.
|
||||
*
|
||||
* Much of the code is derived from the original DDB5074 port by
|
||||
* Geert Uytterhoeven <geert@sonycom.com>
|
||||
* Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@@ -202,17 +202,20 @@ char *tx4927_pcibios_setup(char *str)
|
||||
unsigned long val;
|
||||
|
||||
if (!strncmp(str, "trdyto=", 7)) {
|
||||
if (strict_strtoul(str + 7, 0, &val) == 0)
|
||||
u8 val = 0;
|
||||
if (kstrtou8(str + 7, 0, &val) == 0)
|
||||
tx4927_pci_opts.trdyto = val;
|
||||
return NULL;
|
||||
}
|
||||
if (!strncmp(str, "retryto=", 8)) {
|
||||
if (strict_strtoul(str + 8, 0, &val) == 0)
|
||||
u8 val = 0;
|
||||
if (kstrtou8(str + 8, 0, &val) == 0)
|
||||
tx4927_pci_opts.retryto = val;
|
||||
return NULL;
|
||||
}
|
||||
if (!strncmp(str, "gbwc=", 5)) {
|
||||
if (strict_strtoul(str + 5, 0, &val) == 0)
|
||||
u16 val;
|
||||
if (kstrtou16(str + 5, 0, &val) == 0)
|
||||
tx4927_pci_opts.gbwc = val;
|
||||
return NULL;
|
||||
}
|
||||
|
131
arch/mips/pci/pci-virtio-guest.c
普通文件
131
arch/mips/pci/pci-virtio-guest.c
普通文件
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2013 Cavium, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <uapi/asm/bitfield.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define PCI_CONFIG_ADDRESS 0xcf8
|
||||
#define PCI_CONFIG_DATA 0xcfc
|
||||
|
||||
union pci_config_address {
|
||||
struct {
|
||||
__BITFIELD_FIELD(unsigned enable_bit : 1, /* 31 */
|
||||
__BITFIELD_FIELD(unsigned reserved : 7, /* 30 .. 24 */
|
||||
__BITFIELD_FIELD(unsigned bus_number : 8, /* 23 .. 16 */
|
||||
__BITFIELD_FIELD(unsigned devfn_number : 8, /* 15 .. 8 */
|
||||
__BITFIELD_FIELD(unsigned register_number : 8, /* 7 .. 0 */
|
||||
)))));
|
||||
};
|
||||
u32 w;
|
||||
};
|
||||
|
||||
int pcibios_plat_dev_init(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
return ((pin + slot) % 4)+ MIPS_IRQ_PCIA;
|
||||
}
|
||||
|
||||
static void pci_virtio_guest_write_config_addr(struct pci_bus *bus,
|
||||
unsigned int devfn, int reg)
|
||||
{
|
||||
union pci_config_address pca = { .w = 0 };
|
||||
|
||||
pca.register_number = reg;
|
||||
pca.devfn_number = devfn;
|
||||
pca.bus_number = bus->number;
|
||||
pca.enable_bit = 1;
|
||||
|
||||
outl(pca.w, PCI_CONFIG_ADDRESS);
|
||||
}
|
||||
|
||||
static int pci_virtio_guest_write_config(struct pci_bus *bus,
|
||||
unsigned int devfn, int reg, int size, u32 val)
|
||||
{
|
||||
pci_virtio_guest_write_config_addr(bus, devfn, reg);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
outb(val, PCI_CONFIG_DATA + (reg & 3));
|
||||
break;
|
||||
case 2:
|
||||
outw(val, PCI_CONFIG_DATA + (reg & 2));
|
||||
break;
|
||||
case 4:
|
||||
outl(val, PCI_CONFIG_DATA);
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int reg, int size, u32 *val)
|
||||
{
|
||||
pci_virtio_guest_write_config_addr(bus, devfn, reg);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
*val = inb(PCI_CONFIG_DATA + (reg & 3));
|
||||
break;
|
||||
case 2:
|
||||
*val = inw(PCI_CONFIG_DATA + (reg & 2));
|
||||
break;
|
||||
case 4:
|
||||
*val = inl(PCI_CONFIG_DATA);
|
||||
break;
|
||||
}
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops pci_virtio_guest_ops = {
|
||||
.read = pci_virtio_guest_read_config,
|
||||
.write = pci_virtio_guest_write_config,
|
||||
};
|
||||
|
||||
static struct resource pci_virtio_guest_mem_resource = {
|
||||
.name = "Virtio MEM",
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = 0x10000000,
|
||||
.end = 0x1dffffff
|
||||
};
|
||||
|
||||
static struct resource pci_virtio_guest_io_resource = {
|
||||
.name = "Virtio IO",
|
||||
.flags = IORESOURCE_IO,
|
||||
.start = 0,
|
||||
.end = 0xffff
|
||||
};
|
||||
|
||||
static struct pci_controller pci_virtio_guest_controller = {
|
||||
.pci_ops = &pci_virtio_guest_ops,
|
||||
.mem_resource = &pci_virtio_guest_mem_resource,
|
||||
.io_resource = &pci_virtio_guest_io_resource,
|
||||
};
|
||||
|
||||
static int __init pci_virtio_guest_setup(void)
|
||||
{
|
||||
pr_err("pci_virtio_guest_setup\n");
|
||||
|
||||
/* Virtio comes pre-assigned */
|
||||
pci_set_flags(PCI_PROBE_ONLY);
|
||||
|
||||
pci_virtio_guest_controller.io_map_base = mips_io_port_base;
|
||||
register_pci_controller(&pci_virtio_guest_controller);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(pci_virtio_guest_setup);
|
在新工单中引用
屏蔽一个用户