All of lore.kernel.org
 help / color / mirror / Atom feed
* pci_set_dma_mask()/pci_dma_supported() & broken PCI bridge issue
@ 2004-03-09  4:41 Deepak Saxena
  2004-03-09  4:55 ` Deepak Saxena
  0 siblings, 1 reply; 2+ messages in thread
From: Deepak Saxena @ 2004-03-09  4:41 UTC (permalink / raw)
  To: linux-kernel


I am a bit confused about the proper way that dma_set_mask() should
behave. My situation is that I have an ARM core that has broken
PCI window, allowing DMA only to/from the lower 64MB of RAM. My
current approach to get around this is custom dma-API functions
that trap based on (dev->bus == &pci_bus_type && *dev->dma_mask !=
0xfffffff). If dma_mask is 0xfffffff, I use the generic ARM dma API
implementation, otherwise I call my platform-specific functions
that bounce buffers that are > 64MB.  I set the dma_mask to (64MB - 1) 
by hooking in a platform_notify() function and calling dma_set_mask()
if the device is a PCI device.

Everything was working fine with PCI IDE, EEPro100, and USB, but 
when I tried switching to Intel's e100 driver, the self test failed.  
Looking at the code, the cuplrit is the following line:

	if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {
		DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
		goto err_out_free_res;
	}

pci_set_dma_mask does:

int
pci_set_dma_mask(struct pci_dev *dev, u64 mask)
{
	if (!pci_dma_supported(dev, mask))
		return -EIO; 

	dev->dma_mask = mask;

	return 0;
}

Currently pci_dma_supported() on ARM returns 1 on 0xffffffff, so
the device's dma_mask gets updated and my code is no longer 
trapping the calls to the DMA API, so the self-test buffer
is getting allocated outside of the DMA-safe window and it
never gets updated by the device's write (A PCI analyzer confirms
this is the case). I can fix pci_dma_supported() to return 0 
on my platform if (dma_mask > 64MB), but this still leaves me
with an unusable driver b/c it will just bail out. 

My comment from this experience is that it seems that there needs to 
be a way for the platform code to tell the PCI layer "this dma mask you 
gave me is not supported, but here is what I can support" and the driver 
can decide if this is appropriate. The other option is to have the driver 
keep on trying smaller and smaller masks as Documentation/dma-mapping.txt 
describes. 

Perhaps a pci_get_dma_mask() so that drivers can see what
the current mask is set to? In that case, drivers could do:

	unsigned long long my_mask = 0x00ffffffULL;

	if(pci_get_dma_mask(pdev) > my_mask) {
		if(!pci_set_dma_mask(my_mask)) {
			bail_out;
		}
		... 	
	} else {
		/* We're OK on this platform */
		...
	}

Comments?

~Deepak

-- 
Deepak Saxena - dsaxena at plexity dot net - http://www.plexity.net/

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: pci_set_dma_mask()/pci_dma_supported() & broken PCI bridge issue
  2004-03-09  4:41 pci_set_dma_mask()/pci_dma_supported() & broken PCI bridge issue Deepak Saxena
@ 2004-03-09  4:55 ` Deepak Saxena
  0 siblings, 0 replies; 2+ messages in thread
From: Deepak Saxena @ 2004-03-09  4:55 UTC (permalink / raw)
  To: linux-kernel

On Mar 08 2004, at 21:41, Deepak Saxena was caught saying:
> 
> I am a bit confused about the proper way that dma_set_mask() should
> behave. My situation is that I have an ARM core that has broken
> PCI window, allowing DMA only to/from the lower 64MB of RAM. My
> current approach to get around this is custom dma-API functions
> that trap based on (dev->bus == &pci_bus_type && *dev->dma_mask !=
> 0xfffffff). If dma_mask is 0xfffffff, I use the generic ARM dma API

I meant 0xffffffff

-- 
Deepak Saxena - dsaxena at plexity dot net - http://www.plexity.net/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-03-09  4:55 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-09  4:41 pci_set_dma_mask()/pci_dma_supported() & broken PCI bridge issue Deepak Saxena
2004-03-09  4:55 ` Deepak Saxena

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.