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: pci: enable SRIOV support.

This patch enables the standard sriov support. It allows user to
enable SRIOV (and VFs), then user could pass through accelerators
(VFs) into virtual machine or use VFs directly in host.

Signed-off-by: Zhang Yi Z <yi.z.zhang@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>
Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Link: https://lore.kernel.org/r/1564914022-3710-3-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
bdd4f307 69bb18dd

+120 -1
+36
drivers/fpga/dfl-pci.c
··· 223 223 return ret; 224 224 } 225 225 226 + static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs) 227 + { 228 + struct cci_drvdata *drvdata = pci_get_drvdata(pcidev); 229 + struct dfl_fpga_cdev *cdev = drvdata->cdev; 230 + int ret = 0; 231 + 232 + if (!num_vfs) { 233 + /* 234 + * disable SRIOV and then put released ports back to default 235 + * PF access mode. 236 + */ 237 + pci_disable_sriov(pcidev); 238 + 239 + dfl_fpga_cdev_config_ports_pf(cdev); 240 + 241 + } else { 242 + /* 243 + * before enable SRIOV, put released ports into VF access mode 244 + * first of all. 245 + */ 246 + ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs); 247 + if (ret) 248 + return ret; 249 + 250 + ret = pci_enable_sriov(pcidev, num_vfs); 251 + if (ret) 252 + dfl_fpga_cdev_config_ports_pf(cdev); 253 + } 254 + 255 + return ret; 256 + } 257 + 226 258 static void cci_pci_remove(struct pci_dev *pcidev) 227 259 { 260 + if (dev_is_pf(&pcidev->dev)) 261 + cci_pci_sriov_configure(pcidev, 0); 262 + 228 263 cci_remove_feature_devs(pcidev); 229 264 pci_disable_pcie_error_reporting(pcidev); 230 265 } ··· 269 234 .id_table = cci_pcie_id_tbl, 270 235 .probe = cci_pci_probe, 271 236 .remove = cci_pci_remove, 237 + .sriov_configure = cci_pci_sriov_configure, 272 238 }; 273 239 274 240 module_pci_driver(cci_pci_driver);
+82
drivers/fpga/dfl.c
··· 1131 1131 } 1132 1132 EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port); 1133 1133 1134 + static void config_port_access_mode(struct device *fme_dev, int port_id, 1135 + bool is_vf) 1136 + { 1137 + void __iomem *base; 1138 + u64 v; 1139 + 1140 + base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER); 1141 + 1142 + v = readq(base + FME_HDR_PORT_OFST(port_id)); 1143 + 1144 + v &= ~FME_PORT_OFST_ACC_CTRL; 1145 + v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL, 1146 + is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF); 1147 + 1148 + writeq(v, base + FME_HDR_PORT_OFST(port_id)); 1149 + } 1150 + 1151 + #define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true) 1152 + #define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false) 1153 + 1154 + /** 1155 + * dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode 1156 + * 1157 + * @cdev: parent container device. 1158 + * 1159 + * This function is needed in sriov configuration routine. It could be used to 1160 + * configure the all released ports from VF access mode to PF. 1161 + */ 1162 + void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev) 1163 + { 1164 + struct dfl_feature_platform_data *pdata; 1165 + 1166 + mutex_lock(&cdev->lock); 1167 + list_for_each_entry(pdata, &cdev->port_dev_list, node) { 1168 + if (device_is_registered(&pdata->dev->dev)) 1169 + continue; 1170 + 1171 + config_port_pf_mode(cdev->fme_dev, pdata->id); 1172 + } 1173 + mutex_unlock(&cdev->lock); 1174 + } 1175 + EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf); 1176 + 1177 + /** 1178 + * dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode 1179 + * 1180 + * @cdev: parent container device. 1181 + * @num_vfs: VF device number. 1182 + * 1183 + * This function is needed in sriov configuration routine. It could be used to 1184 + * configure the released ports from PF access mode to VF. 1185 + * 1186 + * Return: 0 on success, negative error code otherwise. 1187 + */ 1188 + int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs) 1189 + { 1190 + struct dfl_feature_platform_data *pdata; 1191 + int ret = 0; 1192 + 1193 + mutex_lock(&cdev->lock); 1194 + /* 1195 + * can't turn multiple ports into 1 VF device, only 1 port for 1 VF 1196 + * device, so if released port number doesn't match VF device number, 1197 + * then reject the request with -EINVAL error code. 1198 + */ 1199 + if (cdev->released_port_num != num_vfs) { 1200 + ret = -EINVAL; 1201 + goto done; 1202 + } 1203 + 1204 + list_for_each_entry(pdata, &cdev->port_dev_list, node) { 1205 + if (device_is_registered(&pdata->dev->dev)) 1206 + continue; 1207 + 1208 + config_port_vf_mode(cdev->fme_dev, pdata->id); 1209 + } 1210 + done: 1211 + mutex_unlock(&cdev->lock); 1212 + return ret; 1213 + } 1214 + EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf); 1215 + 1134 1216 static void __exit dfl_fpga_exit(void) 1135 1217 { 1136 1218 dfl_chardev_uinit();
+2 -1
drivers/fpga/dfl.h
··· 416 416 417 417 int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id); 418 418 int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id); 419 - 419 + void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev); 420 + int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf); 420 421 #endif /* __FPGA_DFL_H */