greybus: kernel_ver: add sg copy operations for kernel < 3.11
For older kernel, < 3.11, no copy to/from buffer with skip support was defined. This could break builds for this versions of kernel. Add them here. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Tested-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
5656ab99a0
commit
8a01b408a6
|
@ -135,4 +135,104 @@ static inline void sysfs_remove_groups(struct kobject *kobj,
|
|||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
|
||||
#define MMC_POWER_UNDEFINED_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
|
||||
#include <linux/scatterlist.h>
|
||||
static inline bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
|
||||
{
|
||||
if (!miter->__remaining) {
|
||||
struct scatterlist *sg;
|
||||
unsigned long pgoffset;
|
||||
|
||||
if (!__sg_page_iter_next(&miter->piter))
|
||||
return false;
|
||||
|
||||
sg = miter->piter.sg;
|
||||
pgoffset = miter->piter.sg_pgoffset;
|
||||
|
||||
miter->__offset = pgoffset ? 0 : sg->offset;
|
||||
miter->__remaining = sg->offset + sg->length -
|
||||
(pgoffset << PAGE_SHIFT) - miter->__offset;
|
||||
miter->__remaining = min_t(unsigned long, miter->__remaining,
|
||||
PAGE_SIZE - miter->__offset);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset)
|
||||
{
|
||||
sg_miter_stop(miter);
|
||||
|
||||
while (offset) {
|
||||
off_t consumed;
|
||||
|
||||
if (!sg_miter_get_next_page(miter))
|
||||
return false;
|
||||
|
||||
consumed = min_t(off_t, offset, miter->__remaining);
|
||||
miter->__offset += consumed;
|
||||
miter->__remaining -= consumed;
|
||||
offset -= consumed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline size_t _sg_copy_buffer(struct scatterlist *sgl,
|
||||
unsigned int nents, void *buf,
|
||||
size_t buflen, off_t skip,
|
||||
bool to_buffer)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
struct sg_mapping_iter miter;
|
||||
unsigned long flags;
|
||||
unsigned int sg_flags = SG_MITER_ATOMIC;
|
||||
|
||||
if (to_buffer)
|
||||
sg_flags |= SG_MITER_FROM_SG;
|
||||
else
|
||||
sg_flags |= SG_MITER_TO_SG;
|
||||
|
||||
sg_miter_start(&miter, sgl, nents, sg_flags);
|
||||
|
||||
if (!sg_miter_skip(&miter, skip))
|
||||
return false;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
while (sg_miter_next(&miter) && offset < buflen) {
|
||||
unsigned int len;
|
||||
|
||||
len = min(miter.length, buflen - offset);
|
||||
|
||||
if (to_buffer)
|
||||
memcpy(buf + offset, miter.addr, len);
|
||||
else
|
||||
memcpy(miter.addr, buf + offset, len);
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
sg_miter_stop(&miter);
|
||||
|
||||
local_irq_restore(flags);
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline size_t sg_pcopy_to_buffer(struct scatterlist *sgl,
|
||||
unsigned int nents, void *buf,
|
||||
size_t buflen, off_t skip)
|
||||
{
|
||||
return _sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
|
||||
}
|
||||
|
||||
static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl,
|
||||
unsigned int nents, void *buf,
|
||||
size_t buflen, off_t skip)
|
||||
{
|
||||
return _sg_copy_buffer(sgl, nents, buf, buflen, skip, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GREYBUS_KERNEL_VER_H */
|
||||
|
|
Loading…
Reference in a new issue