aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fpga/dfl.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fpga/dfl.h')
-rw-r--r--drivers/fpga/dfl.h126
1 files changed, 99 insertions, 27 deletions
diff --git a/drivers/fpga/dfl.h b/drivers/fpga/dfl.h
index 9f0e656de720..06cfcd5e84bb 100644
--- a/drivers/fpga/dfl.h
+++ b/drivers/fpga/dfl.h
@@ -17,9 +17,12 @@
#include <linux/bitfield.h>
#include <linux/cdev.h>
#include <linux/delay.h>
+#include <linux/eventfd.h>
#include <linux/fs.h>
+#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/uuid.h>
@@ -86,6 +89,7 @@
#define FME_HDR_NEXT_AFU NEXT_AFU
#define FME_HDR_CAP 0x30
#define FME_HDR_PORT_OFST(n) (0x38 + ((n) * 0x8))
+#define FME_PORT_OFST_BAR_SKIP 7
#define FME_HDR_BITSTREAM_ID 0x60
#define FME_HDR_BITSTREAM_MD 0x68
@@ -112,6 +116,13 @@
#define FME_PORT_OFST_ACC_VF 1
#define FME_PORT_OFST_IMP BIT_ULL(60)
+/* FME Error Capability Register */
+#define FME_ERROR_CAP 0x70
+
+/* FME Error Capability Register Bitfield */
+#define FME_ERROR_CAP_SUPP_INT BIT_ULL(0) /* Interrupt Support */
+#define FME_ERROR_CAP_INT_VECT GENMASK_ULL(12, 1) /* Interrupt vector */
+
/* PORT Header Register Set */
#define PORT_HDR_DFH DFH
#define PORT_HDR_GUID_L GUID_L
@@ -145,6 +156,20 @@
#define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */
#define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */
+/* Port Error Capability Register */
+#define PORT_ERROR_CAP 0x38
+
+/* Port Error Capability Register Bitfield */
+#define PORT_ERROR_CAP_SUPP_INT BIT_ULL(0) /* Interrupt Support */
+#define PORT_ERROR_CAP_INT_VECT GENMASK_ULL(12, 1) /* Interrupt vector */
+
+/* Port Uint Capability Register */
+#define PORT_UINT_CAP 0x8
+
+/* Port Uint Capability Register Bitfield */
+#define PORT_UINT_CAP_INT_NUM GENMASK_ULL(11, 0) /* Interrupts num */
+#define PORT_UINT_CAP_FST_VECT GENMASK_ULL(23, 12) /* First Vector */
+
/**
* struct dfl_fpga_port_ops - port ops
*
@@ -174,7 +199,7 @@ int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id);
* @id: unique dfl private feature id.
*/
struct dfl_feature_id {
- u64 id;
+ u16 id;
};
/**
@@ -189,24 +214,46 @@ struct dfl_feature_driver {
};
/**
+ * struct dfl_feature_irq_ctx - dfl private feature interrupt context
+ *
+ * @irq: Linux IRQ number of this interrupt.
+ * @trigger: eventfd context to signal when interrupt happens.
+ * @name: irq name needed when requesting irq.
+ */
+struct dfl_feature_irq_ctx {
+ int irq;
+ struct eventfd_ctx *trigger;
+ char *name;
+};
+
+/**
* struct dfl_feature - sub feature of the feature devices
*
+ * @dev: ptr to pdev of the feature device which has the sub feature.
* @id: sub feature id.
* @resource_index: each sub feature has one mmio resource for its registers.
* this index is used to find its mmio resource from the
- * feature dev (platform device)'s reources.
+ * feature dev (platform device)'s resources.
* @ioaddr: mapped mmio resource address.
+ * @irq_ctx: interrupt context list.
+ * @nr_irqs: number of interrupt contexts.
* @ops: ops of this sub feature.
+ * @ddev: ptr to the dfl device of this sub feature.
+ * @priv: priv data of this feature.
*/
struct dfl_feature {
- u64 id;
+ struct platform_device *dev;
+ u16 id;
+ u8 revision;
int resource_index;
void __iomem *ioaddr;
+ struct dfl_feature_irq_ctx *irq_ctx;
+ unsigned int nr_irqs;
const struct dfl_feature_ops *ops;
+ struct dfl_device *ddev;
+ void *priv;
};
-#define DEV_STATUS_IN_USE 0
-
#define FEATURE_DEV_ID_UNUSED (-1)
/**
@@ -219,8 +266,9 @@ struct dfl_feature {
* @dfl_cdev: ptr to container device.
* @id: id used for this feature device.
* @disable_count: count for port disable.
+ * @excl_open: set on feature device exclusive open.
+ * @open_count: count for feature device open.
* @num: number for sub features.
- * @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
* @private: ptr to feature dev private data.
* @features: sub features of this feature dev.
*/
@@ -232,26 +280,46 @@ struct dfl_feature_platform_data {
struct dfl_fpga_cdev *dfl_cdev;
int id;
unsigned int disable_count;
- unsigned long dev_status;
+ bool excl_open;
+ int open_count;
void *private;
int num;
- struct dfl_feature features[0];
+ struct dfl_feature features[];
};
static inline
-int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata)
+int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata,
+ bool excl)
{
- /* Test and set IN_USE flags to ensure file is exclusively used */
- if (test_and_set_bit_lock(DEV_STATUS_IN_USE, &pdata->dev_status))
+ if (pdata->excl_open)
return -EBUSY;
+ if (excl) {
+ if (pdata->open_count)
+ return -EBUSY;
+
+ pdata->excl_open = true;
+ }
+ pdata->open_count++;
+
return 0;
}
static inline
void dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata)
{
- clear_bit_unlock(DEV_STATUS_IN_USE, &pdata->dev_status);
+ pdata->excl_open = false;
+
+ if (WARN_ON(pdata->open_count <= 0))
+ return;
+
+ pdata->open_count--;
+}
+
+static inline
+int dfl_feature_dev_use_count(struct dfl_feature_platform_data *pdata)
+{
+ return pdata->open_count;
}
static inline
@@ -278,12 +346,6 @@ struct dfl_feature_ops {
#define DFL_FPGA_FEATURE_DEV_FME "dfl-fme"
#define DFL_FPGA_FEATURE_DEV_PORT "dfl-port"
-static inline int dfl_feature_platform_data_size(const int num)
-{
- return sizeof(struct dfl_feature_platform_data) +
- num * sizeof(struct dfl_feature);
-}
-
void dfl_fpga_dev_feature_uinit(struct platform_device *pdev);
int dfl_fpga_dev_feature_init(struct platform_device *pdev,
struct dfl_feature_driver *feature_drvs);
@@ -308,7 +370,7 @@ struct platform_device *dfl_fpga_inode_to_feature_dev(struct inode *inode)
(feature) < (pdata)->features + (pdata)->num; (feature)++)
static inline
-struct dfl_feature *dfl_get_feature_by_id(struct device *dev, u64 id)
+struct dfl_feature *dfl_get_feature_by_id(struct device *dev, u16 id)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct dfl_feature *feature;
@@ -321,7 +383,7 @@ struct dfl_feature *dfl_get_feature_by_id(struct device *dev, u64 id)
}
static inline
-void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u64 id)
+void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u16 id)
{
struct dfl_feature *feature = dfl_get_feature_by_id(dev, id);
@@ -332,7 +394,7 @@ void __iomem *dfl_get_feature_ioaddr_by_id(struct device *dev, u64 id)
return NULL;
}
-static inline bool is_dfl_feature_present(struct device *dev, u64 id)
+static inline bool is_dfl_feature_present(struct device *dev, u16 id)
{
return !!dfl_get_feature_ioaddr_by_id(dev, id);
}
@@ -369,10 +431,14 @@ static inline u8 dfl_feature_revision(void __iomem *base)
*
* @dev: parent device.
* @dfls: list of device feature lists.
+ * @nr_irqs: number of irqs for all feature devices.
+ * @irq_table: Linux IRQ numbers for all irqs, indexed by hw irq numbers.
*/
struct dfl_fpga_enum_info {
struct device *dev;
struct list_head dfls;
+ unsigned int nr_irqs;
+ int *irq_table;
};
/**
@@ -380,22 +446,19 @@ struct dfl_fpga_enum_info {
*
* @start: base address of this device feature list.
* @len: size of this device feature list.
- * @ioaddr: mapped base address of this device feature list.
* @node: node in list of device feature lists.
*/
struct dfl_fpga_enum_dfl {
resource_size_t start;
resource_size_t len;
-
- void __iomem *ioaddr;
-
struct list_head node;
};
struct dfl_fpga_enum_info *dfl_fpga_enum_info_alloc(struct device *dev);
int dfl_fpga_enum_info_add_dfl(struct dfl_fpga_enum_info *info,
- resource_size_t start, resource_size_t len,
- void __iomem *ioaddr);
+ resource_size_t start, resource_size_t len);
+int dfl_fpga_enum_info_add_irq(struct dfl_fpga_enum_info *info,
+ unsigned int nr_irqs, int *irq_table);
void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info);
/**
@@ -447,4 +510,13 @@ int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id);
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id);
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev);
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf);
+int dfl_fpga_set_irq_triggers(struct dfl_feature *feature, unsigned int start,
+ unsigned int count, int32_t *fds);
+long dfl_feature_ioctl_get_num_irqs(struct platform_device *pdev,
+ struct dfl_feature *feature,
+ unsigned long arg);
+long dfl_feature_ioctl_set_irq(struct platform_device *pdev,
+ struct dfl_feature *feature,
+ unsigned long arg);
+
#endif /* __FPGA_DFL_H */