|
From: Paul M. <le...@li...> - 2003-06-27 16:09:55
|
On Fri, Jun 27, 2003 at 04:26:05PM +0100, Richard Curnow wrote:
> I've now got stuck because I got lost trying to follow the call chain
> back far enough to locate where the scatter-gather buffers are getting
> allocated and hence why the addresses in the table passed to pci_map_sg
> are all zero. I suspect there's something in asm-sh64 or arch/sh64
> that's missing a real implementation, but I've no idea what.
>=20
> Is anybody au fait with this area of the code and able to give me any
> pointers where to look next?
>=20
There's absolutely nothing wrong with getting a NULL address in this case,
the existing code just doesn't deal with it properly.
Drivers have two options for dealing with this, they can either set
->address or they can set ->page and ->offset, the latter of which is the
preferred method, and is the only thing that works for highmem systems.
Try out this patch (I haven't tried compiling it yet, but its a proof of
concept .. you may also have to adjust some of the flushing), and see if
it works for you..
--- shmedia-2.4/include/asm-sh64/scatterlist.h Tue May 13 15:08:57 2003
+++ shmedia-2.4.test/include/asm-sh64/scatterlist.h Fri Jun 27 11:58:22 2003
@@ -23,12 +23,13 @@
#define _ASM_SH64_SCATTERLIST_H
=20
struct scatterlist {
- char *address; /* Location data is to be transferred to */
- char *alt_address; /* Location of actual if address is a */
- /* dma indirect buffer. NULL otherwise */
- struct page *page; /* Location for highmem page, if any */
- unsigned int offset; /* for highmem, page offset */
- unsigned int length;
+ char *address; /* Location data is to be transferred to, NULL
+ for highmem page */
+ struct page *page; /* Location for highmem page, if any */
+ unsigned int offset; /* for highmem, page offset */
+
+ dma_addr_t dma_address;
+ unsigned int length;
};
=20
#define ISA_DMA_THRESHOLD (0xffffffff)
--- shmedia-2.4/include/asm-sh64/pci.h Fri Jun 20 18:44:48 2003
+++ shmedia-2.4.test/include/asm-sh64/pci.h Fri Jun 27 12:05:26 2003
@@ -141,8 +141,18 @@
int nents,int direction)
{
int i;
- for (i=3D0; i<nents; i++)
- dma_cache_wback_inv((unsigned long)sg[i].address, sg[i].length);=20
+
+ for (i =3D 0; i < nents; i++) {
+ if (sg[i].address) {
+ dma_cache_wback_inv((unsigned long)sg[i].address,
+ sg[i].length);
+ sg[i].dma_address =3D virt_to_bus(sg[i].address);
+ } else {
+ sg[i].dma_address =3D page_to_bus(sg[i].page) +
+ sg[i].offset;
+ }
+ }
+
return nents;
}
=20
@@ -155,7 +165,17 @@
static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist =
*sg,
int nents,int direction)
{
- /* Nothing to do */
+ int i;
+
+ if (direction =3D=3D PCI_DMA_TODEVICE)
+ return;
+=09
+ for (i =3D 0; i < nents; i++) {
+ if (!sg[i].address)
+ continue;
+
+ dma_cache_wback_inv((unsigned long)sg[i].address, sg[i].length);
+ }
}
=20
=20
@@ -188,7 +208,10 @@
struct scatterlist *sg,
int nelems,int direction)
{
- /* Nothing to do */
+ int i;
+
+ for (i =3D 0; i < nelems; i++)
+ dma_cache_wback_inv((unsigned long)sg[i].address, sg[i].length);
}
=20
=20
@@ -219,7 +242,7 @@
** returns, or alternatively stop on the first sg_dma_len(sg) which
** is 0.
*/
-#define sg_dma_address(sg) (virt_to_bus((sg)->address))
+#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
=20
#define PCI_DMA_BUS_IS_PHYS (1)
|