Merge branch 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block: [SCSI] Remove full sg table memset() [SCSI] ide-scsi: remove usage of sg_last() Fix loop terminating conditions in fill_sg(). [BLOCK] Clear sg entry before filling in blk_rq_map_sg() IA64: iommu uses sg_next with an invalid sg element cciss: disable DMA refetch on Smart Array P600 swiotlb: fix map_sg failure handling SPARC64: fix iommu sg chaining [SCSI] ide-scsi: use scsi_sg_count() instead of ->use_sg
This commit is contained in:
		
						commit
						b6257a9036
					
				| @ -1179,7 +1179,6 @@ sba_fill_pdir( | ||||
| 	u64 *pdirp = NULL; | ||||
| 	unsigned long dma_offset = 0; | ||||
| 
 | ||||
| 	dma_sg--; | ||||
| 	while (nents-- > 0) { | ||||
| 		int     cnt = startsg->dma_length; | ||||
| 		startsg->dma_length = 0; | ||||
| @ -1201,7 +1200,8 @@ sba_fill_pdir( | ||||
| 			u32 pide = startsg->dma_address & ~PIDE_FLAG; | ||||
| 			dma_offset = (unsigned long) pide & ~iovp_mask; | ||||
| 			startsg->dma_address = 0; | ||||
| 			dma_sg = sg_next(dma_sg); | ||||
| 			if (n_mappings) | ||||
| 				dma_sg = sg_next(dma_sg); | ||||
| 			dma_sg->dma_address = pide | ioc->ibase; | ||||
| 			pdirp = &(ioc->pdir_base[pide >> iovp_shift]); | ||||
| 			n_mappings++; | ||||
|  | ||||
| @ -10,7 +10,6 @@ | ||||
| #include <linux/device.h> | ||||
| #include <linux/dma-mapping.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/scatterlist.h> | ||||
| 
 | ||||
| #ifdef CONFIG_PCI | ||||
| #include <linux/pci.h> | ||||
| @ -476,12 +475,11 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr, | ||||
| #define SG_ENT_PHYS_ADDRESS(SG)	\ | ||||
| 	(__pa(page_address((SG)->page)) + (SG)->offset) | ||||
| 
 | ||||
| static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | ||||
| 			   int nused, int nelems, | ||||
| 			   unsigned long iopte_protection) | ||||
| static void fill_sg(iopte_t *iopte, struct scatterlist *sg, | ||||
| 		    int nused, int nelems, | ||||
| 		    unsigned long iopte_protection) | ||||
| { | ||||
| 	struct scatterlist *dma_sg = sg; | ||||
| 	struct scatterlist *sg_end = sg_last(sg, nelems); | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < nused; i++) { | ||||
| @ -517,6 +515,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | ||||
| 					break; | ||||
| 				} | ||||
| 				sg = sg_next(sg); | ||||
| 				nelems--; | ||||
| 			} | ||||
| 
 | ||||
| 			pteval = iopte_protection | (pteval & IOPTE_PAGE); | ||||
| @ -530,18 +529,20 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | ||||
| 
 | ||||
| 			pteval = (pteval & IOPTE_PAGE) + len; | ||||
| 			sg = sg_next(sg); | ||||
| 			nelems--; | ||||
| 
 | ||||
| 			/* Skip over any tail mappings we've fully mapped,
 | ||||
| 			 * adjusting pteval along the way.  Stop when we | ||||
| 			 * detect a page crossing event. | ||||
| 			 */ | ||||
| 			while (sg != sg_end && | ||||
| 			while (nelems && | ||||
| 			       (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | ||||
| 			       (pteval == SG_ENT_PHYS_ADDRESS(sg)) && | ||||
| 			       ((pteval ^ | ||||
| 				 (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { | ||||
| 				pteval += sg->length; | ||||
| 				sg = sg_next(sg); | ||||
| 				nelems--; | ||||
| 			} | ||||
| 			if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) | ||||
| 				pteval = ~0UL; | ||||
|  | ||||
| @ -12,18 +12,22 @@ | ||||
|  */ | ||||
| 
 | ||||
| #ifdef VERIFY_SG | ||||
| static int verify_lengths(struct scatterlist *sg, int nents, int npages) | ||||
| static int verify_lengths(struct scatterlist *sglist, int nents, int npages) | ||||
| { | ||||
| 	int sg_len, dma_len; | ||||
| 	int i, pgcount; | ||||
| 	struct scatterlist *sg; | ||||
| 
 | ||||
| 	sg_len = 0; | ||||
| 	for (i = 0; i < nents; i++) | ||||
| 		sg_len += sg[i].length; | ||||
| 	for_each_sg(sglist, sg, nents, i) | ||||
| 		sg_len += sg->length; | ||||
| 
 | ||||
| 	dma_len = 0; | ||||
| 	for (i = 0; i < nents && sg[i].dma_length; i++) | ||||
| 		dma_len += sg[i].dma_length; | ||||
| 	for_each_sg(sglist, sg, nents, i) { | ||||
| 		if (!sg->dma_length) | ||||
| 			break; | ||||
| 		dma_len += sg->dma_length; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sg_len != dma_len) { | ||||
| 		printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", | ||||
| @ -32,13 +36,16 @@ static int verify_lengths(struct scatterlist *sg, int nents, int npages) | ||||
| 	} | ||||
| 
 | ||||
| 	pgcount = 0; | ||||
| 	for (i = 0; i < nents && sg[i].dma_length; i++) { | ||||
| 	for_each_sg(sglist, sg, nents, i) { | ||||
| 		unsigned long start, end; | ||||
| 
 | ||||
| 		start = sg[i].dma_address; | ||||
| 		if (!sg->dma_length) | ||||
| 			break; | ||||
| 
 | ||||
| 		start = sg->dma_address; | ||||
| 		start = start & IO_PAGE_MASK; | ||||
| 
 | ||||
| 		end = sg[i].dma_address + sg[i].dma_length; | ||||
| 		end = sg->dma_address + sg->dma_length; | ||||
| 		end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; | ||||
| 
 | ||||
| 		pgcount += ((end - start) >> IO_PAGE_SHIFT); | ||||
| @ -113,7 +120,7 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, | ||||
| 		if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) | ||||
| 			iopte++; | ||||
| 
 | ||||
| 		sg++; | ||||
| 		sg = sg_next(sg); | ||||
| 		if (--nents <= 0) | ||||
| 			break; | ||||
| 		sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); | ||||
| @ -147,7 +154,7 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) | ||||
| 		nents = verify_one_map(dma_sg, &sg, nents, &iopte); | ||||
| 		if (nents <= 0) | ||||
| 			break; | ||||
| 		dma_sg++; | ||||
| 		dma_sg = sg_next(dma_sg); | ||||
| 		if (dma_sg->dma_length == 0) | ||||
| 			break; | ||||
| 	} | ||||
| @ -169,22 +176,24 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages) | ||||
| void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages) | ||||
| { | ||||
| 	if (verify_lengths(sg, nents, npages) < 0 || | ||||
| 	    verify_maps(sg, nents, iopte) < 0) { | ||||
| 	struct scatterlist *sg; | ||||
| 
 | ||||
| 	if (verify_lengths(sglist, nents, npages) < 0 || | ||||
| 	    verify_maps(sglist, nents, iopte) < 0) { | ||||
| 		int i; | ||||
| 
 | ||||
| 		printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); | ||||
| 		printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK); | ||||
| 		printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK); | ||||
| 
 | ||||
| 		for (i = 0; i < nents; i++) { | ||||
| 		for_each_sg(sglist, sg, nents, i) { | ||||
| 			printk("sg(%d): page_addr(%p) off(%x) length(%x) " | ||||
| 			       "dma_address[%016lx] dma_length[%016lx]\n", | ||||
| 			       "dma_address[%016x] dma_length[%016x]\n", | ||||
| 			       i, | ||||
| 			       page_address(sg[i].page), sg[i].offset, | ||||
| 			       sg[i].length, | ||||
| 			       sg[i].dma_address, sg[i].dma_length); | ||||
| 			       page_address(sg->page), sg->offset, | ||||
| 			       sg->length, | ||||
| 			       sg->dma_address, sg->dma_length); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -205,12 +214,12 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents) | ||||
| 	while (--nents) { | ||||
| 		unsigned long addr; | ||||
| 
 | ||||
| 		sg++; | ||||
| 		sg = sg_next(sg); | ||||
| 		addr = (unsigned long) (page_address(sg->page) + sg->offset); | ||||
| 		if (! VCONTIG(prev, addr)) { | ||||
| 			dma_sg->dma_address = dent_addr; | ||||
| 			dma_sg->dma_length = dent_len; | ||||
| 			dma_sg++; | ||||
| 			dma_sg = sg_next(dma_sg); | ||||
| 
 | ||||
| 			dent_addr = ((dent_addr + | ||||
| 				      dent_len + | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| #include <linux/types.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/scatterlist.h> | ||||
| 
 | ||||
| #include <asm/iommu.h> | ||||
| #include <asm/scatterlist.h> | ||||
|  | ||||
| @ -13,7 +13,6 @@ | ||||
| #include <linux/irq.h> | ||||
| #include <linux/msi.h> | ||||
| #include <linux/log2.h> | ||||
| #include <linux/scatterlist.h> | ||||
| 
 | ||||
| #include <asm/iommu.h> | ||||
| #include <asm/irq.h> | ||||
| @ -369,12 +368,11 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr, | ||||
| #define SG_ENT_PHYS_ADDRESS(SG)	\ | ||||
| 	(__pa(page_address((SG)->page)) + (SG)->offset) | ||||
| 
 | ||||
| static inline long fill_sg(long entry, struct device *dev, | ||||
| 			   struct scatterlist *sg, | ||||
| 			   int nused, int nelems, unsigned long prot) | ||||
| static long fill_sg(long entry, struct device *dev, | ||||
| 		    struct scatterlist *sg, | ||||
| 		    int nused, int nelems, unsigned long prot) | ||||
| { | ||||
| 	struct scatterlist *dma_sg = sg; | ||||
| 	struct scatterlist *sg_end = sg_last(sg, nelems); | ||||
| 	unsigned long flags; | ||||
| 	int i; | ||||
| 
 | ||||
| @ -415,6 +413,7 @@ static inline long fill_sg(long entry, struct device *dev, | ||||
| 					break; | ||||
| 				} | ||||
| 				sg = sg_next(sg); | ||||
| 				nelems--; | ||||
| 			} | ||||
| 
 | ||||
| 			pteval = (pteval & IOPTE_PAGE); | ||||
| @ -433,19 +432,20 @@ static inline long fill_sg(long entry, struct device *dev, | ||||
| 
 | ||||
| 			pteval = (pteval & IOPTE_PAGE) + len; | ||||
| 			sg = sg_next(sg); | ||||
| 			nelems--; | ||||
| 
 | ||||
| 			/* Skip over any tail mappings we've fully mapped,
 | ||||
| 			 * adjusting pteval along the way.  Stop when we | ||||
| 			 * detect a page crossing event. | ||||
| 			 */ | ||||
| 			while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | ||||
| 			while (nelems && | ||||
| 			       (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | ||||
| 			       (pteval == SG_ENT_PHYS_ADDRESS(sg)) && | ||||
| 			       ((pteval ^ | ||||
| 				 (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { | ||||
| 				pteval += sg->length; | ||||
| 				if (sg == sg_end) | ||||
| 					break; | ||||
| 				sg = sg_next(sg); | ||||
| 				nelems--; | ||||
| 			} | ||||
| 			if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) | ||||
| 				pteval = ~0UL; | ||||
|  | ||||
| @ -1352,6 +1352,7 @@ new_segment: | ||||
| 			sg = next_sg; | ||||
| 			next_sg = sg_next(sg); | ||||
| 
 | ||||
| 			memset(sg, 0, sizeof(*sg)); | ||||
| 			sg->page = bvec->bv_page; | ||||
| 			sg->length = nbytes; | ||||
| 			sg->offset = bvec->bv_offset; | ||||
|  | ||||
| @ -3076,15 +3076,20 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	/* Disabling DMA prefetch for the P600
 | ||||
| 	 * An ASIC bug may result in a prefetch beyond | ||||
| 	 * physical memory. | ||||
| 	/* Disabling DMA prefetch and refetch for the P600.
 | ||||
| 	 * An ASIC bug may result in accesses to invalid memory addresses. | ||||
| 	 * We've disabled prefetch for some time now. Testing with XEN | ||||
| 	 * kernels revealed a bug in the refetch if dom0 resides on a P600. | ||||
| 	 */ | ||||
| 	if(board_id == 0x3225103C) { | ||||
| 		__u32 dma_prefetch; | ||||
| 		__u32 dma_refetch; | ||||
| 		dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG); | ||||
| 		dma_prefetch |= 0x8000; | ||||
| 		writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG); | ||||
| 		pci_read_config_dword(pdev, PCI_COMMAND_PARITY, &dma_refetch); | ||||
| 		dma_refetch |= 0x1; | ||||
| 		pci_write_config_dword(pdev, PCI_COMMAND_PARITY, dma_refetch); | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CCISS_DEBUG | ||||
|  | ||||
| @ -70,7 +70,7 @@ typedef struct idescsi_pc_s { | ||||
| 	u8 *buffer;				/* Data buffer */ | ||||
| 	u8 *current_position;			/* Pointer into the above buffer */ | ||||
| 	struct scatterlist *sg;			/* Scatter gather table */ | ||||
| 	struct scatterlist *last_sg;		/* Last sg element */ | ||||
| 	unsigned int sg_cnt;			/* Number of entries in sg */ | ||||
| 	int b_count;				/* Bytes transferred from current entry */ | ||||
| 	struct scsi_cmnd *scsi_cmd;		/* SCSI command */ | ||||
| 	void (*done)(struct scsi_cmnd *);	/* Scsi completion routine */ | ||||
| @ -192,7 +192,7 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne | ||||
| 		} | ||||
| 		bcount -= count; pc->b_count += count; | ||||
| 		if (pc->b_count == pc->sg->length) { | ||||
| 			if (pc->sg == pc->last_sg) | ||||
| 			if (!--pc->sg_cnt) | ||||
| 				break; | ||||
| 			pc->sg = sg_next(pc->sg); | ||||
| 			pc->b_count = 0; | ||||
| @ -229,7 +229,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | ||||
| 		} | ||||
| 		bcount -= count; pc->b_count += count; | ||||
| 		if (pc->b_count == pc->sg->length) { | ||||
| 			if (pc->sg == pc->last_sg) | ||||
| 			if (!--pc->sg_cnt) | ||||
| 				break; | ||||
| 			pc->sg = sg_next(pc->sg); | ||||
| 			pc->b_count = 0; | ||||
| @ -807,7 +807,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, | ||||
| 	memcpy (pc->c, cmd->cmnd, cmd->cmd_len); | ||||
| 	pc->buffer = NULL; | ||||
| 	pc->sg = scsi_sglist(cmd); | ||||
| 	pc->last_sg = sg_last(pc->sg, cmd->use_sg); | ||||
| 	pc->sg_cnt = scsi_sg_count(cmd); | ||||
| 	pc->b_count = 0; | ||||
| 	pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); | ||||
| 	pc->scsi_cmd = cmd; | ||||
|  | ||||
| @ -764,8 +764,6 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) | ||||
| 		if (unlikely(!sgl)) | ||||
| 			goto enomem; | ||||
| 
 | ||||
| 		memset(sgl, 0, sizeof(*sgl) * sgp->size); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * first loop through, set initial index and return value | ||||
| 		 */ | ||||
|  | ||||
| @ -696,7 +696,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||||
| 				/* Don't panic here, we expect map_sg users
 | ||||
| 				   to do proper error handling. */ | ||||
| 				swiotlb_full(hwdev, sg->length, dir, 0); | ||||
| 				swiotlb_unmap_sg(hwdev, sg - i, i, dir); | ||||
| 				swiotlb_unmap_sg(hwdev, sgl, i, dir); | ||||
| 				sgl[0].dma_length = 0; | ||||
| 				return 0; | ||||
| 			} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user