Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fpga: dfl: afu: add AFU state related sysfs interfaces

This patch introduces more sysfs interfaces for Accelerated
Function Unit (AFU). These interfaces allow users to read
current AFU Power State (APx), read / clear AFU Power (APx)
events which are sticky to identify transient APx state,
and manage AFU's LTR (latency tolerance reporting).

Signed-off-by: Ananda Ravuri <ananda.ravuri@intel.com>
Signed-off-by: Xu Yilun <yilun.xu@intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
Acked-by: Alan Tull <atull@kernel.org>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Link: https://lore.kernel.org/r/1564914022-3710-4-git-send-email-hao.wu@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Wu Hao and committed by
Greg Kroah-Hartman
d2ad5ac1 bdd4f307

+180
+32
Documentation/ABI/testing/sysfs-platform-dfl-port
··· 14 14 Accelerator Function Unit (AFU) for different functions. It 15 15 returns uuid which could be used to identify which PR bitstream 16 16 is programmed in this AFU. 17 + 18 + What: /sys/bus/platform/devices/dfl-port.0/power_state 19 + Date: August 2019 20 + KernelVersion: 5.4 21 + Contact: Wu Hao <hao.wu@intel.com> 22 + Description: Read-only. It reports the APx (AFU Power) state, different APx 23 + means different throttling level. When reading this file, it 24 + returns "0" - Normal / "1" - AP1 / "2" - AP2 / "6" - AP6. 25 + 26 + What: /sys/bus/platform/devices/dfl-port.0/ap1_event 27 + Date: August 2019 28 + KernelVersion: 5.4 29 + Contact: Wu Hao <hao.wu@intel.com> 30 + Description: Read-write. Read this file for AP1 (AFU Power State 1) event. 31 + It's used to indicate transient AP1 state. Write 1 to this 32 + file to clear AP1 event. 33 + 34 + What: /sys/bus/platform/devices/dfl-port.0/ap2_event 35 + Date: August 2019 36 + KernelVersion: 5.4 37 + Contact: Wu Hao <hao.wu@intel.com> 38 + Description: Read-write. Read this file for AP2 (AFU Power State 2) event. 39 + It's used to indicate transient AP2 state. Write 1 to this 40 + file to clear AP2 event. 41 + 42 + What: /sys/bus/platform/devices/dfl-port.0/ltr 43 + Date: August 2019 44 + KernelVersion: 5.4 45 + Contact: Wu Hao <hao.wu@intel.com> 46 + Description: Read-write. Read or set AFU latency tolerance reporting value. 47 + Set ltr to 1 if the AFU can tolerate latency >= 40us or set it 48 + to 0 if it is latency sensitive.
+137
drivers/fpga/dfl-afu-main.c
··· 141 141 } 142 142 static DEVICE_ATTR_RO(id); 143 143 144 + static ssize_t 145 + ltr_show(struct device *dev, struct device_attribute *attr, char *buf) 146 + { 147 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 148 + void __iomem *base; 149 + u64 v; 150 + 151 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 152 + 153 + mutex_lock(&pdata->lock); 154 + v = readq(base + PORT_HDR_CTRL); 155 + mutex_unlock(&pdata->lock); 156 + 157 + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v)); 158 + } 159 + 160 + static ssize_t 161 + ltr_store(struct device *dev, struct device_attribute *attr, 162 + const char *buf, size_t count) 163 + { 164 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 165 + void __iomem *base; 166 + bool ltr; 167 + u64 v; 168 + 169 + if (kstrtobool(buf, &ltr)) 170 + return -EINVAL; 171 + 172 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 173 + 174 + mutex_lock(&pdata->lock); 175 + v = readq(base + PORT_HDR_CTRL); 176 + v &= ~PORT_CTRL_LATENCY; 177 + v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0); 178 + writeq(v, base + PORT_HDR_CTRL); 179 + mutex_unlock(&pdata->lock); 180 + 181 + return count; 182 + } 183 + static DEVICE_ATTR_RW(ltr); 184 + 185 + static ssize_t 186 + ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf) 187 + { 188 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 189 + void __iomem *base; 190 + u64 v; 191 + 192 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 193 + 194 + mutex_lock(&pdata->lock); 195 + v = readq(base + PORT_HDR_STS); 196 + mutex_unlock(&pdata->lock); 197 + 198 + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v)); 199 + } 200 + 201 + static ssize_t 202 + ap1_event_store(struct device *dev, struct device_attribute *attr, 203 + const char *buf, size_t count) 204 + { 205 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 206 + void __iomem *base; 207 + bool clear; 208 + 209 + if (kstrtobool(buf, &clear) || !clear) 210 + return -EINVAL; 211 + 212 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 213 + 214 + mutex_lock(&pdata->lock); 215 + writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS); 216 + mutex_unlock(&pdata->lock); 217 + 218 + return count; 219 + } 220 + static DEVICE_ATTR_RW(ap1_event); 221 + 222 + static ssize_t 223 + ap2_event_show(struct device *dev, struct device_attribute *attr, 224 + char *buf) 225 + { 226 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 227 + void __iomem *base; 228 + u64 v; 229 + 230 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 231 + 232 + mutex_lock(&pdata->lock); 233 + v = readq(base + PORT_HDR_STS); 234 + mutex_unlock(&pdata->lock); 235 + 236 + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v)); 237 + } 238 + 239 + static ssize_t 240 + ap2_event_store(struct device *dev, struct device_attribute *attr, 241 + const char *buf, size_t count) 242 + { 243 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 244 + void __iomem *base; 245 + bool clear; 246 + 247 + if (kstrtobool(buf, &clear) || !clear) 248 + return -EINVAL; 249 + 250 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 251 + 252 + mutex_lock(&pdata->lock); 253 + writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS); 254 + mutex_unlock(&pdata->lock); 255 + 256 + return count; 257 + } 258 + static DEVICE_ATTR_RW(ap2_event); 259 + 260 + static ssize_t 261 + power_state_show(struct device *dev, struct device_attribute *attr, char *buf) 262 + { 263 + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); 264 + void __iomem *base; 265 + u64 v; 266 + 267 + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); 268 + 269 + mutex_lock(&pdata->lock); 270 + v = readq(base + PORT_HDR_STS); 271 + mutex_unlock(&pdata->lock); 272 + 273 + return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v)); 274 + } 275 + static DEVICE_ATTR_RO(power_state); 276 + 144 277 static struct attribute *port_hdr_attrs[] = { 145 278 &dev_attr_id.attr, 279 + &dev_attr_ltr.attr, 280 + &dev_attr_ap1_event.attr, 281 + &dev_attr_ap2_event.attr, 282 + &dev_attr_power_state.attr, 146 283 NULL, 147 284 }; 148 285 ATTRIBUTE_GROUPS(port_hdr);
+11
drivers/fpga/dfl.h
··· 119 119 #define PORT_HDR_NEXT_AFU NEXT_AFU 120 120 #define PORT_HDR_CAP 0x30 121 121 #define PORT_HDR_CTRL 0x38 122 + #define PORT_HDR_STS 0x40 122 123 123 124 /* Port Capability Register Bitfield */ 124 125 #define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */ ··· 131 130 /* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/ 132 131 #define PORT_CTRL_LATENCY BIT_ULL(2) 133 132 #define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */ 133 + 134 + /* Port Status Register Bitfield */ 135 + #define PORT_STS_AP2_EVT BIT_ULL(13) /* AP2 event detected */ 136 + #define PORT_STS_AP1_EVT BIT_ULL(12) /* AP1 event detected */ 137 + #define PORT_STS_PWR_STATE GENMASK_ULL(11, 8) /* AFU power states */ 138 + #define PORT_STS_PWR_STATE_NORM 0 139 + #define PORT_STS_PWR_STATE_AP1 1 /* 50% throttling */ 140 + #define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */ 141 + #define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */ 142 + 134 143 /** 135 144 * struct dfl_fpga_port_ops - port ops 136 145 *