Subversion Repositories Kolibri OS

Rev

Rev 5270 | Rev 6293 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5270 Rev 6082
Line 52... Line 52...
52
		nents++;
52
		nents++;
53
	return nents;
53
	return nents;
54
}
54
}
55
EXPORT_SYMBOL(sg_nents);
55
EXPORT_SYMBOL(sg_nents);
Line -... Line 56...
-
 
56
 
-
 
57
/**
-
 
58
 * sg_nents_for_len - return total count of entries in scatterlist
-
 
59
 *                    needed to satisfy the supplied length
-
 
60
 * @sg:		The scatterlist
-
 
61
 * @len:	The total required length
-
 
62
 *
-
 
63
 * Description:
-
 
64
 * Determines the number of entries in sg that are required to meet
-
 
65
 * the supplied length, taking into acount chaining as well
-
 
66
 *
-
 
67
 * Returns:
-
 
68
 *   the number of sg entries needed, negative error on failure
-
 
69
 *
-
 
70
 **/
-
 
71
int sg_nents_for_len(struct scatterlist *sg, u64 len)
-
 
72
{
-
 
73
	int nents;
-
 
74
	u64 total;
-
 
75
 
-
 
76
	if (!len)
-
 
77
		return 0;
-
 
78
 
-
 
79
	for (nents = 0, total = 0; sg; sg = sg_next(sg)) {
-
 
80
		nents++;
-
 
81
		total += sg->length;
-
 
82
		if (total >= len)
-
 
83
			return nents;
-
 
84
	}
-
 
85
 
-
 
86
	return -EINVAL;
-
 
87
}
Line 56... Line 88...
56
 
88
EXPORT_SYMBOL(sg_nents_for_len);
57
 
89
 
58
/**
90
/**
59
 * sg_last - return the last scatterlist entry in a list
91
 * sg_last - return the last scatterlist entry in a list
Line 69... Line 101...
69
 *   exist from @sgl@.
101
 *   exist from @sgl@.
70
 *
102
 *
71
 **/
103
 **/
72
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
104
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
73
{
105
{
74
#ifndef CONFIG_ARCH_HAS_SG_CHAIN
-
 
75
	struct scatterlist *ret = &sgl[nents - 1];
-
 
76
#else
-
 
77
	struct scatterlist *sg, *ret = NULL;
106
	struct scatterlist *sg, *ret = NULL;
78
	unsigned int i;
107
	unsigned int i;
Line 79... Line 108...
79
 
108
 
80
	for_each_sg(sgl, sg, nents, i)
109
	for_each_sg(sgl, sg, nents, i)
Line 81... Line -...
81
		ret = sg;
-
 
82
 
110
		ret = sg;
83
#endif
111
 
84
#ifdef CONFIG_DEBUG_SG
112
#ifdef CONFIG_DEBUG_SG
85
	BUG_ON(sgl[0].sg_magic != SG_MAGIC);
113
	BUG_ON(sgl[0].sg_magic != SG_MAGIC);
86
	BUG_ON(!sg_is_last(ret));
114
	BUG_ON(!sg_is_last(ret));
Line 358... Line 386...
358
 
386
 
359
    return true;
387
	return true;
360
}
388
}
Line -... Line 389...
-
 
389
EXPORT_SYMBOL(__sg_page_iter_next);
-
 
390
 
-
 
391
/**
-
 
392
 * sg_miter_start - start mapping iteration over a sg list
-
 
393
 * @miter: sg mapping iter to be started
-
 
394
 * @sgl: sg list to iterate over
-
 
395
 * @nents: number of sg entries
-
 
396
 *
-
 
397
 * Description:
-
 
398
 *   Starts mapping iterator @miter.
-
 
399
 *
-
 
400
 * Context:
-
 
401
 *   Don't care.
-
 
402
 */
-
 
403
void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
-
 
404
		    unsigned int nents, unsigned int flags)
-
 
