ia64/xen-unstable

changeset 1895:8cae910510d1

bitkeeper revision 1.1108.2.24 (410133delTf8MZfF-gDO2KEJpDxCOg)

Ensure that merged scatter-gather lists are valid in the face
of moulinexed machine address space.
author kaf24@scramble.cl.cam.ac.uk
date Fri Jul 23 15:50:54 2004 +0000 (2004-07-23)
parents 51f8d2380c82
children 90591e5e7c45
files linux-2.4.26-xen-sparse/include/asm-xen/pci.h
line diff
     1.1 --- a/linux-2.4.26-xen-sparse/include/asm-xen/pci.h	Fri Jul 23 05:14:44 2004 +0000
     1.2 +++ b/linux-2.4.26-xen-sparse/include/asm-xen/pci.h	Fri Jul 23 15:50:54 2004 +0000
     1.3 @@ -145,7 +145,8 @@ static inline void pci_unmap_page(struct
     1.4  static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
     1.5  			     int nents, int direction)
     1.6  {
     1.7 -	int i;
     1.8 +	int i, j, nr_pfns;
     1.9 +	unsigned long first_pfn;
    1.10  
    1.11  	if (direction == PCI_DMA_NONE)
    1.12  		out_of_line_bug();
    1.13 @@ -159,10 +160,28 @@ static inline int pci_map_sg(struct pci_
    1.14   		else if (!sg[i].address && !sg[i].page)
    1.15   			out_of_line_bug();
    1.16   
    1.17 - 		if (sg[i].address)
    1.18 + 		if (sg[i].address) {
    1.19   			sg[i].dma_address = virt_to_bus(sg[i].address);
    1.20 - 		else
    1.21 + 			first_pfn = virt_to_phys(sg[i].address) >> PAGE_SHIFT;
    1.22 + 			nr_pfns = (((unsigned long)sg[i].address & 
    1.23 + 			    (PAGE_SIZE-1)) + sg[i].length + PAGE_SIZE - 1) >>
    1.24 + 			    PAGE_SHIFT;
    1.25 + 		} else {
    1.26   			sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
    1.27 + 			first_pfn = page_to_phys(sg[i].page) >> PAGE_SHIFT;
    1.28 + 			nr_pfns = (sg[i].offset + sg[i].length + PAGE_SIZE - 
    1.29 + 			    1) >> PAGE_SHIFT;
    1.30 + 		}
    1.31 +
    1.32 +                /*
    1.33 +                 * Check that we merged physical buffers are also contiguous
    1.34 +                 * in machine-address space. We try to fail by returning 0.
    1.35 +                 */
    1.36 +                for (j = 1; j < nr_pfns; j++) {
    1.37 +                    if ( unlikely(pfn_to_mfn(first_pfn+j) != 
    1.38 +                                  (pfn_to_mfn(first_pfn)+j)) )
    1.39 +                        return 0;
    1.40 +                }
    1.41   	}
    1.42   
    1.43  	flush_write_buffers();