summaryrefslogtreecommitdiff
path: root/include/linux/bio.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/bio.h')
-rw-r--r--include/linux/bio.h50
1 files changed, 47 insertions, 3 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h
index b244108a27a8..ffc38fca9c1e 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -21,6 +21,8 @@
#define __LINUX_BIO_H
#include <linux/kdev_t.h>
+#include <linux/highmem.h>
+
/* Platforms may set this to teach the BIO layer about IOMMU hardware. */
#include <asm/io.h>
#ifndef BIO_VMERGE_BOUNDARY
@@ -47,9 +49,6 @@ struct bio_vec {
unsigned int bv_offset;
};
-/*
- * weee, c forward decl...
- */
struct bio;
typedef void (bio_end_io_t) (struct bio *);
typedef void (bio_destructor_t) (struct bio *);
@@ -206,4 +205,49 @@ extern inline void bio_init(struct bio *);
extern int bio_ioctl(kdev_t, unsigned int, unsigned long);
+#ifdef CONFIG_HIGHMEM
+/*
+ * remember to add offset! and never ever reenable interrupts between a
+ * bio_kmap_irq and bio_kunmap_irq!!
+ *
+ * This function MUST be inlined - it plays with the CPU interrupt flags.
+ * Hence the `extern inline'.
+ */
+extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags)
+{
+ unsigned long addr;
+
+ __save_flags(*flags);
+
+ /*
+ * could be low
+ */
+ if (!PageHighMem(bio_page(bio)))
+ return bio_data(bio);
+
+ /*
+ * it's a highmem page
+ */
+ __cli();
+ addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_SRC_IRQ);
+
+ if (addr & ~PAGE_MASK)
+ BUG();
+
+ return (char *) addr + bio_offset(bio);
+}
+
+extern inline void bio_kunmap_irq(char *buffer, unsigned long *flags)
+{
+ unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
+
+ kunmap_atomic((void *) ptr, KM_BIO_SRC_IRQ);
+ __restore_flags(*flags);
+}
+
+#else
+#define bio_kmap_irq(bio, flags) (bio_data(bio))
+#define bio_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0)
+#endif
+
#endif /* __LINUX_BIO_H */