linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Logan Gunthorpe <logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-block-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org,
	linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: "Jens Axboe" <axboe-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org>,
	"Keith Busch"
	<keith.busch-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	"Andrew Morton"
	<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>,
	"Johannes Berg"
	<johannes.berg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	"Matthew Wilcox"
	<mawilcox-0li6OtcxBFHby3iVrkZq2A@public.gmane.org>,
	"Benjamin Herrenschmidt"
	<benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>,
	"Ming Lei" <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>,
	"Christian König" <christian.koenig-5C7GfCeVMHo@public.gmane.org>,
	"Jason Gunthorpe"
	<jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>,
	"Jerome Glisse" <jglisse-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	"Christoph Hellwig" <hch-jcswGhMUV9g@public.gmane.org>
Subject: [RFC PATCH 06/16] scatterlist: convert page_link to pfn_t
Date: Wed, 24 May 2017 15:42:17 -0600	[thread overview]
Message-ID: <1495662147-18277-7-git-send-email-logang@deltatee.com> (raw)
In-Reply-To: <1495662147-18277-1-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>

This patch replaces the old page_link bits with the somewhat safer
pfn_t. This change seems to have been planned for in the design of pfn_t
by Dan.

The conversion is surprisingly straightforward. sg_assign_pfn and
sg_set_pfn helpers are added which are similar analogs to their
page_link versions. A union for the chain pointer (with length and
offset) is also used instead of trying to shoehorn a pointer (that may
not be page aligned) into a pfn_t.

This results in some code that feels a fair bit cleaner seeing it avoids
a lot of casting and use of hard coded ones and twos.

The one side affect is that, on 32 bit systems, the sgl entry will be
32 bits larger seeing pfn_t is always 64 bits and the unsigned long it
replaced was 32 bits. However, it should still fit the same
SG_CHUNK_SIZE entries into a single page so this probably isn't a huge
issue.

Signed-off-by: Logan Gunthorpe <logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
Signed-off-by: Stephen Bates <sbates-pv7U853sEMVWk0Htik3J/w@public.gmane.org>
---
 drivers/memstick/core/mspro_block.c |   2 +-
 include/linux/scatterlist.h         | 145 ++++++++++++++++++++++--------------
 2 files changed, 92 insertions(+), 55 deletions(-)

diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index c00d8a2..38ae9ef 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -580,7 +580,7 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card,
 {
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	unsigned char t_val = 0;
-	struct scatterlist t_sg = { 0 };
+	struct scatterlist t_sg = {};
 	size_t t_offset;
 
 	if ((*mrq)->error)
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index cb3c8fe..cce3af9 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -5,16 +5,25 @@
 #include <linux/types.h>
 #include <linux/bug.h>
 #include <linux/mm.h>
+#include <linux/pfn_t.h>
 #include <asm/io.h>
 
 struct scatterlist {
 #ifdef CONFIG_DEBUG_SG
 	unsigned long	sg_magic;
 #endif
-	unsigned long	page_link;
-	unsigned int	offset;
-	unsigned int	length;
+	pfn_t		__pfn;
+	union {
+		struct {
+			unsigned int	offset;
+			unsigned int	length;
+		};
+
+		struct scatterlist *__chain;
+	};
+
 	dma_addr_t	dma_address;
+
 #ifdef CONFIG_NEED_SG_DMA_LENGTH
 	unsigned int	dma_length;
 #endif
@@ -41,33 +50,71 @@ struct sg_table {
 	unsigned int orig_nents;	/* original size of list */
 };
 
-/*
- * Notes on SG table design.
- *
- * We use the unsigned long page_link field in the scatterlist struct to place
- * the page pointer AND encode information about the sg table as well. The two
- * lower bits are reserved for this information.
- *
- * If bit 0 is set, then the page_link contains a pointer to the next sg
- * table list. Otherwise the next entry is at sg + 1.
- *
- * If bit 1 is set, then this sg entry is the last element in a list.
+#define SG_MAGIC	0x87654321
+
+static inline bool sg_is_chain(struct scatterlist *sg)
+{
+	return sg->__pfn.val & PFN_SG_CHAIN;
+}
+
+static inline bool sg_is_last(struct scatterlist *sg)
+{
+	return sg->__pfn.val & PFN_SG_LAST;
+}
+
+static inline struct scatterlist *sg_chain_ptr(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(!sg_is_chain(sg));
+#endif
+
+	return sg->__chain;
+}
+
+/**
+ * sg_assign_pfn - Assign a given pfn to an SG entry
+ * @sg:		   SG entry
+ * @pfn:	   The pfn
  *
- * See sg_next().
+ * Description:
+ *   Assign a to sg entry. Also see sg_set_pfn(), the most commonly used
+ *   variant.
  *
- */
+ **/
+static inline void sg_assign_pfn(struct scatterlist *sg, pfn_t pfn)
+{
+	u64 flags = sg->__pfn.val & PFN_SG_LAST;
 
-#define SG_MAGIC	0x87654321
+	pfn.val &= ~(PFN_SG_CHAIN | PFN_SG_LAST);
+	BUG_ON(!pfn_t_has_page(pfn));
 
-/*
- * We overload the LSB of the page pointer to indicate whether it's
- * a valid sg entry, or whether it points to the start of a new scatterlist.
- * Those low bits are there for everyone! (thanks mason :-)
- */
-#define sg_is_chain(sg)		((sg)->page_link & 0x01)
-#define sg_is_last(sg)		((sg)->page_link & 0x02)
-#define sg_chain_ptr(sg)	\
-	((struct scatterlist *) ((sg)->page_link & ~0x03))
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+	BUG_ON(sg_is_chain(sg));
+#endif
+
+	sg->__pfn.val = pfn.val | flags;
+}
+
+/**
+ * sg_set_pfn - Set sg entry to point at given pfn
+ * @sg:		 SG entry
+ * @pfn:	 The pfn
+ * @len:	 Length of data
+ * @offset:	 Offset into page
+ *
+ * Description:
+ *   Use this function to set an sg entry pointing at a pfn, never assign
+ *   the pfn directly.
+ *
+ **/
+static inline void sg_set_pfn(struct scatterlist *sg, pfn_t pfn,
+			      unsigned int len, unsigned int offset)
+{
+	sg_assign_pfn(sg, pfn);
+	sg->offset = offset;
+	sg->length = len;
+}
 
 /**
  * sg_assign_page - Assign a given page to an SG entry
@@ -81,18 +128,7 @@ struct sg_table {
  **/
 static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
 {
-	unsigned long page_link = sg->page_link & 0x3;
-
-	/*
-	 * In order for the low bit stealing approach to work, pages
-	 * must be aligned at a 32-bit boundary as a minimum.
-	 */
-	BUG_ON((unsigned long) page & 0x03);
-#ifdef CONFIG_DEBUG_SG
-	BUG_ON(sg->sg_magic != SG_MAGIC);
-	BUG_ON(sg_is_chain(sg));
-#endif
-	sg->page_link = page_link | (unsigned long) page;
+	sg_assign_pfn(sg, page_to_pfn_t(page));
 }
 
 /**
@@ -123,7 +159,17 @@ static inline struct page *sg_page(struct scatterlist *sg)
 	BUG_ON(sg->sg_magic != SG_MAGIC);
 	BUG_ON(sg_is_chain(sg));
 #endif
-	return (struct page *)((sg)->page_link & ~0x3);
+	return pfn_t_to_page(sg->__pfn);
+}
+
+static inline pfn_t sg_pfn_t(struct scatterlist *sg)
+{
+#ifdef CONFIG_DEBUG_SG
+	BUG_ON(sg->sg_magic != SG_MAGIC);
+	BUG_ON(sg_is_chain(sg));
+#endif
+
+	return sg->__pfn;
 }
 
 /**
@@ -161,17 +207,8 @@ 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)
 {
-	/*
-	 * offset and length are unused for chain entry.  Clear them.
-	 */
-	prv[prv_nents - 1].offset = 0;
-	prv[prv_nents - 1].length = 0;
-
-	/*
-	 * Set lowest bit to indicate a link pointer, and make sure to clear
-	 * the termination bit if it happens to be set.
-	 */
-	prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
+	prv[prv_nents - 1].__pfn = __pfn_to_pfn_t(0, PFN_SG_CHAIN);
+	prv[prv_nents - 1].__chain = sgl;
 }
 
 /**
@@ -191,8 +228,8 @@ static inline void sg_mark_end(struct scatterlist *sg)
 	/*
 	 * Set termination bit, clear potential chain bit
 	 */
-	sg->page_link |= 0x02;
-	sg->page_link &= ~0x01;
+	sg->__pfn.val |= PFN_SG_LAST;
+	sg->__pfn.val &= ~PFN_SG_CHAIN;
 }
 
 /**
@@ -208,7 +245,7 @@ static inline void sg_unmark_end(struct scatterlist *sg)
 #ifdef CONFIG_DEBUG_SG
 	BUG_ON(sg->sg_magic != SG_MAGIC);
 #endif
-	sg->page_link &= ~0x02;
+	sg->__pfn.val &= ~PFN_SG_LAST;
 }
 
 /**
@@ -223,7 +260,7 @@ static inline void sg_unmark_end(struct scatterlist *sg)
  **/
 static inline dma_addr_t sg_phys(struct scatterlist *sg)
 {
-	return page_to_phys(sg_page(sg)) + sg->offset;
+	return pfn_t_to_phys(sg->__pfn) + sg->offset;
 }
 
 /**
-- 
2.1.4

  parent reply	other threads:[~2017-05-24 21:42 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-24 21:42 [RFC PATCH 00/16] Unmappable memory in SGLs for p2p transfers Logan Gunthorpe
     [not found] ` <1495662147-18277-1-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-05-24 21:42   ` [RFC PATCH 01/16] dmaengine: ste_dma40, imx-dma: Cleanup scatterlist layering violations Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 02/16] staging: ccree: Cleanup: remove references to page_link Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 03/16] kfifo: Cleanup example to not use page_link Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 04/16] um: add dummy ioremap and iounmap functions Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 05/16] tile: provide default ioremap declaration Logan Gunthorpe
2017-05-24 21:42   ` Logan Gunthorpe [this message]
2017-05-24 21:42   ` [RFC PATCH 07/16] scatterlist: support unmappable memory in the scatterlist Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 08/16] scatterlist: add iomem support to sg_miter and sg_copy_* Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 09/16] bvec: introduce bvec_page and bvec_set_page accessors Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 10/16] bvec: massive conversion of all bv_page users Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 11/16] bvec: convert to using pfn_t internally Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 12/16] bvec: use sg_set_pfn when mapping a bio to an sgl Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 13/16] block: bio: introduce bio_add_pfn Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 14/16] block: bio: go straight from pfn_t to phys instead of through page Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 15/16] dma-mapping: introduce and use unmappable safe sg_virt call Logan Gunthorpe
2017-05-24 21:42   ` [RFC PATCH 16/16] nvmet: use unmappable sgl in rdma target Logan Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1495662147-18277-7-git-send-email-logang@deltatee.com \
    --to=logang-otvngxwrz7hwk0htik3j/w@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=axboe-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org \
    --cc=benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org \
    --cc=christian.koenig-5C7GfCeVMHo@public.gmane.org \
    --cc=hch-jcswGhMUV9g@public.gmane.org \
    --cc=jglisse-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org \
    --cc=johannes.berg-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=keith.busch-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=linux-block-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org \
    --cc=linux-nvme-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mawilcox-0li6OtcxBFHby3iVrkZq2A@public.gmane.org \
    --cc=ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).