RFC: pci_write_bits*() convenience functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There are a lot of code fragments in kernel looking like this:

u16 buf;
pci_read_config_word(pdev, offset, &buf);
buf &= ~mask;
buf |= value;
pci_write_config_word(pdev, offset, buf);

In in-kernel EDAC sources I found an implementation of pci_write_bits*()
that allows above 5 lines to be easily converted to:

pci_write_bits16(pdev, offset, value, mask);

Since this sequence is common while initializing a device or sometimes
during its normal operation I even wrote similar wrappers (see: driver
for CB710 memory card reader, posted about a month ago to LKML and
MMC mailinglists). I guess that there are more people hiding that
could use this.

This patch moves functions mentioned above to global include: linux/pci.h.
I verified that no users in EDAC code rely on the mask != (u16)(-1) test
and I think that plain pci_write_config_X() is better in cases where
this test is known to evaluate to false.

What's interesting, there are 2039 lines where pci_read_config_*() is used
and in only about 161 the return value is checked (as of current linux-2.6.git
tree: commit 3d44cc3e01..., quick grep test).

Best Regards,
Michał Mirosław

(Please Cc: me on reply to list.)

diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 4b55ec6..f1f8b94 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -722,54 +722,6 @@ struct edac_pci_ctl_info {
 #define to_edac_pci_ctl_work(w) \
 		container_of(w, struct edac_pci_ctl_info,work)
 
-/* write all or some bits in a byte-register*/
-static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
-				   u8 mask)
-{
-	if (mask != 0xff) {
-		u8 buf;
-
-		pci_read_config_byte(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_byte(pdev, offset, value);
-}
-
-/* write all or some bits in a word-register*/
-static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
-				    u16 value, u16 mask)
-{
-	if (mask != 0xffff) {
-		u16 buf;
-
-		pci_read_config_word(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_word(pdev, offset, value);
-}
-
-/* write all or some bits in a dword-register*/
-static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
-				    u32 value, u32 mask)
-{
-	if (mask != 0xffff) {
-		u32 buf;
-
-		pci_read_config_dword(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_dword(pdev, offset, value);
-}
-
 #endif				/* CONFIG_PCI */
 
 extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index feb4657..f9ee511 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -610,6 +610,22 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where,
 	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 
+#define GEN_PCI_UPDATE_FUNC(t,b)					\
+static inline void pci_write_bits##b(struct pci_dev *dev, int where,	\
+	u##b value, u##b mask)						\
+{									\
+	u##b buf;							\
+									\
+	pci_read_config_##t(dev, where, &buf);				\
+	buf &= ~mask;							\
+	buf |= value;							\
+	pci_write_config_##t(dev, where, buf);				\
+}
+GEN_PCI_UPDATE_FUNC(byte,8)
+GEN_PCI_UPDATE_FUNC(word,16)
+GEN_PCI_UPDATE_FUNC(dword,32)
+#undef GEN_PCI_UPDATE_FUNC
+
 int __must_check pci_enable_device(struct pci_dev *dev);
 int __must_check pci_enable_device_io(struct pci_dev *dev);
 int __must_check pci_enable_device_mem(struct pci_dev *dev);
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux