1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. 4 */ 5 6 /* 7 * This driver supports an interface for DCA clients and providers to meet. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/notifier.h> 12 #include <linux/device.h> 13 #include <linux/dca.h> 14 #include <linux/slab.h> 15 #include <linux/module.h> 16 17 #define DCA_VERSION "1.12.1" 18 19 MODULE_VERSION(DCA_VERSION); 20 MODULE_LICENSE("GPL"); 21 MODULE_AUTHOR("Intel Corporation"); 22 23 static DEFINE_RAW_SPINLOCK(dca_lock); 24 25 static LIST_HEAD(dca_domains); 26 27 static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); 28 29 static int dca_providers_blocked; 30 31 static struct pci_bus *dca_pci_rc_from_dev(struct device *dev) 32 { 33 struct pci_dev *pdev = to_pci_dev(dev); 34 struct pci_bus *bus = pdev->bus; 35 36 while (bus->parent) 37 bus = bus->parent; 38 39 return bus; 40 } 41 42 static struct dca_domain *dca_allocate_domain(struct pci_bus *rc) 43 { 44 struct dca_domain *domain; 45 46 domain = kzalloc(sizeof(*domain), GFP_NOWAIT); 47 if (!domain) 48 return NULL; 49 50 INIT_LIST_HEAD(&domain->dca_providers); 51 domain->pci_rc = rc; 52 53 return domain; 54 } 55 56 static void dca_free_domain(struct dca_domain *domain) 57 { 58 list_del(&domain->node); 59 kfree(domain); 60 } 61 62 static int dca_provider_ioat_ver_3_0(struct device *dev) 63 { 64 struct pci_dev *pdev = to_pci_dev(dev); 65 66 return ((pdev->vendor == PCI_VENDOR_ID_INTEL) && 67 ((pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG0) || 68 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG1) || 69 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG2) || 70 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG3) || 71 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG4) || 72 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG5) || 73 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG6) || 74 (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG7))); 75 } 76 77 static void unregister_dca_providers(void) 78 { 79 struct dca_provider *dca, *_dca; 80 struct list_head unregistered_providers; 81 struct dca_domain *domain; 82 unsigned long flags; 83 84 blocking_notifier_call_chain(&dca_provider_chain, 85 DCA_PROVIDER_REMOVE, NULL); 86 87 INIT_LIST_HEAD(&unregistered_providers); 88 89 raw_spin_lock_irqsave(&dca_lock, flags); 90 91 if (list_empty(&dca_domains)) { 92 raw_spin_unlock_irqrestore(&dca_lock, flags); 93 return; 94 } 95 96 /* at this point only one domain in the list is expected */ 97 domain = list_first_entry(&dca_domains, struct dca_domain, node); 98 99 list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) 100 list_move(&dca->node, &unregistered_providers); 101 102 dca_free_domain(domain); 103 104 raw_spin_unlock_irqrestore(&dca_lock, flags); 105 106 list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) { 107 dca_sysfs_remove_provider(dca); 108 list_del(&dca->node); 109 } 110 } 111 112 static struct dca_domain *dca_find_domain(struct pci_bus *rc) 113 { 114 struct dca_domain *domain; 115 116 list_for_each_entry(domain, &dca_domains, node) 117 if (domain->pci_rc == rc) 118 return domain; 119 120 return NULL; 121 } 122 123 static struct dca_domain *dca_get_domain(struct device *dev) 124 { 125 struct pci_bus *rc; 126 struct dca_domain *domain; 127 128 rc = dca_pci_rc_from_dev(dev); 129 domain = dca_find_domain(rc); 130 131 if (!domain) { 132 if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) 133 dca_providers_blocked = 1; 134 } 135 136 return domain; 137 } 138 139 static struct dca_provider *dca_find_provider_by_dev(struct device *dev) 140 { 141 struct dca_provider *dca; 142 struct pci_bus *rc; 143 struct dca_domain *domain; 144 145 if (dev) { 146 rc = dca_pci_rc_from_dev(dev); 147 domain = dca_find_domain(rc); 148 if (!domain) 149 return NULL; 150 } else { 151 if (!list_empty(&dca_domains)) 152 domain = list_first_entry(&dca_domains, 153 struct dca_domain, 154 node); 155 else 156 return NULL; 157 } 158 159 list_for_each_entry(dca, &domain->dca_providers, node) 160 if ((!dev) || (dca->ops->dev_managed(dca, dev))) 161 return dca; 162 163 return NULL; 164 } 165 166 /** 167 * dca_add_requester - add a dca client to the list 168 * @dev - the device that wants dca service 169 */ 170 int dca_add_requester(struct device *dev) 171 { 172 struct dca_provider *dca; 173 int err, slot = -ENODEV; 174 unsigned long flags; 175 struct pci_bus *pci_rc; 176 struct dca_domain *domain; 177 178 if (!dev) 179 return -EFAULT; 180 181 raw_spin_lock_irqsave(&dca_lock, flags); 182 183 /* check if the requester has not been added already */ 184 dca = dca_find_provider_by_dev(dev); 185 if (dca) { 186 raw_spin_unlock_irqrestore(&dca_lock, flags); 187 return -EEXIST; 188 } 189 190 pci_rc = dca_pci_rc_from_dev(dev); 191 domain = dca_find_domain(pci_rc); 192 if (!domain) { 193 raw_spin_unlock_irqrestore(&dca_lock, flags); 194 return -ENODEV; 195 } 196 197 list_for_each_entry(dca, &domain->dca_providers, node) { 198 slot = dca->ops->add_requester(dca, dev); 199 if (slot >= 0) 200 break; 201 } 202 203 raw_spin_unlock_irqrestore(&dca_lock, flags); 204 205 if (slot < 0) 206 return slot; 207 208 err = dca_sysfs_add_req(dca, dev, slot); 209 if (err) { 210 raw_spin_lock_irqsave(&dca_lock, flags); 211 if (dca == dca_find_provider_by_dev(dev)) 212 dca->ops->remove_requester(dca, dev); 213 raw_spin_unlock_irqrestore(&dca_lock, flags); 214 return err; 215 } 216 217 return 0; 218 } 219 EXPORT_SYMBOL_GPL(dca_add_requester); 220 221 /** 222 * dca_remove_requester - remove a dca client from the list 223 * @dev - the device that wants dca service 224 */ 225 int dca_remove_requester(struct device *dev) 226 { 227 struct dca_provider *dca; 228 int slot; 229 unsigned long flags; 230 231 if (!dev) 232 return -EFAULT; 233 234 raw_spin_lock_irqsave(&dca_lock, flags); 235 dca = dca_find_provider_by_dev(dev); 236 if (!dca) { 237 raw_spin_unlock_irqrestore(&dca_lock, flags); 238 return -ENODEV; 239 } 240 slot = dca->ops->remove_requester(dca, dev); 241 raw_spin_unlock_irqrestore(&dca_lock, flags); 242 243 if (slot < 0) 244 return slot; 245 246 dca_sysfs_remove_req(dca, slot); 247 248 return 0; 249 } 250 EXPORT_SYMBOL_GPL(dca_remove_requester); 251 252 /** 253 * dca_common_get_tag - return the dca tag (serves both new and old api) 254 * @dev - the device that wants dca service 255 * @cpu - the cpuid as returned by get_cpu() 256 */ 257 static u8 dca_common_get_tag(struct device *dev, int cpu) 258 { 259 struct dca_provider *dca; 260 u8 tag; 261 unsigned long flags; 262 263 raw_spin_lock_irqsave(&dca_lock, flags); 264 265 dca = dca_find_provider_by_dev(dev); 266 if (!dca) { 267 raw_spin_unlock_irqrestore(&dca_lock, flags); 268 return -ENODEV; 269 } 270 tag = dca->ops->get_tag(dca, dev, cpu); 271 272 raw_spin_unlock_irqrestore(&dca_lock, flags); 273 return tag; 274 } 275 276 /** 277 * dca3_get_tag - return the dca tag to the requester device 278 * for the given cpu (new api) 279 * @dev - the device that wants dca service 280 * @cpu - the cpuid as returned by get_cpu() 281 */ 282 u8 dca3_get_tag(struct device *dev, int cpu) 283 { 284 if (!dev) 285 return -EFAULT; 286 287 return dca_common_get_tag(dev, cpu); 288 } 289 EXPORT_SYMBOL_GPL(dca3_get_tag); 290 291 /** 292 * dca_get_tag - return the dca tag for the given cpu (old api) 293 * @cpu - the cpuid as returned by get_cpu() 294 */ 295 u8 dca_get_tag(int cpu) 296 { 297 return dca_common_get_tag(NULL, cpu); 298 } 299 EXPORT_SYMBOL_GPL(dca_get_tag); 300 301 /** 302 * alloc_dca_provider - get data struct for describing a dca provider 303 * @ops - pointer to struct of dca operation function pointers 304 * @priv_size - size of extra mem to be added for provider's needs 305 */ 306 struct dca_provider *alloc_dca_provider(const struct dca_ops *ops, 307 int priv_size) 308 { 309 struct dca_provider *dca; 310 int alloc_size; 311 312 alloc_size = (sizeof(*dca) + priv_size); 313 dca = kzalloc(alloc_size, GFP_KERNEL); 314 if (!dca) 315 return NULL; 316 dca->ops = ops; 317 318 return dca; 319 } 320 EXPORT_SYMBOL_GPL(alloc_dca_provider); 321 322 /** 323 * free_dca_provider - release the dca provider data struct 324 * @ops - pointer to struct of dca operation function pointers 325 * @priv_size - size of extra mem to be added for provider's needs 326 */ 327 void free_dca_provider(struct dca_provider *dca) 328 { 329 kfree(dca); 330 } 331 EXPORT_SYMBOL_GPL(free_dca_provider); 332 333 /** 334 * register_dca_provider - register a dca provider 335 * @dca - struct created by alloc_dca_provider() 336 * @dev - device providing dca services 337 */ 338 int register_dca_provider(struct dca_provider *dca, struct device *dev) 339 { 340 int err; 341 unsigned long flags; 342 struct dca_domain *domain, *newdomain = NULL; 343 344 raw_spin_lock_irqsave(&dca_lock, flags); 345 if (dca_providers_blocked) { 346 raw_spin_unlock_irqrestore(&dca_lock, flags); 347 return -ENODEV; 348 } 349 raw_spin_unlock_irqrestore(&dca_lock, flags); 350 351 err = dca_sysfs_add_provider(dca, dev); 352 if (err) 353 return err; 354 355 raw_spin_lock_irqsave(&dca_lock, flags); 356 domain = dca_get_domain(dev); 357 if (!domain) { 358 struct pci_bus *rc; 359 360 if (dca_providers_blocked) { 361 raw_spin_unlock_irqrestore(&dca_lock, flags); 362 dca_sysfs_remove_provider(dca); 363 unregister_dca_providers(); 364 return -ENODEV; 365 } 366 367 raw_spin_unlock_irqrestore(&dca_lock, flags); 368 rc = dca_pci_rc_from_dev(dev); 369 newdomain = dca_allocate_domain(rc); 370 if (!newdomain) 371 return -ENODEV; 372 raw_spin_lock_irqsave(&dca_lock, flags); 373 /* Recheck, we might have raced after dropping the lock */ 374 domain = dca_get_domain(dev); 375 if (!domain) { 376 domain = newdomain; 377 newdomain = NULL; 378 list_add(&domain->node, &dca_domains); 379 } 380 } 381 list_add(&dca->node, &domain->dca_providers); 382 raw_spin_unlock_irqrestore(&dca_lock, flags); 383 384 blocking_notifier_call_chain(&dca_provider_chain, 385 DCA_PROVIDER_ADD, NULL); 386 kfree(newdomain); 387 return 0; 388 } 389 EXPORT_SYMBOL_GPL(register_dca_provider); 390 391 /** 392 * unregister_dca_provider - remove a dca provider 393 * @dca - struct created by alloc_dca_provider() 394 */ 395 void unregister_dca_provider(struct dca_provider *dca, struct device *dev) 396 { 397 unsigned long flags; 398 struct pci_bus *pci_rc; 399 struct dca_domain *domain; 400 401 blocking_notifier_call_chain(&dca_provider_chain, 402 DCA_PROVIDER_REMOVE, NULL); 403 404 raw_spin_lock_irqsave(&dca_lock, flags); 405 406 if (list_empty(&dca_domains)) { 407 raw_spin_unlock_irqrestore(&dca_lock, flags); 408 return; 409 } 410 411 list_del(&dca->node); 412 413 pci_rc = dca_pci_rc_from_dev(dev); 414 domain = dca_find_domain(pci_rc); 415 if (list_empty(&domain->dca_providers)) 416 dca_free_domain(domain); 417 418 raw_spin_unlock_irqrestore(&dca_lock, flags); 419 420 dca_sysfs_remove_provider(dca); 421 } 422 EXPORT_SYMBOL_GPL(unregister_dca_provider); 423 424 /** 425 * dca_register_notify - register a client's notifier callback 426 */ 427 void dca_register_notify(struct notifier_block *nb) 428 { 429 blocking_notifier_chain_register(&dca_provider_chain, nb); 430 } 431 EXPORT_SYMBOL_GPL(dca_register_notify); 432 433 /** 434 * dca_unregister_notify - remove a client's notifier callback 435 */ 436 void dca_unregister_notify(struct notifier_block *nb) 437 { 438 blocking_notifier_chain_unregister(&dca_provider_chain, nb); 439 } 440 EXPORT_SYMBOL_GPL(dca_unregister_notify); 441 442 static int __init dca_init(void) 443 { 444 pr_info("dca service started, version %s\n", DCA_VERSION); 445 return dca_sysfs_init(); 446 } 447 448 static void __exit dca_exit(void) 449 { 450 dca_sysfs_exit(); 451 } 452 453 arch_initcall(dca_init); 454 module_exit(dca_exit); 455 456