#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 */