405
{
-
 
406
	memset(miter, 0, sizeof(struct sg_mapping_iter));
-
 
407
 
-
 
408
	__sg_page_iter_start(&miter->piter, sgl, nents, 0);
-
 
409
	WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
-
 
410
	miter->__flags = flags;
-
 
411
}
-
 
412
EXPORT_SYMBOL(sg_miter_start);
-
 
413
 
-
 
414
static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
-
 
415
{
-
 
416
	if (!miter->__remaining) {
-
 
417
		struct scatterlist *sg;
-
 
418
		unsigned long pgoffset;
-
 
419
 
-
 
420
		if (!__sg_page_iter_next(&miter->piter))
-
 
421
			return false;
-
 
422
 
-
 
423
		sg = miter->piter.sg;
-
 
424
		pgoffset = miter->piter.sg_pgoffset;
-
 
425
 
-
 
426
		miter->__offset = pgoffset ? 0 : sg->offset;
-
 
427
		miter->__remaining = sg->offset + sg->length -
-
 
428
				(pgoffset << PAGE_SHIFT) - miter->__offset;
-
 
429
		miter->__remaining = min_t(unsigned long, miter->__remaining,
-
 
430
					   PAGE_SIZE - miter->__offset);
-
 
431
	}
-
 
432
 
-
 
433
	return true;
-
 
434
}
-
 
435
 
-
 
436
/**
-
 
437
 * sg_miter_skip - reposition mapping iterator
-
 
438
 * @miter: sg mapping iter to be skipped
-
 
439
 * @offset: number of bytes to plus the current location
-
 
440
 *
-
 
441
 * Description:
-
 
442
 *   Sets the offset of @miter to its current location plus @offset bytes.
-
 
443
 *   If mapping iterator @miter has been proceeded by sg_miter_next(), this
-
 
444
 *   stops @miter.
-
 
445
 *
-
 
446
 * Context:
-
 
447
 *   Don't care if @miter is stopped, or not proceeded yet.
-
 
448
 *   Otherwise, preemption disabled if the SG_MITER_ATOMIC is set.
-
 
449
 *
-
 
450
 * Returns:
-
 
451
 *   true if @miter contains the valid mapping.  false if end of sg
-
 
452
 *   list is reached.
-
 
453
 */
-
 
454
bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset)
-
 
455
{
-
 
456
	sg_miter_stop(miter);
-
 
457
 
-
 
458
	while (offset) {
-
 
459
		off_t consumed;
-
 
460
 
-
 
461
		if (!sg_miter_get_next_page(miter))
-
 
462
			return false;
-
 
463
 
-
 
464
		consumed = min_t(off_t, offset, miter->__remaining);
-
 
465
		miter->__offset += consumed;
-
 
466
		miter->__remaining -= consumed;
-
 
467
		offset -= consumed;
-
 
468
	}
-
 
469
 
-
 
470
	return true;
-
 
471
}
-
 
472
EXPORT_SYMBOL(sg_miter_skip);
-
 
473
 
-
 
474
/**
-
 
475
 * sg_miter_next - proceed mapping iterator to the next mapping
-
 
476
 * @miter: sg mapping iter to proceed
-
 
477
 *
-
 
478
 * Description:
-
 
479
 *   Proceeds @miter to the next mapping.  @miter should have been started
-
 
480
 *   using sg_miter_start().  On successful return, @miter->page,
-
 
481
 *   @miter->addr and @miter->length point to the current mapping.
-
 
482
 *
-
 
483
 * Context:
-
 
484
 *   Preemption disabled if SG_MITER_ATOMIC.  Preemption must stay disabled
-
 
485
 *   till @miter is stopped.  May sleep if !SG_MITER_ATOMIC.
-
 
486
 *
-
 
487
 * Returns:
-
 
488
 *   true if @miter contains the next mapping.  false if end of sg
-
 
489
 *   list is reached.
-
 
490
 */
-
 
491
bool sg_miter_next(struct sg_mapping_iter *miter)
-
 
