Skip to content

Commit

Permalink
Merge branch 'for-4.3/sg' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
Pull SG updates from Jens Axboe:
 "This contains a set of scatter-gather related changes/fixes for 4.3:

   - Add support for limited chaining of sg tables even for
     architectures that do not set ARCH_HAS_SG_CHAIN.  From Christoph.

   - Add sg chain support to target_rd.  From Christoph.

   - Fixup open coded sg->page_link in crypto/omap-sham.  From
     Christoph.

   - Fixup open coded crypto ->page_link manipulation.  From Dan.

   - Also from Dan, automated fixup of manual sg_unmark_end()
     manipulations.

   - Also from Dan, automated fixup of open coded sg_phys()
     implementations.

   - From Robert Jarzmik, addition of an sg table splitting helper that
     drivers can use"

* 'for-4.3/sg' of git://git.kernel.dk/linux-block:
  lib: scatterlist: add sg splitting function
  scatterlist: use sg_phys()
  crypto/omap-sham: remove an open coded access to ->page_link
  scatterlist: remove open coded sg_unmark_end instances
  crypto: replace scatterwalk_sg_chain with sg_chain
  target/rd: always chain S/G list
  scatterlist: allow limited chaining without ARCH_HAS_SG_CHAIN
  • Loading branch information
torvalds committed Sep 2, 2015
2 parents 52b084d + f8bcbe6 commit d975f30
Show file tree
Hide file tree
Showing 21 changed files with 234 additions and 81 deletions.
2 changes: 1 addition & 1 deletion arch/arm/mm/dma-mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
return -ENOMEM;

for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
phys_addr_t phys = page_to_phys(sg_page(s));
phys_addr_t phys = sg_phys(s) & PAGE_MASK;
unsigned int len = PAGE_ALIGN(s->offset + s->length);

if (!is_coherent &&
Expand Down
3 changes: 1 addition & 2 deletions arch/microblaze/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
/* FIXME this part of code is untested */
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg);
__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
sg->length, direction);
__dma_sync(sg_phys(sg), sg->length, direction);
}

return nents;
Expand Down
2 changes: 1 addition & 1 deletion block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
if (rq->cmd_flags & REQ_WRITE)
memset(q->dma_drain_buffer, 0, q->dma_drain_size);

sg->page_link &= ~0x02;
sg_unmark_end(sg);
sg = sg_next(sg);
sg_set_page(sg, virt_to_page(q->dma_drain_buffer),
q->dma_drain_size,
Expand Down
2 changes: 1 addition & 1 deletion crypto/algif_skcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static int skcipher_alloc_sgl(struct sock *sk)
sgl->cur = 0;

if (sg)
scatterwalk_sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);

list_add_tail(&sgl->list, &ctx->tsgl);
}
Expand Down
4 changes: 2 additions & 2 deletions crypto/gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,14 @@ static void crypto_gcm_init_common(struct aead_request *req)
sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
if (sg != pctx->src + 1)
scatterwalk_sg_chain(pctx->src, 2, sg);
sg_chain(pctx->src, 2, sg);

