From 5e2a06489e4d4d85ca4ca20af23f213e95c2fbeb Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 24 Oct 2007 08:44:21 +0200 Subject: [PATCH 01/14] SG build fix Signed-off-by: David S. Miller Signed-off-by: Jens Axboe --- arch/sparc64/kernel/iommu_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c index b70324e0d83d..efd5dff85f60 100644 --- a/arch/sparc64/kernel/iommu_common.c +++ b/arch/sparc64/kernel/iommu_common.c @@ -234,7 +234,7 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents) dma_sg->dma_length = dent_len; if (dma_sg != sg) { - dma_sg = next_sg(dma_sg); + dma_sg = sg_next(dma_sg); dma_sg->dma_length = 0; } From de58d942924d431c1c2144ece35b0b9aceadaf2c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 24 Oct 2007 08:45:35 +0200 Subject: [PATCH 02/14] sg: add missing sg_init_table calls to zfcp kernel BUG at include/linux/scatterlist.h:50! illegal operation: 0001 [#1] [...] Call Trace: ([<000000000026f184>] zfcp_ns_gid_pn_request+0x4c/0x2a0) [<0000000000276dd4>] zfcp_erp_strategy_do_action+0x1410/0x1938 [<0000000000278412>] zfcp_erp_thread+0x4fa/0x1430 [<000000000001990a>] kernel_thread_starter+0x6/0xc [<0000000000019904>] kernel_thread_starter+0x0/0xc Cc: Swen Schillig Cc: Christof Schmitt Signed-off-by: Heiko Carstens Signed-off-by: Jens Axboe --- drivers/s390/scsi/zfcp_aux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index fd5d0c1570df..d9e7be979760 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1518,6 +1518,8 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) return -ENOMEM; memset(data, 0, sizeof(*data)); + sg_init_table(&data->req , 1); + sg_init_table(&data->resp , 1); data->ct.req = &data->req; data->ct.resp = &data->resp; data->ct.req_count = data->ct.resp_count = 1; From d91c5e8839791b27672277e81451873499bc517e Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 24 Oct 2007 08:46:01 +0200 Subject: [PATCH 03/14] More SG build fixes Signed-off-by: Jens Axboe --- arch/sparc64/kernel/ldc.c | 2 +- drivers/block/sunvdc.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c index c8313cb60f0a..217478a94128 100644 --- a/arch/sparc64/kernel/ldc.c +++ b/arch/sparc64/kernel/ldc.c @@ -2121,7 +2121,7 @@ int ldc_map_sg(struct ldc_channel *lp, state.nc = 0; for (i = 0; i < num_sg; i++) - fill_cookies(&state, page_to_pfn(sg[i].page) << PAGE_SHIFT, + fill_cookies(&state, page_to_pfn(sg_page(&sg[i])) << PAGE_SHIFT, sg[i].offset, sg[i].length); return state.nc; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 7276f7d207c2..fac4c6cd04f7 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include From 5a1cb47ff4c3fbc8ebdb53c3e4f2a1dec466b339 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Oct 2007 08:55:40 +0200 Subject: [PATCH 04/14] m68k: sg fallout Signed-off-by: Geert Uytterhoeven Signed-off-by: Jens Axboe --- arch/m68k/kernel/dma.c | 2 +- drivers/scsi/atari_NCR5380.c | 5 ++--- drivers/scsi/sun3x_esp.c | 4 ++-- net/ieee80211/ieee80211_crypt_tkip.c | 2 +- net/ieee80211/ieee80211_crypt_wep.c | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c index ef490e1ce600..6f8c080dd9f9 100644 --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -9,10 +9,10 @@ #include #include #include +#include #include #include -#include void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t flag) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index d1780980fb20..a9680b5e8ac6 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -477,10 +477,9 @@ static void merge_contiguous_buffers(Scsi_Cmnd *cmd) for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; cmd->SCp.buffers_residual && - virt_to_phys(page_address(cmd->SCp.buffer[1].page) + - cmd->SCp.buffer[1].offset) == endaddr;) { + virt_to_phys(sg_virt(&cmd->SCp.buffer[1])) == endaddr;) { MER_PRINTK("VTOP(%p) == %08lx -> merging\n", - page_address(cmd->SCp.buffer[1].page), endaddr); + page_address(sg_page(&cmd->SCp.buffer[1])), endaddr); #if (NDEBUG & NDEBUG_MERGING) ++cnt; #endif diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index 80fb3f88af2e..1bc41907a038 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -332,8 +332,8 @@ static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) struct scatterlist *sg = sp->SCp.buffer; while (sz >= 0) { - sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) + - sg[sz].offset, sg[sz].length); + sg[sz].dma_address = dvma_map((unsigned long)sg_virt(&sg[sz]), + sg[sz].length); sz--; } sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 811777682e2b..74d017520a23 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include MODULE_AUTHOR("Jouni Malinen"); diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 9693429489ed..866fc04c44f9 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include MODULE_AUTHOR("Jouni Malinen"); From bd6dee6f30a0f6943df190b387b5f8fe98a848f3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Oct 2007 09:01:09 +0200 Subject: [PATCH 05/14] mmc: sg fallout Do a full scan of the directory to try and be a bit more proactive, instead of waiting for things to break. Signed-off-by: Jens Axboe --- drivers/mmc/host/au1xmmc.c | 2 +- drivers/mmc/host/mmci.c | 6 +++--- drivers/mmc/host/pxamci.c | 1 - drivers/mmc/host/sdhci.c | 2 -- drivers/mmc/host/wbsd.c | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index bcbb6d247bf7..c77fadc0dfa3 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -40,13 +40,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include "au1xmmc.h" diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index d0eb0a2abf4d..95244a7e7353 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -20,11 +20,11 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -167,7 +167,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, * partially written to a page is properly coherent. */ if (host->sg_len && data->flags & MMC_DATA_READ) - flush_dcache_page(host->sg_ptr->page); + flush_dcache_page(sg_page(host->sg_ptr)); } if (status & MCI_DATAEND) { mmci_stop_data(host); @@ -319,7 +319,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) * page, ensure that the data cache is coherent. */ if (status & MCI_RXACTIVE) - flush_dcache_page(host->sg_ptr->page); + flush_dcache_page(sg_page(host->sg_ptr)); if (!mmci_next_sg(host)) break; diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0601e01aa2c2..a25ee71998a9 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index d7c5b94d8c58..6b80bf77a4ef 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -17,8 +17,6 @@ #include -#include - #include "sdhci.h" #define DRIVER_NAME "sdhci" diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index fa4c8c53cc7a..4d5f37421874 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -33,10 +33,10 @@ #include #include #include +#include #include #include -#include #include "wbsd.h" From 18ccc4194389c6edc78ede76ada3bf753525b11c Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 24 Oct 2007 10:16:02 +0200 Subject: [PATCH 06/14] AVR32: Fix sg_page breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latest sg changes introduce the following build errors on AVR32: include/asm/dma-mapping.h: In function ‘dma_map_sg’: include/asm/dma-mapping.h:220: error: implicit declaration of function ‘sg_page’ include/asm/dma-mapping.h:220: error: invalid operands to binary - include/asm/dma-mapping.h:221: error: implicit declaration of function ‘sg_virt’ include/asm/dma-mapping.h:221: warning: assignment makes pointer from integer without a cast include/asm/dma-mapping.h: In function ‘dma_sync_sg_for_device’: include/asm/dma-mapping.h:330: warning: passing argument 2 of ‘dma_cache_sync’ makes pointer from integer without a cast Fix it by including the correct header file, i.e. linux/scatterlist.h instead of asm/scatterlist.h. Signed-off-by: Haavard Skinnemoen --- include/asm-avr32/dma-mapping.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h index a7131630c057..57dc672bab8e 100644 --- a/include/asm-avr32/dma-mapping.h +++ b/include/asm-avr32/dma-mapping.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include From 642f149031d70415d9318b919d50b71e4724adbd Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Oct 2007 11:20:47 +0200 Subject: [PATCH 07/14] SG: Change sg_set_page() to take length and offset argument Most drivers need to set length and offset as well, so may as well fold those three lines into one. Add sg_assign_page() for those two locations that only needed to set the page, where the offset/length is set outside of the function context. Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 4 +-- crypto/hmac.c | 3 +- drivers/ata/libata-core.c | 4 +-- drivers/block/cryptoloop.c | 9 ++--- drivers/block/ub.c | 9 ++--- drivers/ieee1394/dma.c | 4 +-- drivers/infiniband/core/umem.c | 4 +-- drivers/infiniband/hw/mthca/mthca_memfree.c | 9 ++--- drivers/md/dm-crypt.c | 8 ++--- drivers/media/common/saa7146_core.c | 3 +- drivers/media/video/ivtv/ivtv-udma.c | 6 ++-- drivers/media/video/videobuf-dma-sg.c | 10 ++---- drivers/net/mlx4/icm.c | 4 +-- drivers/s390/scsi/zfcp_aux.c | 10 ++---- drivers/s390/scsi/zfcp_def.h | 3 +- drivers/s390/scsi/zfcp_erp.c | 7 ++-- drivers/scsi/ipr.c | 2 +- drivers/scsi/iscsi_tcp.c | 4 +-- drivers/scsi/osst.c | 6 ++-- drivers/scsi/sg.c | 13 +++---- drivers/scsi/st.c | 14 +++----- fs/ecryptfs/crypto.c | 25 +++++-------- include/asm-frv/scatterlist.h | 3 +- include/linux/scatterlist.h | 40 +++++++++++++++------ net/core/skbuff.c | 9 ++--- net/ieee80211/ieee80211_crypt_tkip.c | 9 ++--- net/sctp/auth.c | 4 +-- net/sctp/sm_make_chunk.c | 8 ++--- net/sunrpc/auth_gss/gss_krb5_crypto.c | 14 ++++---- net/sunrpc/xdr.c | 4 +-- net/xfrm/xfrm_algo.c | 9 ++--- 31 files changed, 99 insertions(+), 162 deletions(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index de5ba479c224..b01dee3ae7f3 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1366,9 +1366,7 @@ new_segment: sg = sg_next(sg); } - sg_set_page(sg, bvec->bv_page); - sg->length = nbytes; - sg->offset = bvec->bv_offset; + sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset); nsegs++; } bvprv = bvec; diff --git a/crypto/hmac.c b/crypto/hmac.c index e4eb6ac53b5c..6691981bda11 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -160,8 +160,7 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, sg_set_buf(sg1, ipad, bs); - sg_set_page(&sg[1], (void *) sg); - sg1[1].length = 0; + sg_set_page(&sg[1], (void *) sg, 0, 0); sg_set_buf(sg2, opad, bs + ds); err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2d147b51c978..b5f7c5913062 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4689,8 +4689,8 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) * data in this function or read data in ata_sg_clean. */ offset = lsg->offset + lsg->length - qc->pad_len; - sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT)); - psg->offset = offset_in_page(offset); + sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), + qc->pad_len, offset_in_page(offset)); if (qc->tf.flags & ATA_TFLAG_WRITE) { void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 1b58b010797f..241167878edf 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -150,13 +150,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, u32 iv[4] = { 0, }; iv[0] = cpu_to_le32(IV & 0xffffffff); - sg_set_page(&sg_in, in_page); - sg_in.offset = in_offs; - sg_in.length = sz; - - sg_set_page(&sg_out, out_page); - sg_out.offset = out_offs; - sg_out.length = sz; + sg_set_page(&sg_in, in_page, sz, in_offs); + sg_set_page(&sg_out, out_page, sz, out_offs); desc.info = iv; err = encdecfunc(&desc, &sg_out, &sg_in, sz); diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 14143f2c484d..5e740e14ab35 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1428,9 +1428,8 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->state = UB_CMDST_INIT; scmd->nsg = 1; sg = &scmd->sgv[0]; - sg_set_page(sg, virt_to_page(sc->top_sense)); - sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1); - sg->length = UB_SENSE_SIZE; + sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE, + (unsigned long)sc->top_sense & (PAGE_SIZE-1)); scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; scmd->done = ub_top_sense_done; @@ -1864,9 +1863,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->state = UB_CMDST_INIT; cmd->nsg = 1; sg = &cmd->sgv[0]; - sg_set_page(sg, virt_to_page(p)); - sg->offset = (unsigned long)p & (PAGE_SIZE-1); - sg->length = 8; + sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1)); cmd->len = 8; cmd->lun = lun; cmd->done = ub_probe_done; diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index 3051e312fdc8..f5f4983dfbf3 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -111,8 +111,8 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, unsigned long va = (unsigned long)dma->kvirt + (i << PAGE_SHIFT); - sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va)); - dma->sglist[i].length = PAGE_SIZE; + sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va), + PAGE_SIZE, 0); } /* map sglist to the IOMMU */ diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 14159ff29408..4e3128ff73c1 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -171,9 +171,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, if (vma_list && !is_vm_hugetlb_page(vma_list[i + off])) umem->hugetlb = 0; - sg_set_page(&chunk->page_list[i], page_list[i + off]); - chunk->page_list[i].offset = 0; - chunk->page_list[i].length = PAGE_SIZE; + sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0); } chunk->nmap = ib_dma_map_sg(context->device, diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 007b38157fc4..1f4d27d7c16d 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -113,9 +113,7 @@ static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_m if (!page) return -ENOMEM; - sg_set_page(mem, page); - mem->length = PAGE_SIZE << order; - mem->offset = 0; + sg_set_page(mem, page, PAGE_SIZE << order, 0); return 0; } @@ -481,9 +479,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, if (ret < 0) goto out; - sg_set_page(&db_tab->page[i].mem, pages[0]); - db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE; - db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK; + sg_set_page(&db_tab->page[i].mem, pages[0], MTHCA_ICM_PAGE_SIZE, + uaddr & ~PAGE_MASK); ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); if (ret < 0) { diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ac54f697c508..1c159ac68c98 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -351,14 +351,10 @@ static int crypt_convert(struct crypt_config *cc, struct scatterlist sg_in, sg_out; sg_init_table(&sg_in, 1); - sg_set_page(&sg_in, bv_in->bv_page); - sg_in.offset = bv_in->bv_offset + ctx->offset_in; - sg_in.length = 1 << SECTOR_SHIFT; + sg_set_page(&sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); sg_init_table(&sg_out, 1); - sg_set_page(&sg_out, bv_out->bv_page); - sg_out.offset = bv_out->bv_offset + ctx->offset_out; - sg_out.length = 1 << SECTOR_SHIFT; + sg_set_page(&sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, bv_out->bv_offset + ctx->offset_out); ctx->offset_in += sg_in.length; if (ctx->offset_in >= bv_in->bv_len) { diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 2b1f8b4be00a..cb034ead95ab 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -118,8 +118,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sg_set_page(&sglist[i], pg); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index 912b424e5204..460db03b0ba0 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c @@ -49,8 +49,6 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info unsigned int len = (i == dma_page->page_count - 1) ? dma_page->tail : PAGE_SIZE - offset; - dma->SGlist[map_offset].length = len; - dma->SGlist[map_offset].offset = offset; if (PageHighMem(dma->map[map_offset])) { void *src; @@ -63,10 +61,10 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); kunmap_atomic(src, KM_BOUNCE_READ); local_irq_restore(flags); - sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset]); + sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); } else { - sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset]); + sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset); } offset = 0; map_offset++; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 9ab94a749d81..44ee408e145f 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -67,8 +67,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sg_set_page(&sglist[i], pg); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; @@ -95,16 +94,13 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; - sg_set_page(&sglist[0], pages[0]); - sglist[0].offset = offset; - sglist[0].length = PAGE_SIZE - offset; + sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset); for (i = 1; i < nr_pages; i++) { if (NULL == pages[i]) goto nopage; if (PageHighMem(pages[i])) goto highmem; - sg_set_page(&sglist[i], pages[i]); - sglist[i].length = PAGE_SIZE; + sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0); } return sglist; diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index 887633b207d9..2a5bef6388fe 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c @@ -101,9 +101,7 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_ma if (!page) return -ENOMEM; - sg_set_page(mem, page); - mem->length = PAGE_SIZE << order; - mem->offset = 0; + sg_set_page(mem, page, PAGE_SIZE << order, 0); return 0; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index d9e7be979760..00118499018b 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -562,8 +562,6 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) sg_init_table(sg_list->sg, sg_list->count); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { - sg->length = min(size, PAGE_SIZE); - sg->offset = 0; address = (void *) get_zeroed_page(GFP_KERNEL); if (address == NULL) { sg_list->count = i; @@ -571,7 +569,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) retval = -ENOMEM; goto out; } - zfcp_address_to_sg(address, sg); + zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE)); size -= sg->length; } @@ -1523,10 +1521,8 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) data->ct.req = &data->req; data->ct.resp = &data->resp; data->ct.req_count = data->ct.resp_count = 1; - zfcp_address_to_sg(&data->ct_iu_req, &data->req); - zfcp_address_to_sg(&data->ct_iu_resp, &data->resp); - data->req.length = sizeof(struct ct_iu_gid_pn_req); - data->resp.length = sizeof(struct ct_iu_gid_pn_resp); + zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req)); + zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp)); *gid_pn = data; return 0; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 326e7ee232cb..0754542978b6 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -74,8 +74,7 @@ zfcp_sg_to_address(struct scatterlist *list) static inline void zfcp_address_to_sg(void *address, struct scatterlist *list) { - sg_set_page(list, virt_to_page(address)); - list->offset = ((unsigned long) address) & (PAGE_SIZE - 1); + sg_set_buf(list, address, 0); } #define REQUEST_LIST_SIZE 128 diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 9438d0b28799..5552b755c08a 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -322,9 +322,9 @@ zfcp_erp_adisc(struct zfcp_port *port) if (address == NULL) goto nomem; - zfcp_address_to_sg(address, send_els->req); + zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc)); address += PAGE_SIZE >> 1; - zfcp_address_to_sg(address, send_els->resp); + zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc)); send_els->req_count = send_els->resp_count = 1; send_els->adapter = adapter; @@ -336,9 +336,6 @@ zfcp_erp_adisc(struct zfcp_port *port) adisc = zfcp_sg_to_address(send_els->req); send_els->ls_code = adisc->code = ZFCP_LS_ADISC; - send_els->req->length = sizeof(struct zfcp_ls_adisc); - send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc); - /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports without FC-AL-2 capability, so we don't set it */ adisc->wwpn = fc_host_port_name(adapter->scsi_host); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 439b97a6a269..0841df01bc19 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2890,7 +2890,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) return NULL; } - sg_set_page(&scatterlist[i], page); + sg_set_page(&scatterlist[i], page, 0, 0); } return sglist; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6ce4109efdf3..097a136398cb 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -79,9 +79,7 @@ static inline void iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) { sg_init_table(&ibuf->sg, 1); - sg_set_page(&ibuf->sg, sg_page(sg)); - ibuf->sg.offset = sg->offset; - ibuf->sg.length = sg->length; + sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset); /* * Fastpath: sg element fits into single page */ diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 1c5c4b68f20f..4652ad22516b 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5256,8 +5256,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) STbuffer->sg[0].offset = 0; if (page != NULL) { - sg_set_page(&STbuffer->sg[0], page); - STbuffer->sg[0].length = b_size; + sg_set_page(&STbuffer->sg[0], page, b_size, 0); STbuffer->b_data = page_address(page); break; } @@ -5285,8 +5284,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) normalize_buffer(STbuffer); return 0; } - sg_set_page(&STbuffer->sg[segs], page); - STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size; + sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0); got += STbuffer->sg[segs].length; STbuffer->buffer_size = got; STbuffer->sg_segs = ++segs; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cc1971002846..b5fa4f091387 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1717,16 +1717,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, goto out_unlock; */ } - sg_set_page(sgl, pages[0]); - sgl[0].offset = uaddr & ~PAGE_MASK; + sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK); if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; - for (i=1; i < nr_pages ; i++) { - sg_set_page(&sgl[i], pages[i]); - sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; - count -= PAGE_SIZE; - } + for (i=1; i < nr_pages ; i++) + sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0); } else { sgl[0].length = count; @@ -1854,8 +1850,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = ret_sz; } } - sg_set_page(sg, p); - sg->length = (ret_sz > num) ? num : ret_sz; + sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0); SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " "ret_sz=%d\n", k, num, ret_sz)); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index ce69b9efc102..98dfd6ea209c 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3797,13 +3797,11 @@ static void buf_to_sg(struct st_buffer *STbp, unsigned int length) sg = &(STbp->sg[0]); frp = STbp->frp; for (i=count=0; count < length; i++) { - sg_set_page(&sg[i], frp[i].page); if (length - count > frp[i].length) - sg[i].length = frp[i].length; + sg_set_page(&sg[i], frp[i].page, frp[i].length, 0); else - sg[i].length = length - count; + sg_set_page(&sg[i], frp[i].page, length - count, 0); count += sg[i].length; - sg[i].offset = 0; } STbp->sg_segs = i; STbp->frp_sg_current = length; @@ -4446,15 +4444,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa } /* Populate the scatter/gather list */ - sg_set_page(&sgl[0], pages[0]); - sgl[0].offset = uaddr & ~PAGE_MASK; + sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK); if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; for (i=1; i < nr_pages ; i++) { - sg_set_page(&sgl[i], pages[i]);; - sgl[i].offset = 0; - sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; + sg_set_page(&sgl[i], pages[i], + count < PAGE_SIZE ? count : PAGE_SIZE, 0);; count -= PAGE_SIZE; } } diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 0a9882edf562..7a472b129997 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -282,10 +282,8 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, while (size > 0 && i < sg_size) { pg = virt_to_page(addr); offset = offset_in_page(addr); - if (sg) { - sg_set_page(&sg[i], pg); - sg[i].offset = offset; - } + if (sg) + sg_set_page(&sg[i], pg, 0, offset); remainder_of_page = PAGE_CACHE_SIZE - offset; if (size >= remainder_of_page) { if (sg) @@ -716,12 +714,8 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, sg_init_table(&src_sg, 1); sg_init_table(&dst_sg, 1); - sg_set_page(&src_sg, src_page); - src_sg.offset = src_offset; - src_sg.length = size; - sg_set_page(&dst_sg, dst_page); - dst_sg.offset = dst_offset; - dst_sg.length = size; + sg_set_page(&src_sg, src_page, size, src_offset); + sg_set_page(&dst_sg, dst_page, size, dst_offset); return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); } @@ -746,14 +740,11 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist src_sg, dst_sg; sg_init_table(&src_sg, 1); - sg_init_table(&dst_sg, 1); + sg_set_page(&src_sg, src_page, size, src_offset); + + sg_init_table(&dst_sg, 1); + sg_set_page(&dst_sg, dst_page, size, dst_offset); - sg_set_page(&src_sg, src_page); - src_sg.offset = src_offset; - src_sg.length = size; - sg_set_page(&dst_sg, dst_page); - dst_sg.offset = dst_offset; - dst_sg.length = size; return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); } diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h index 99ba76edc42a..2e7143b5a7ad 100644 --- a/include/asm-frv/scatterlist.h +++ b/include/asm-frv/scatterlist.h @@ -16,8 +16,7 @@ * * can be rewritten as * - * sg_set_page(virt_to_page(some_ptr)); - * sg->offset = (unsigned long) some_ptr & ~PAGE_MASK; + * sg_set_buf(sg, some_ptr, length); * * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens */ diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index df7ddcee7c4b..809b2ac2e37e 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -26,18 +26,16 @@ #define SG_MAGIC 0x87654321 /** - * sg_set_page - Set sg entry to point at given page - * @sg: SG entry - * @page: The page + * sg_assign_page - Assign a given page to an SG entry + * @sg: SG entry + * @page: The page * * Description: - * Use this function to set an sg entry pointing at a page, never assign - * the page directly. We encode sg table information in the lower bits - * of the page pointer. See sg_page() for looking up the page belonging - * to an sg entry. + * Assign page to sg entry. Also see sg_set_page(), the most commonly used + * variant. * **/ -static inline void sg_set_page(struct scatterlist *sg, struct page *page) +static inline void sg_assign_page(struct scatterlist *sg, struct page *page) { unsigned long page_link = sg->page_link & 0x3; @@ -52,6 +50,28 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page) sg->page_link = page_link | (unsigned long) page; } +/** + * sg_set_page - Set sg entry to point at given page + * @sg: SG entry + * @page: The page + * @len: Length of data + * @offset: Offset into page + * + * Description: + * Use this function to set an sg entry pointing at a page, never assign + * the page directly. We encode sg table information in the lower bits + * of the page pointer. See sg_page() for looking up the page belonging + * to an sg entry. + * + **/ +static inline void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) +{ + sg_assign_page(sg, page); + sg->offset = offset; + sg->length = len; +} + #define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) /** @@ -64,9 +84,7 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page) static inline void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen) { - sg_set_page(sg, virt_to_page(buf)); - sg->offset = offset_in_page(buf); - sg->length = buflen; + sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); } /* diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4e2c84fcf276..7b7c6c44c2da 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2045,9 +2045,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > 0) { if (copy > len) copy = len; - sg_set_page(&sg[elt], virt_to_page(skb->data + offset)); - sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg[elt].length = copy; + sg_set_buf(sg, skb->data + offset, copy); elt++; if ((len -= copy) == 0) return elt; @@ -2065,9 +2063,8 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > len) copy = len; - sg_set_page(&sg[elt], frag->page); - sg[elt].offset = frag->page_offset+offset-start; - sg[elt].length = copy; + sg_set_page(&sg[elt], frag->page, copy, + frag->page_offset+offset-start); elt++; if (!(len -= copy)) return elt; diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 74d017520a23..4cce3534e408 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -537,13 +537,8 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, return -1; } sg_init_table(sg, 2); - sg_set_page(&sg[0], virt_to_page(hdr)); - sg[0].offset = offset_in_page(hdr); - sg[0].length = 16; - - sg_set_page(&sg[1], virt_to_page(data)); - sg[1].offset = offset_in_page(data); - sg[1].length = data_len; + sg_set_buf(&sg[0], hdr, 16); + sg_set_buf(&sg[1], data, data_len); if (crypto_hash_setkey(tfm_michael, key, 8)) return -1; diff --git a/net/sctp/auth.c b/net/sctp/auth.c index cbd64b216cce..621113a109b2 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -727,9 +727,7 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, /* set up scatter list */ end = skb_tail_pointer(skb); sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(auth)); - sg.offset = (unsigned long)(auth) % PAGE_SIZE; - sg.length = end - (unsigned char *)auth; + sg_set_buf(&sg, auth, end - (unsigned char *)auth); desc.tfm = asoc->ep->auth_hmacs[hmac_id]; desc.flags = 0; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 658476c4d587..c055212875f6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1514,9 +1514,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, /* Sign the message. */ sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(&cookie->c)); - sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; - sg.length = bodysize; + sg_set_buf(&sg, &cookie->c, bodysize); keylen = SCTP_SECRET_SIZE; key = (char *)ep->secret_key[ep->current_key]; desc.tfm = sctp_sk(ep->base.sk)->hmac; @@ -1587,9 +1585,7 @@ struct sctp_association *sctp_unpack_cookie( /* Check the signature. */ keylen = SCTP_SECRET_SIZE; sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(bear_cookie)); - sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; - sg.length = bodysize; + sg_set_buf(&sg, bear_cookie, bodysize); key = (char *)ep->secret_key[ep->current_key]; desc.tfm = sctp_sk(ep->base.sk)->hmac; desc.flags = 0; diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 32be431affcf..24711be4b2dc 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -199,7 +199,7 @@ encryptor(struct scatterlist *sg, void *data) } else { in_page = sg_page(sg); } - sg_set_page(&desc->infrags[desc->fragno], in_page); + sg_assign_page(&desc->infrags[desc->fragno], in_page); desc->fragno++; desc->fraglen += sg->length; desc->pos += sg->length; @@ -215,11 +215,10 @@ encryptor(struct scatterlist *sg, void *data) if (ret) return ret; if (fraglen) { - sg_set_page(&desc->outfrags[0], sg_page(sg)); - desc->outfrags[0].offset = sg->offset + sg->length - fraglen; - desc->outfrags[0].length = fraglen; + sg_set_page(&desc->outfrags[0], sg_page(sg), fraglen, + sg->offset + sg->length - fraglen); desc->infrags[0] = desc->outfrags[0]; - sg_set_page(&desc->infrags[0], in_page); + sg_assign_page(&desc->infrags[0], in_page); desc->fragno = 1; desc->fraglen = fraglen; } else { @@ -287,9 +286,8 @@ decryptor(struct scatterlist *sg, void *data) if (ret) return ret; if (fraglen) { - sg_set_page(&desc->frags[0], sg_page(sg)); - desc->frags[0].offset = sg->offset + sg->length - fraglen; - desc->frags[0].length = fraglen; + sg_set_page(&desc->frags[0], sg_page(sg), fraglen, + sg->offset + sg->length - fraglen); desc->fragno = 1; desc->fraglen = fraglen; } else { diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 3d1f7cdf9dd0..f38dac30481b 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1059,9 +1059,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, do { if (thislen > page_len) thislen = page_len; - sg_set_page(sg, buf->pages[i]); - sg->offset = page_offset; - sg->length = thislen; + sg_set_page(sg, buf->pages[i], thislen, page_offset); ret = actor(sg, data); if (ret) goto out; diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 313d4bed3aa9..fa45989a716a 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -553,9 +553,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg_set_page(&sg, virt_to_page(skb->data + offset)); - sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg.length = copy; + sg_set_buf(&sg, skb->data + offset, copy); err = icv_update(desc, &sg, copy); if (unlikely(err)) @@ -578,9 +576,8 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg_set_page(&sg, frag->page); - sg.offset = frag->page_offset + offset-start; - sg.length = copy; + sg_set_page(&sg, frag->page, copy, + frag->page_offset + offset-start); err = icv_update(desc, &sg, copy); if (unlikely(err)) From 23464ffa47689e46985fb10ae9e34bbc9e83f387 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Wed, 24 Oct 2007 13:07:11 +0200 Subject: [PATCH 08/14] arch/um/drivers/ubd_kern.c: fix a building error Fix this uml building error: arch/um/drivers/ubd_kern.c: In function 'do_ubd_request': arch/um/drivers/ubd_kern.c:1118: error: implicit declaration of function 'sg_page' arch/um/drivers/ubd_kern.c:1118: warning: passing argument 6 of 'prepare_request' makes pointer from integer without a cast make[1]: *** [arch/um/drivers/ubd_kern.o] Error 1 make: *** [arch/um/drivers] Error 2 Signed-off-by: WANG Cong Add sg_init_table() call as well. Signed-off-by: Jens Axboe --- arch/um/drivers/ubd_kern.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 3a8cd3dfb51c..e184b44b1011 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -35,6 +35,7 @@ #include "linux/genhd.h" #include "linux/spinlock.h" #include "linux/platform_device.h" +#include "linux/scatterlist.h" #include "asm/segment.h" #include "asm/uaccess.h" #include "asm/irq.h" @@ -704,6 +705,7 @@ static int ubd_add(int n, char **error_out) ubd_dev->size = ROUND_BLOCK(ubd_dev->size); INIT_LIST_HEAD(&ubd_dev->restart); + sg_init_table(&ubd_dev->sg, MAX_SG); err = -ENOMEM; ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); From 3d1266c7042e696704e22085a0f55c714bc06194 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Oct 2007 13:21:21 +0200 Subject: [PATCH 09/14] SG: audit of drivers that use blk_rq_map_sg() They need to properly init the sg table, or blk_rq_map_sg() will complain if CONFIG_DEBUG_SG is set. Signed-off-by: Jens Axboe --- drivers/block/virtio_blk.c | 10 ++++++---- drivers/cdrom/viocd.c | 3 ++- drivers/message/i2o/i2o_block.c | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index a901eee64ba5..3cf7129d83e6 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -4,7 +4,9 @@ #include #include #include -#include +#include + +#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) static unsigned char virtblk_index = 'a'; struct virtio_blk @@ -23,7 +25,7 @@ struct virtio_blk mempool_t *pool; /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[3+MAX_PHYS_SEGMENTS]; + struct scatterlist sg[VIRTIO_MAX_SG]; }; struct virtblk_req @@ -94,8 +96,8 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, if (blk_barrier_rq(vbr->req)) vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; - /* We have to zero this, otherwise blk_rq_map_sg gets upset. */ - memset(vblk->sg, 0, sizeof(vblk->sg)); + /* This init could be done at vblk creation time */ + sg_init_table(vblk->sg, VIRTIO_MAX_SG); sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr)); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 880b5dce3a62..d8bb44b98a6a 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -41,9 +41,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -258,6 +258,7 @@ static int send_request(struct request *req) cmd = viomajorsubtype_cdio | viocdwrite; } + sg_init_table(&sg, 1); if (blk_rq_map_sg(req->q, req, &sg) == 0) { printk(VIOCD_KERN_WARNING "error setting up scatter/gather list\n"); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index d602ba6d5417..682406168de9 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -284,6 +284,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&ireq->queue); + sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); return ireq; }; From 8c7837c4f5cf177729297ba3fef1ec62f50f499b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 24 Oct 2007 13:28:40 +0200 Subject: [PATCH 10/14] xtensa: dma-mapping.h is using linux/scatterlist.h functions, so include it It's currently using asm/scatterlist.h, but that is not enough. Signed-off-by: Jens Axboe --- include/asm-xtensa/dma-mapping.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h index 8bd9d2c02a24..3c7d537dd15d 100644 --- a/include/asm-xtensa/dma-mapping.h +++ b/include/asm-xtensa/dma-mapping.h @@ -11,10 +11,10 @@ #ifndef _XTENSA_DMA_MAPPING_H #define _XTENSA_DMA_MAPPING_H -#include #include #include #include +#include /* * DMA-consistent mapping functions. From 82861924a5f26208c8421a799a4e8724d48eb560 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Oct 2007 14:09:25 +0200 Subject: [PATCH 11/14] blackfin: fix sg fallout Signed-off-by: Adrian Bunk Signed-off-by: Jens Axboe --- arch/blackfin/kernel/dma-mapping.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c index a16cb03c5291..d6b61d56b656 100644 --- a/arch/blackfin/kernel/dma-mapping.c +++ b/arch/blackfin/kernel/dma-mapping.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include From e88a39dee10d3a506ed8c4ba78cde0dd76a6fc83 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 25 Oct 2007 09:13:32 +0200 Subject: [PATCH 12/14] x86: pci-gart fix map_sg could copy the last sg element to another position (if merging some elements). It breaks sg chaining. This copies only dma_address/length instead of the whole sg element. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- arch/x86/kernel/pci-gart_64.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index c56e9ee64964..ae7e0161ce46 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -338,7 +338,6 @@ static int __dma_map_cont(struct scatterlist *start, int nelems, BUG_ON(s != start && s->offset); if (s == start) { - *sout = *s; sout->dma_address = iommu_bus_base; sout->dma_address += iommu_page*PAGE_SIZE + s->offset; sout->dma_length = s->length; @@ -365,7 +364,7 @@ static inline int dma_map_cont(struct scatterlist *start, int nelems, { if (!need) { BUG_ON(nelems != 1); - *sout = *start; + sout->dma_address = start->dma_address; sout->dma_length = start->length; return 0; } From 4f33a9d9a416313f0ecf6e6953d205385a431cd5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 25 Oct 2007 09:17:03 +0200 Subject: [PATCH 13/14] ub: add sg_init_table for sense and read capacity commands Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/block/ub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 5e740e14ab35..08e909dc7944 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1428,6 +1428,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->state = UB_CMDST_INIT; scmd->nsg = 1; sg = &scmd->sgv[0]; + sg_init_table(sg, UB_MAX_REQ_SG); sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE, (unsigned long)sc->top_sense & (PAGE_SIZE-1)); scmd->len = UB_SENSE_SIZE; @@ -1863,6 +1864,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->state = UB_CMDST_INIT; cmd->nsg = 1; sg = &cmd->sgv[0]; + sg_init_table(sg, UB_MAX_REQ_SG); sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1)); cmd->len = 8; cmd->lun = lun; From 85cdffcde0b6b831a06422413300d0f5c0e608c3 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 25 Oct 2007 09:55:05 +0200 Subject: [PATCH 14/14] fix sg_phys to use dma_addr_t x86_32 CONFIG_HIGHMEM64G with 5GB RAM hung when booting, after issuing some "request_module: runaway loop modprobe binfmt-0000" messages in trying to exec /sbin/init. The binprm buf doesn't see the right ".ELF" header because sg_phys() is providing the wrong physical addresses for high pages: a 32-bit unsigned long is too small in this case, we need to use dma_addr_t. Signed-off-by: Hugh Dickins Signed-off-by: Jens Axboe --- include/linux/scatterlist.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 809b2ac2e37e..457123171389 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -1,6 +1,7 @@ #ifndef _LINUX_SCATTERLIST_H #define _LINUX_SCATTERLIST_H +#include #include #include #include @@ -255,7 +256,7 @@ static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) * on the sg page. * **/ -static inline unsigned long sg_phys(struct scatterlist *sg) +static inline dma_addr_t sg_phys(struct scatterlist *sg) { return page_to_phys(sg_page(sg)) + sg->offset; }