492
{
-
 
493
	sg_miter_stop(miter);
-
 
494
 
-
 
495
	/*
-
 
496
	 * Get to the next page if necessary.
-
 
497
	 * __remaining, __offset is adjusted by sg_miter_stop
-
 
498
	 */
-
 
499
	if (!sg_miter_get_next_page(miter))
-
 
500
		return false;
-
 
501
 
Line -... Line 502...
-
 
502
	miter->page = sg_page_iter_page(&miter->piter);
-
 
503
	miter->consumed = miter->length = miter->__remaining;
-
 
504
 
-
 
505
	if (miter->__flags & SG_MITER_ATOMIC)
-
 
506
		miter->addr = kmap_atomic(miter->page) + miter->__offset;
-
 
507
	else
-
 
508
		miter->addr = kmap(miter->page) + miter->__offset;
-
 
509
 
-
 
510
	return true;
-
 
511
}
-
 
512
EXPORT_SYMBOL(sg_miter_next);
-
 
513
 
-
 
514
/**
-
 
515
 * sg_miter_stop - stop mapping iteration
-
 
516
 * @miter: sg mapping iter to be stopped
-
 
517
 *
-
 
518
 * Description:
-
 
519
 *   Stops mapping iterator @miter.  @miter should have been started
-
 
520
 *   started using sg_miter_start().  A stopped iteration can be
-
 
521
 *   resumed by calling sg_miter_next() on it.  This is useful when
-
 
522
 *   resources (kmap) need to be released during iteration.
-
 
523
 *
-
 
524
 * Context:
-
 
525
 *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
-
 
526
 *   otherwise.
-
 
527
 */
-
 
528
void sg_miter_stop(struct sg_mapping_iter *miter)
-
 
529
{
-
 
530
	WARN_ON(miter->consumed > miter->length);
-
 
531
 
-
 
532
	/* drop resources from the last iteration */
-
 
533
	if (miter->addr) {
-
 
534
		miter->__offset += miter->consumed;
-
 
535
		miter->__remaining -= miter->consumed;
-
 
536
 
-
 
537
		if (miter->__flags & SG_MITER_ATOMIC) {
-
 
538
			WARN_ON_ONCE(preemptible());
-
 
539
			kunmap_atomic(miter->addr);
-
 
540
		} else
-
 
541
			kunmap(miter->page);
-
 
542
 
-
 
543
		miter->page = NULL;
-
 
544
		miter->addr = NULL;
-
 
545
		miter->length = 0;
-
 
546
		miter->consumed = 0;
-
 
547
	}
-
 
548
}
-
 
549
EXPORT_SYMBOL(sg_miter_stop);
-
 
550
 
-
 
551
/**
-
 
552
 * sg_copy_buffer - Copy data between a linear buffer and an SG list
-
 
553
 * @sgl:		 The SG list
-
 
554
 * @nents:		 Number of SG entries
-
 
555
 * @buf:		 Where to copy from
-
 
556
 * @buflen:		 The number of bytes to copy
-
 
557
 * @skip:		 Number of bytes to skip before copying
-
 
558
 * @to_buffer:		 transfer direction (true == from an sg list to a
-
 
559
 *			 buffer, false == from a buffer to an sg list
-
 
560
 *
-
 
561
 * Returns the number of copied bytes.
-
 
562
 *
-
 
563
 **/
-
 
564
size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
-
 
565
		      size_t buflen, off_t skip, bool to_buffer)
-
 