if (req->src != req->dst) {
sg_init_table(pctx->dst, 3);
sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
if (sg != pctx->dst + 1)
scatterwalk_sg_chain(pctx->dst, 2, sg);
sg_chain(pctx->dst, 2, sg);
}
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/crypto/bfin_crc.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,7 @@ static int bfin_crypto_crc_handle_queue(struct bfin_crypto_crc *crc,
sg_init_table(ctx->bufsl, nsg);
sg_set_buf(ctx->bufsl, ctx->buflast, ctx->buflast_len);
if (nsg > 1)
scatterwalk_sg_chain(ctx->bufsl, nsg,
req->src);
sg_chain(ctx->bufsl, nsg, req->src);
ctx->sg = ctx->bufsl;
} else
ctx->sg = req->src;
Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/omap-sham.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
* the dmaengine may try to DMA the incorrect amount of data.
*/
sg_init_table(&ctx->sgl, 1);
ctx->sgl.page_link = ctx->sg->page_link;
sg_assign_page(&ctx->sgl, sg_page(ctx->sg));
ctx->sgl.offset = ctx->sg->offset;
sg_dma_len(&ctx->sgl) = len32;
sg_dma_address(&ctx->sgl) = sg_dma_address(ctx->sg);
Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/qce/sha.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ static int qce_ahash_update(struct ahash_request *req)
if (rctx->buflen) {
sg_init_table(rctx->sg, 2);
sg_set_buf(rctx->sg, rctx->tmpbuf, rctx->buflen);
scatterwalk_sg_chain(rctx->sg, 2, req->src);
sg_chain(rctx->sg, 2, req->src);
req->src = rctx->sg;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/sahara.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ static int sahara_sha_prepare_request(struct ahash_request *req)
sg_init_table(rctx->in_sg_chain, 2);
sg_set_buf(rctx->in_sg_chain, rctx->rembuf, rctx->buf_cnt);

scatterwalk_sg_chain(rctx->in_sg_chain, 2, req->src);
sg_chain(rctx->in_sg_chain, 2, req->src);

rctx->total = req->nbytes + rctx->buf_cnt;
rctx->in_sg = rctx->in_sg_chain;
Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/talitos.c
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
sg_init_table(req_ctx->bufsl, nsg);
sg_set_buf(req_ctx->bufsl, req_ctx->buf, req_ctx->nbuf);
if (nsg > 1)
scatterwalk_sg_chain(req_ctx->bufsl, 2, areq->src);
sg_chain(req_ctx->bufsl, 2, areq->src);
req_ctx->psrc = req_ctx->bufsl;
} else
req_ctx->psrc = areq->src;
Expand Down
4 changes: 2 additions & 2 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2103,7 +2103,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
sg_res = aligned_nrpages(sg->offset, sg->length);
sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
sg->dma_length = sg->length;
pteval = page_to_phys(sg_page(sg)) | prot;
pteval = (sg_phys(sg) & PAGE_MASK) | prot;
phys_pfn = pteval >> VTD_PAGE_SHIFT;
}

Expand Down Expand Up @@ -3631,7 +3631,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,

for_each_sg(sglist, sg, nelems, i) {
BUG_ON(!sg_page(sg));
sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
sg->dma_address = sg_phys(sg);
sg->dma_length = sg->length;
}
return nelems;
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,7 @@ size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);

for_each_sg(sg, s, nents, i) {
phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset;
phys_addr_t phys = sg_phys(s);

/*
* We are mapping on IOMMU page boundaries, so offset within
Expand Down
4 changes: 2 additions & 2 deletions drivers/mmc/card/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,15 +467,15 @@ static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq,
sg_set_buf(__sg, buf + offset, len);
offset += len;
remain -= len;
(__sg++)->page_link &= ~0x02;
sg_unmark_end(__sg++);
sg_len++;
} while (remain);
}

list_for_each_entry(req, &packed->list, queuelist) {
sg_len += blk_rq_map_sg(mq->queue, req, __sg);
__sg = sg + (sg_len - 1);
(__sg++)->page_link &= ~0x02;
sg_unmark_end(__sg++);
}
sg_mark_end(sg + (sg_len - 1));
return sg_len;
Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/android/ion/ion_chunk_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap,
err:
sg = table->sgl;
for (i -= 1; i >= 0; i--) {
gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
sg->length);
sg = sg_next(sg);
}
Expand Down Expand Up @@ -109,7 +109,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
DMA_BIDIRECTIONAL);

for_each_sg(table->sgl, sg, table->nents, i) {
gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
sg->length);
}
chunk_heap->allocated -= allocated_size;
Expand Down
44 changes: 0 additions & 44 deletions drivers/target/target_core_rd.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,12 @@ static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *
sg_per_table = (total_sg_needed > max_sg_per_table) ?
max_sg_per_table : total_sg_needed;

#ifdef CONFIG_ARCH_HAS_SG_CHAIN

/*
* Reserve extra element for chain entry
*/
if (sg_per_table < total_sg_needed)
chain_entry = 1;

#endif /* CONFIG_ARCH_HAS_SG_CHAIN */

sg = kcalloc(sg_per_table + chain_entry, sizeof(*sg),
GFP_KERNEL);
if (!sg) {
Expand All @@ -158,15 +154,11 @@ static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *

sg_init_table(sg, sg_per_table + chain_entry);

#ifdef CONFIG_ARCH_HAS_SG_CHAIN

if (i > 0) {
sg_chain(sg_table[i - 1].sg_table,
max_sg_per_table + 1, sg);
}

#endif /* CONFIG_ARCH_HAS_SG_CHAIN */

sg_table[i].sg_table = sg;
sg_table[i].rd_sg_count = sg_per_table;
sg_table[i].page_start_offset = page_offset;
Expand Down Expand Up @@ -430,42 +422,6 @@ static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, bool is_read)
prot_sg = &prot_table->sg_table[prot_page -
prot_table->page_start_offset];

#ifndef CONFIG_ARCH_HAS_SG_CHAIN

prot_npages = DIV_ROUND_UP(prot_offset + sectors * se_dev->prot_length,
PAGE_SIZE);

/*
* Allocate temporaly contiguous scatterlist entries if prot pages
* straddles multiple scatterlist tables.
*/
if (prot_table->page_end_offset < prot_page + prot_npages - 1) {
int i;

prot_sg = kcalloc(prot_npages, sizeof(*prot_sg), GFP_KERNEL);
if (!prot_sg)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;

need_to_release = true;
sg_init_table(prot_sg, prot_npages);

for (i = 0; i < prot_npages; i++) {
if (prot_page + i > prot_table->page_end_offset) {
prot_table = rd_get_prot_table(dev,
prot_page + i);
if (!prot_table) {
kfree(prot_sg);
return rc;
}
sg_unmark_end(&prot_sg[i - 1]);
}
prot_sg[i] = prot_table->sg_table[prot_page + i -
prot_table->page_start_offset];
}
}

#endif /* !CONFIG_ARCH_HAS_SG_CHAIN */

if (is_read)
rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
prot_sg, prot_offset);
Expand Down
10 changes: 1 addition & 9 deletions include/crypto/scatterwalk.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@
#include <linux/scatterlist.h>
#include <linux/sched.h>

static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num,
struct scatterlist *sg2)
{
sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
sg1[num - 1].page_link &= ~0x02;
sg1[num - 1].page_link |= 0x01;
}

static inline void scatterwalk_crypto_chain(struct scatterlist *head,
struct scatterlist *sg,
int chain, int num)
Expand All @@ -43,7 +35,7 @@ static inline void scatterwalk_crypto_chain(struct scatterlist *head,
}

if (sg)
scatterwalk_sg_chain(head, num, sg);
sg_chain(head, num, sg);
else
sg_mark_end(head);
}
Expand Down
9 changes: 5 additions & 4 deletions include/linux/scatterlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,6 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
struct scatterlist *sgl)
{
#ifndef CONFIG_ARCH_HAS_SG_CHAIN
BUG();
#endif

/*
* offset and length are unused for chain entry. Clear them.
*/
Expand Down Expand Up @@ -251,6 +247,11 @@ struct scatterlist *sg_next(struct scatterlist *);
struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
void sg_init_table(struct scatterlist *, unsigned int);
void sg_init_one(struct scatterlist *, const void *, unsigned int);
int sg_split(struct scatterlist *in, const int in_mapped_nents,
const off_t skip, const int nb_splits,
const size_t *split_sizes,
struct scatterlist **out, int *out_mapped_nents,
gfp_t gfp_mask);

typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t);
typedef void (sg_free_fn)(struct scatterlist *, unsigned int);
Expand Down
7 changes: 7 additions & 0 deletions lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,13 @@ config UCS2_STRING

source "lib/fonts/Kconfig"

config SG_SPLIT
def_bool n
help
Provides a heler to split scatterlists into chunks, each chunk being a
scatterlist. This should be selected by a driver or an API which
whishes to split a scatterlist amongst multiple DMA channel.

#
# sg chaining option
#
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o

obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o

obj-$(CONFIG_SG_SPLIT) += sg_split.o
obj-$(CONFIG_STMP_DEVICE) += stmp_device.o

libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \
Expand Down
4 changes: 0 additions & 4 deletions lib/scatterlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,12 @@ EXPORT_SYMBOL(sg_nents_for_len);
**/
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
{
#ifndef CONFIG_ARCH_HAS_SG_CHAIN
struct scatterlist *ret = &sgl[nents - 1];
#else
struct scatterlist *sg, *ret = NULL;
unsigned int i;

for_each_sg(sgl, sg, nents, i)
ret = sg;

#endif
#ifdef CONFIG_DEBUG_SG
BUG_ON(sgl[0].sg_magic != SG_MAGIC);
BUG_ON(!sg_is_last(ret));
Expand Down
Loading

0 comments on commit d975f30

Please sign in to comment.