Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad7ad57c authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: Fix conflicts in SBUS/PCI/EBUS/ISA DMA handling.



Fully unify all of the DMA ops so that subordinate bus types to
the DMA operation providers (such as ebus, isa, of_device) can
work transparently.

Basically, we just make sure that for every system device we
create, the dev->archdata 'iommu' and 'stc' fields are filled
in.

Then we have two platform variants of the DMA ops, one for SUN4U which
actually programs the real hardware, and one for SUN4V which makes
hypervisor calls.

This also fixes the crashes in parport_pc on sparc64, reported by
Meelis Roos.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c7f439b9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -8,14 +8,14 @@ EXTRA_CFLAGS := -Werror
extra-y		:= head.o init_task.o vmlinux.lds

obj-y		:= process.o setup.o cpu.o idprom.o \
		   traps.o auxio.o una_asm.o sysfs.o \
		   traps.o auxio.o una_asm.o sysfs.o iommu.o \
		   irq.o ptrace.o time.o sys_sparc.o signal.o \
		   unaligned.o central.o pci.o starfire.o semaphore.o \
		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
		   visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o

obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o \
			    pci_psycho.o pci_sabre.o pci_schizo.o \
			    pci_sun4v.o pci_sun4v_asm.o pci_fire.o
obj-$(CONFIG_SMP)	 += smp.o trampoline.o hvtramp.o
+2 −0
Original line number Diff line number Diff line
@@ -391,6 +391,8 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
	sd = &dev->ofdev.dev.archdata;
	sd->prom_node = dp;
	sd->op = &dev->ofdev;
	sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
	sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;

	dev->ofdev.node = dp;
	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+145 −159

File changed and moved.

Preview size limit exceeded, changes collapsed.

+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
		sd = &isa_dev->ofdev.dev.archdata;
		sd->prom_node = dp;
		sd->op = &isa_dev->ofdev;
		sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
		sd->stc = isa_br->ofdev.dev.parent->archdata.stc;

		isa_dev->ofdev.node = dp;
		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+51 −11
Original line number Diff line number Diff line
@@ -283,12 +283,6 @@ int __init pcic_present(void)
	return pci_controller_scan(pci_is_controller);
}

const struct pci_iommu_ops *pci_iommu_ops;
EXPORT_SYMBOL(pci_iommu_ops);

extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
	pci_sun4v_iommu_ops;

/* Find each controller in the system, attach and initialize
 * software state structure for each and link into the
 * pci_pbm_root.  Setup the controller enough such
@@ -296,11 +290,6 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
 */
static void __init pci_controller_probe(void)
{
	if (tlb_type == hypervisor)
		pci_iommu_ops = &pci_sun4v_iommu_ops;
	else
		pci_iommu_ops = &pci_sun4u_iommu_ops;

	printk("PCI: Probing for controllers.\n");

	pci_controller_scan(pci_controller_init);
@@ -406,6 +395,10 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
	sd->op = of_find_device_by_node(node);
	sd->msi_num = 0xffffffff;

	sd = &sd->op->dev.archdata;
	sd->iommu = pbm->iommu;
	sd->stc = &pbm->stc;

	type = of_get_property(node, "device_type", NULL);
	if (type == NULL)
		type = "";
@@ -1226,4 +1219,51 @@ struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
}
EXPORT_SYMBOL(pci_device_to_OF_node);

static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
{
	struct pci_dev *ali_isa_bridge;
	u8 val;

	/* ALI sound chips generate 31-bits of DMA, a special register
	 * determines what bit 31 is emitted as.
	 */
	ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL,
					 PCI_DEVICE_ID_AL_M1533,
					 NULL);

	pci_read_config_byte(ali_isa_bridge, 0x7e, &val);
	if (set_bit)
		val |= 0x01;
	else
		val &= ~0x01;
	pci_write_config_byte(ali_isa_bridge, 0x7e, val);
	pci_dev_put(ali_isa_bridge);
}

int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
{
	u64 dma_addr_mask;

	if (pdev == NULL) {
		dma_addr_mask = 0xffffffff;
	} else {
		struct iommu *iommu = pdev->dev.archdata.iommu;

		dma_addr_mask = iommu->dma_addr_mask;

		if (pdev->vendor == PCI_VENDOR_ID_AL &&
		    pdev->device == PCI_DEVICE_ID_AL_M5451 &&
		    device_mask == 0x7fffffff) {
			ali_sound_dma_hack(pdev,
					   (dma_addr_mask & 0x80000000) != 0);
			return 1;
		}
	}

	if (device_mask >= (1UL << 32UL))
		return 0;

	return (device_mask & dma_addr_mask) == dma_addr_mask;
}

#endif /* !(CONFIG_PCI) */
Loading