566
{
-
 
567
	unsigned int offset = 0;
-
 
568
	struct sg_mapping_iter miter;
-
 
569
	unsigned long flags;
-
 
570
	unsigned int sg_flags = SG_MITER_ATOMIC;
-
 
571
 
-
 
572
	if (to_buffer)
-
 
573
		sg_flags |= SG_MITER_FROM_SG;
-
 
574
	else
Line -... Line 575...
-
 
575
		sg_flags |= SG_MITER_TO_SG;
-
 
576
 
-
 
577
	sg_miter_start(&miter, sgl, nents, sg_flags);
-
 
578
 
-
 
579
	if (!sg_miter_skip(&miter, skip))
-
 
580
		return false;
-
 
581
 
-
 
582
	local_irq_save(flags);
-
 
583
 
-
 
584
	while (sg_miter_next(&miter) && offset < buflen) {
-
 
585
		unsigned int len;
-
 
586
 
-
 
587
		len = min(miter.length, buflen - offset);
-
 
588
 
-
 
589
		if (to_buffer)
-
 
590
			memcpy(buf + offset, miter.addr, len);
-
 
591
		else
-
 
592
			memcpy(miter.addr, buf + offset, len);
-
 
593
 
-
 
594
		offset += len;
-
 
595
	}
-
 
596
 
-
 
597
	sg_miter_stop(&miter);
-
 
598
 
-
 
599
	local_irq_restore(flags);
-
 
600
	return offset;
-
 
601
}
-
 
602
EXPORT_SYMBOL(sg_copy_buffer);
-
 
603
 
-
 
604
/**
-
 
605
 * sg_copy_from_buffer - Copy from a linear buffer to an SG list
-
 
606
 * @sgl:		 The SG list
-
 
607
 * @nents:		 Number of SG entries
-
 
608
 * @buf:		 Where to copy from
-
 
609
 * @buflen:		 The number of bytes to copy
-
 
610
 *
-
 
611
 * Returns the number of copied bytes.
-
 
612
 *
-
 
613
 **/
-
 
614
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
-
 
615
			   const void *buf, size_t buflen)
-
 
616
{
-
 
617
	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, 0, false);
-
 
618
}
-
 
619
EXPORT_SYMBOL(sg_copy_from_buffer);
-
 
620
 
-
 
621
/**
-
 
622
 * sg_copy_to_buffer - Copy from an SG list to a linear buffer
-
 
623
 * @sgl:		 The SG list
-
 
624
 * @nents:		 Number of SG entries
-
 
625
 * @buf:		 Where to copy to
-
 
626
 * @buflen:		 The number of bytes to copy
-
 
627
 *
-
 
628
 * Returns the number of copied bytes.
-
 
629
 *
-
 
630
 **/
-
 
631
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
-
 
632
			 void *buf, size_t buflen)
-
 
633
{
-
 
634
	return sg_copy_buffer(sgl, nents, buf, buflen, 0, true);
-
 
635
}
-
 
636
EXPORT_SYMBOL(sg_copy_to_buffer);
-
 
637
 
-
 
638
/**
-
 
639
 * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list
-
 
640
 * @sgl:		 The SG list
-
 
641
 * @nents:		 Number of SG entries
-
 
642
 * @buf:		 Where to copy from
-
 
643
 * @buflen:		 The number of bytes to copy
-
 
644
 * @skip:		 Number of bytes to skip before copying
-
 
645
 *
-
 
646
 * Returns the number of copied bytes.
-
 
647
 *
-
 
648
 **/
-
 
649
size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
-
 
650
			    const void *buf, size_t buflen, off_t skip)
-
 
651
{
-
 
652
	return sg_copy_buffer(sgl, nents, (void *)buf, buflen, skip, false);
-
 
653
}
-
 
654
EXPORT_SYMBOL(sg_pcopy_from_buffer);
-
 
655
 
-
 
656
/**
-
 
657
 * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer
-
 
658
 * @sgl:		 The SG list
-
 
659
 * @nents:		 Number of SG entries
-
 
660
 * @buf:		 Where to copy to
-
 
661
 * @buflen:		 The number of bytes to copy
-
 
662
 * @skip:		 Number of bytes to skip before copying
-
 
663
 *
-
 
664
 * Returns the number of copied bytes.
-
 
665
 *
-
 
666
 **/
-
 
667
size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
-
 
668
			  void *buf, size_t buflen, off_t skip)