194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings#include <linux/delay.h>
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
4f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/sched.h>
55a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
77ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox#include <linux/wait.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
948b19148733b4826eeedfd8be9f19b61c8d010b1Adrian Bunk#include "pci.h"
1048b19148733b4826eeedfd8be9f19b61c8d010b1Adrian Bunk
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This interrupt-safe spinlock protects all accesses to PCI
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configuration space.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16a2e27787f893621c5a6b865acf6b7766f8671328Jan KiszkaDEFINE_RAW_SPINLOCK(pci_lock);
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Wrappers for all PCI configuration access functions.  They just check
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  alignment, do locking and call the low-level functions pointed to
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  by pci_dev->ops.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_byte_BAD 0
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_word_BAD (pos & 1)
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_dword_BAD (pos & 3)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_OP_READ(size,type,len) \
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_bus_read_config_##size \
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(struct pci_bus *bus, unsigned int devfn, int pos, type *value)	\
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{									\
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;							\
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;						\
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 data = 0;							\
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
36511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irqsave(&pci_lock, flags);			\
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = bus->ops->read(bus, devfn, pos, len, &data);		\
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*value = (type)data;						\
39511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irqrestore(&pci_lock, flags);		\
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;							\
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_OP_WRITE(size,type,len) \
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_bus_write_config_##size \
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(struct pci_bus *bus, unsigned int devfn, int pos, type value)	\
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{									\
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;							\
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;						\
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
50511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irqsave(&pci_lock, flags);			\
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = bus->ops->write(bus, devfn, pos, len, value);		\
52511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irqrestore(&pci_lock, flags);		\
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;							\
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_READ(byte, u8, 1)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_READ(word, u16, 2)
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_READ(dword, u32, 4)
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_WRITE(byte, u8, 1)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_WRITE(word, u16, 2)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsPCI_OP_WRITE(dword, u32, 4)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_read_config_byte);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_read_config_word);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_read_config_dword);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_write_config_byte);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_write_config_word);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_write_config_dword);
69e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
70a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying/**
71a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying * pci_bus_set_ops - Set raw operations of pci bus
72a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying * @bus:	pci bus struct
73a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying * @ops:	new raw operations
74a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying *
75a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying * Return previous raw operations
76a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying */
77a72b46c3849cdb05993015991bde548ab8b6d7acHuang Yingstruct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
78a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying{
79a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying	struct pci_ops *old_ops;
80a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying	unsigned long flags;
81a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying
82511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irqsave(&pci_lock, flags);
83a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying	old_ops = bus->ops;
84a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying	bus->ops = ops;
85511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irqrestore(&pci_lock, flags);
86a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying	return old_ops;
87a72b46c3849cdb05993015991bde548ab8b6d7acHuang Ying}
88a72b46c3849cdb05993015991bde548ab8b6d7acHuang YingEXPORT_SYMBOL(pci_bus_set_ops);
89287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
90287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger/**
91287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * pci_read_vpd - Read one entry from Vital Product Data
92287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @dev:	pci device struct
93287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @pos:	offset in vpd space
94287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @count:	number of bytes to read
95287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @buf:	pointer to where to store result
96287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger *
97287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger */
98287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemmingerssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
99287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger{
100287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	if (!dev->vpd || !dev->vpd->ops)
101287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		return -ENODEV;
102287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	return dev->vpd->ops->read(dev, pos, count, buf);
103287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger}
104287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen HemmingerEXPORT_SYMBOL(pci_read_vpd);
105287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
106287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger/**
107287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * pci_write_vpd - Write entry to Vital Product Data
108287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @dev:	pci device struct
109287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger * @pos:	offset in vpd space
110cffb2fafb726c898fec1c5ae33717741f94fda83Randy Dunlap * @count:	number of bytes to write
111cffb2fafb726c898fec1c5ae33717741f94fda83Randy Dunlap * @buf:	buffer containing write data
112287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger *
113287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger */
114287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemmingerssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
115287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger{
116287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	if (!dev->vpd || !dev->vpd->ops)
117287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		return -ENODEV;
118287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	return dev->vpd->ops->write(dev, pos, count, buf);
119287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger}
120287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen HemmingerEXPORT_SYMBOL(pci_write_vpd);
121287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
1227ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox/*
1237ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox * The following routines are to prevent the user from accessing PCI config
1247ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox * space when it's unsafe to do so.  Some devices require this during BIST and
1257ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox * we're required to prevent it during D-state transitions.
1267ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox *
1277ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox * We have a bit per device to indicate it's blocked and a global wait queue
1287ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox * for callers to sleep on until devices are unblocked.
1297ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox */
130fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszkastatic DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
131e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
132fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszkastatic noinline void pci_wait_cfg(struct pci_dev *dev)
1337ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox{
1347ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	DECLARE_WAITQUEUE(wait, current);
1357ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox
136fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	__add_wait_queue(&pci_cfg_wait, &wait);
1377ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	do {
1387ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox		set_current_state(TASK_UNINTERRUPTIBLE);
139511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner		raw_spin_unlock_irq(&pci_lock);
1407ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox		schedule();
141511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner		raw_spin_lock_irq(&pci_lock);
142fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	} while (dev->block_cfg_access);
143fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	__remove_wait_queue(&pci_cfg_wait, &wait);
144e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King}
145e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
14634e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen/* Returns 0 on success, negative values indicate error. */
147e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King#define PCI_USER_READ_CONFIG(size,type)					\
148e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian Kingint pci_user_read_config_##size						\
149e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	(struct pci_dev *dev, int pos, type *val)			\
150e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King{									\
151e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	int ret = 0;							\
152e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	u32 data = -1;							\
15334e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen	if (PCI_##size##_BAD)						\
15434e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen		return -EINVAL;						\
155511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irq(&pci_lock);				\
156fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	if (unlikely(dev->block_cfg_access))				\
157fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka		pci_wait_cfg(dev);					\
1587ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	ret = dev->bus->ops->read(dev->bus, dev->devfn,			\
159e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King					pos, sizeof(type), &data);	\
160511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irq(&pci_lock);				\
161e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	*val = (type)data;						\
16234e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen	if (ret > 0)							\
16334e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen		ret = -EINVAL;						\
164e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	return ret;							\
165e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King}
166e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
16734e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen/* Returns 0 on success, negative values indicate error. */
168e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King#define PCI_USER_WRITE_CONFIG(size,type)				\
169e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian Kingint pci_user_write_config_##size					\
170e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	(struct pci_dev *dev, int pos, type val)			\
171e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King{									\
172e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	int ret = -EIO;							\
17334e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen	if (PCI_##size##_BAD)						\
17434e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen		return -EINVAL;						\
175511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irq(&pci_lock);				\
176fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	if (unlikely(dev->block_cfg_access))				\
177fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka		pci_wait_cfg(dev);					\
1787ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	ret = dev->bus->ops->write(dev->bus, dev->devfn,		\
179e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King					pos, sizeof(type), val);	\
180511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irq(&pci_lock);				\
18134e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen	if (ret > 0)							\
18234e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen		ret = -EINVAL;						\
183e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	return ret;							\
184e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King}
185e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
186e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_READ_CONFIG(byte, u8)
187e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_READ_CONFIG(word, u16)
188e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_READ_CONFIG(dword, u32)
189e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_WRITE_CONFIG(byte, u8)
190e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_WRITE_CONFIG(word, u16)
191e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian KingPCI_USER_WRITE_CONFIG(dword, u32)
192e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
19394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings/* VPD access through PCI 2.2+ VPD capability */
19494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
19594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1)
19694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
19794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsstruct pci_vpd_pci22 {
19894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	struct pci_vpd base;
1991120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	struct mutex lock;
2001120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	u16	flag;
20194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	bool	busy;
2021120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	u8	cap;
20394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings};
20494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
2051120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger/*
2061120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger * Wait for last operation to complete.
2071120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger * This code has to spin since there is no other notification from the PCI
2081120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger * hardware. Since the VPD is often implemented by serial attachment to an
2091120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger * EEPROM, it may take many milliseconds to complete.
21034e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen *
21134e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen * Returns 0 on success, negative values indicate error.
2121120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger */
21394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsstatic int pci_vpd_pci22_wait(struct pci_dev *dev)
21494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings{
21594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	struct pci_vpd_pci22 *vpd =
21694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		container_of(dev->vpd, struct pci_vpd_pci22, base);
2171120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	unsigned long timeout = jiffies + HZ/20 + 2;
2181120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	u16 status;
21994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	int ret;
22094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
22194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	if (!vpd->busy)
22294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		return 0;
22394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
22494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	for (;;) {
2251120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
22694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings						&status);
22734e3207205ef492451cc5c53694d4772a9728b9fGreg Thelen		if (ret < 0)
22894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings			return ret;
2291120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger
2301120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
23194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings			vpd->busy = false;
23294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings			return 0;
23394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		}
2341120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger
2355030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava		if (time_after(jiffies, timeout)) {
2365030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava			dev_printk(KERN_DEBUG, &dev->dev,
2375030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava				   "vpd r/w failed.  This is likely a firmware "
2385030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava				   "bug on this device.  Contact the card "
2395030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava				   "vendor for a firmware update.");
24094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings			return -ETIMEDOUT;
2415030718ee465c759c2a851851e79039f58b9efb3Prarit Bhargava		}
2421120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		if (fatal_signal_pending(current))
2431120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger			return -EINTR;
2441120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		if (!cond_resched())
2451120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger			udelay(10);
24694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	}
24794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings}
24894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
249287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemmingerstatic ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
250287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger				  void *arg)
25194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings{
25294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	struct pci_vpd_pci22 *vpd =
25394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		container_of(dev->vpd, struct pci_vpd_pci22, base);
254287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	int ret;
255287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	loff_t end = pos + count;
256287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	u8 *buf = arg;
25794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
258287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	if (pos < 0 || pos > vpd->base.len || end > vpd->base.len)
25994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		return -EINVAL;
26094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
2611120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	if (mutex_lock_killable(&vpd->lock))
2621120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		return -EINTR;
2631120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger
26494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	ret = pci_vpd_pci22_wait(dev);
26594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	if (ret < 0)
26694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		goto out;
2671120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger
268287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	while (pos < end) {
269287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		u32 val;
270287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		unsigned int i, skip;
271287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
272287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
273287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger						 pos & ~3);
274287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		if (ret < 0)
275287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			break;
276287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		vpd->busy = true;
277287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		vpd->flag = PCI_VPD_ADDR_F;
278287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_vpd_pci22_wait(dev);
279287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		if (ret < 0)
280287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			break;
281287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
282287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA, &val);
283287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		if (ret < 0)
284287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			break;
285287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
286287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		skip = pos & 3;
287287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		for (i = 0;  i < sizeof(u32); i++) {
288287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			if (i >= skip) {
289287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger				*buf++ = val;
290287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger				if (++pos == end)
291287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger					break;
292287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			}
293287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			val >>= 8;
294287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		}
295287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	}
29694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsout:
2971120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	mutex_unlock(&vpd->lock);
298287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	return ret ? ret : count;
29994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings}
30094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
301287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemmingerstatic ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count,
302287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger				   const void *arg)
30394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings{
30494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	struct pci_vpd_pci22 *vpd =
30594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		container_of(dev->vpd, struct pci_vpd_pci22, base);
306287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	const u8 *buf = arg;
307287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	loff_t end = pos + count;
3081120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	int ret = 0;
30994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
310287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	if (pos < 0 || (pos & 3) || (count & 3) || end > vpd->base.len)
31194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		return -EINVAL;
31294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
3131120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	if (mutex_lock_killable(&vpd->lock))
3141120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger		return -EINTR;
315287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
31694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	ret = pci_vpd_pci22_wait(dev);
31794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	if (ret < 0)
31894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		goto out;
319287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
320287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	while (pos < end) {
321287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		u32 val;
322287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
323287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		val = *buf++;
324287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		val |= *buf++ << 8;
325287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		val |= *buf++ << 16;
326287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		val |= *buf++ << 24;
327287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
328287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA, val);
329287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		if (ret < 0)
330287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			break;
331287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
332287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger						 pos | PCI_VPD_ADDR_F);
333287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		if (ret < 0)
334287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger			break;
335287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
336287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		vpd->busy = true;
337287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		vpd->flag = 0;
338287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		ret = pci_vpd_pci22_wait(dev);
339d97ecd819137118b4686a753415f93215a6edacfGreg Thelen		if (ret < 0)
340d97ecd819137118b4686a753415f93215a6edacfGreg Thelen			break;
341287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger
342287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger		pos += sizeof(u32);
343287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	}
34494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsout:
3451120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	mutex_unlock(&vpd->lock);
346287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemminger	return ret ? ret : count;
34794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings}
34894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
34994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsstatic void pci_vpd_pci22_release(struct pci_dev *dev)
35094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings{
35194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
35294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings}
35394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
354287d19ce2e67c15e79a187b3bdcbbea1a0a51a7dStephen Hemmingerstatic const struct pci_vpd_ops pci_vpd_pci22_ops = {
35594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	.read = pci_vpd_pci22_read,
35694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	.write = pci_vpd_pci22_write,
35794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	.release = pci_vpd_pci22_release,
35894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings};
35994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
36094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchingsint pci_vpd_pci22_init(struct pci_dev *dev)
36194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings{
36294e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	struct pci_vpd_pci22 *vpd;
36394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	u8 cap;
36494e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
36594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
36694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	if (!cap)
36794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		return -ENODEV;
36894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
36994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	if (!vpd)
37094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings		return -ENOMEM;
37194e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
37299cb233d60cbe644203f19938c729ea2bb004d70Benjamin Li	vpd->base.len = PCI_VPD_PCI22_SIZE;
37394e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	vpd->base.ops = &pci_vpd_pci22_ops;
3741120f8b8169fb2cb51219d326892d963e762edb6Stephen Hemminger	mutex_init(&vpd->lock);
37594e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	vpd->cap = cap;
37694e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	vpd->busy = false;
37794e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	dev->vpd = &vpd->base;
37894e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings	return 0;
37994e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings}
38094e6108803469a37ee1e3c92dafdd1d59298602fBen Hutchings
381e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King/**
382db5679437a2b938c9127480a3923633721583a4fStephen Hemminger * pci_vpd_truncate - Set available Vital Product Data size
383db5679437a2b938c9127480a3923633721583a4fStephen Hemminger * @dev:	pci device struct
384db5679437a2b938c9127480a3923633721583a4fStephen Hemminger * @size:	available memory in bytes
385db5679437a2b938c9127480a3923633721583a4fStephen Hemminger *
386db5679437a2b938c9127480a3923633721583a4fStephen Hemminger * Adjust size of available VPD area.
387db5679437a2b938c9127480a3923633721583a4fStephen Hemminger */
388db5679437a2b938c9127480a3923633721583a4fStephen Hemmingerint pci_vpd_truncate(struct pci_dev *dev, size_t size)
389db5679437a2b938c9127480a3923633721583a4fStephen Hemminger{
390db5679437a2b938c9127480a3923633721583a4fStephen Hemminger	if (!dev->vpd)
391db5679437a2b938c9127480a3923633721583a4fStephen Hemminger		return -EINVAL;
392db5679437a2b938c9127480a3923633721583a4fStephen Hemminger
393db5679437a2b938c9127480a3923633721583a4fStephen Hemminger	/* limited by the access method */
394db5679437a2b938c9127480a3923633721583a4fStephen Hemminger	if (size > dev->vpd->len)
395db5679437a2b938c9127480a3923633721583a4fStephen Hemminger		return -EINVAL;
396db5679437a2b938c9127480a3923633721583a4fStephen Hemminger
397db5679437a2b938c9127480a3923633721583a4fStephen Hemminger	dev->vpd->len = size;
398d407e32efe060afa2b9a797a91376ebc65b4ce11Anton Vorontsov	if (dev->vpd->attr)
399d407e32efe060afa2b9a797a91376ebc65b4ce11Anton Vorontsov		dev->vpd->attr->size = size;
400db5679437a2b938c9127480a3923633721583a4fStephen Hemminger
401db5679437a2b938c9127480a3923633721583a4fStephen Hemminger	return 0;
402db5679437a2b938c9127480a3923633721583a4fStephen Hemminger}
403db5679437a2b938c9127480a3923633721583a4fStephen HemmingerEXPORT_SYMBOL(pci_vpd_truncate);
404db5679437a2b938c9127480a3923633721583a4fStephen Hemminger
405db5679437a2b938c9127480a3923633721583a4fStephen Hemminger/**
406fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * pci_cfg_access_lock - Lock PCI config reads/writes
407e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King * @dev:	pci device struct
408e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King *
409fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * When access is locked, any userspace reads or writes to config
410fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * space and concurrent lock requests will sleep until access is
411fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * allowed via pci_cfg_access_unlocked again.
4127ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox */
413fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszkavoid pci_cfg_access_lock(struct pci_dev *dev)
414fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka{
415fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	might_sleep();
416fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka
417fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	raw_spin_lock_irq(&pci_lock);
418fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	if (dev->block_cfg_access)
419fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka		pci_wait_cfg(dev);
420fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	dev->block_cfg_access = 1;
421fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	raw_spin_unlock_irq(&pci_lock);
422fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka}
423fb51ccbf217c1c994607b6519c7d85250928553dJan KiszkaEXPORT_SYMBOL_GPL(pci_cfg_access_lock);
424fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka
425fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka/**
426fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * pci_cfg_access_trylock - try to lock PCI config reads/writes
427fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * @dev:	pci device struct
428fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka *
429fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * Same as pci_cfg_access_lock, but will return 0 if access is
430fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * already locked, 1 otherwise. This function can be used from
431fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * atomic contexts.
432fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka */
433fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszkabool pci_cfg_access_trylock(struct pci_dev *dev)
434e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King{
435e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	unsigned long flags;
436fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	bool locked = true;
437e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
438511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irqsave(&pci_lock, flags);
439fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	if (dev->block_cfg_access)
440fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka		locked = false;
441fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	else
442fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka		dev->block_cfg_access = 1;
443511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irqrestore(&pci_lock, flags);
4447ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox
445fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	return locked;
446e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King}
447fb51ccbf217c1c994607b6519c7d85250928553dJan KiszkaEXPORT_SYMBOL_GPL(pci_cfg_access_trylock);
448e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
449e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King/**
450fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * pci_cfg_access_unlock - Unlock PCI config reads/writes
451e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King * @dev:	pci device struct
452e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King *
453fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka * This function allows PCI config accesses to resume.
4547ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox */
455fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszkavoid pci_cfg_access_unlock(struct pci_dev *dev)
456e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King{
457e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King	unsigned long flags;
458e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King
459511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_lock_irqsave(&pci_lock, flags);
4607ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox
4617ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	/* This indicates a problem in the caller, but we don't need
4627ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox	 * to kill them, unlike a double-block above. */
463fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	WARN_ON(!dev->block_cfg_access);
4647ea7e98fd8d02351c43ef4ab35d70f3aaa26c31dMatthew Wilcox
465fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	dev->block_cfg_access = 0;
466fb51ccbf217c1c994607b6519c7d85250928553dJan Kiszka	wake_up_all(&pci_cfg_wait);
467511dd98ce8cf6dc4f8f2cb32a8af31ce9f4ba4a1Thomas Gleixner	raw_spin_unlock_irqrestore(&pci_lock, flags);
468e04b0ea2e0f9c1bb0d874db4493fc7f7a623116bBrian King}
469fb51ccbf217c1c994607b6519c7d85250928553dJan KiszkaEXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
470