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.

net: pse-pd: Add support for PSE power domains

Introduce PSE power domain support as groundwork for upcoming port
priority features. Multiple PSE PIs can now be grouped under a single
PSE power domain, enabling future enhancements like defining available
power budgets, port priority modes, and disconnection policies. This
setup will allow the system to assess whether activating a port would
exceed the available power budget, preventing over-budget states
proactively.

Signed-off-by: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-4-78a1a645e2ee@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kory Maincent (Dent Project) and committed by
Jakub Kicinski
50f8b341 f5e7aeca

+142
+140
drivers/net/pse-pd/pse_core.c
··· 16 16 #include <linux/rtnetlink.h> 17 17 #include <net/net_trackers.h> 18 18 19 + #define PSE_PW_D_LIMIT INT_MAX 20 + 19 21 static DEFINE_MUTEX(pse_list_mutex); 20 22 static LIST_HEAD(pse_controller_list); 23 + static DEFINE_XARRAY_ALLOC(pse_pw_d_map); 24 + static DEFINE_MUTEX(pse_pw_d_mutex); 21 25 22 26 /** 23 27 * struct pse_control - a PSE control ··· 40 36 unsigned int id; 41 37 struct kref refcnt; 42 38 struct phy_device *attached_phydev; 39 + }; 40 + 41 + /** 42 + * struct pse_power_domain - a PSE power domain 43 + * @id: ID of the power domain 44 + * @supply: Power supply the Power Domain 45 + * @refcnt: Number of gets of this pse_power_domain 46 + */ 47 + struct pse_power_domain { 48 + int id; 49 + struct regulator *supply; 50 + struct kref refcnt; 43 51 }; 44 52 45 53 static int of_load_single_pse_pi_pairset(struct device_node *node, ··· 501 485 return 0; 502 486 } 503 487 488 + static void __pse_pw_d_release(struct kref *kref) 489 + { 490 + struct pse_power_domain *pw_d = container_of(kref, 491 + struct pse_power_domain, 492 + refcnt); 493 + 494 + regulator_put(pw_d->supply); 495 + xa_erase(&pse_pw_d_map, pw_d->id); 496 + mutex_unlock(&pse_pw_d_mutex); 497 + } 498 + 499 + /** 500 + * pse_flush_pw_ds - flush all PSE power domains of a PSE 501 + * @pcdev: a pointer to the initialized PSE controller device 502 + */ 503 + static void pse_flush_pw_ds(struct pse_controller_dev *pcdev) 504 + { 505 + struct pse_power_domain *pw_d; 506 + int i; 507 + 508 + for (i = 0; i < pcdev->nr_lines; i++) { 509 + if (!pcdev->pi[i].pw_d) 510 + continue; 511 + 512 + pw_d = xa_load(&pse_pw_d_map, pcdev->pi[i].pw_d->id); 513 + if (!pw_d) 514 + continue; 515 + 516 + kref_put_mutex(&pw_d->refcnt, __pse_pw_d_release, 517 + &pse_pw_d_mutex); 518 + } 519 + } 520 + 521 + /** 522 + * devm_pse_alloc_pw_d - allocate a new PSE power domain for a device 523 + * @dev: device that is registering this PSE power domain 524 + * 525 + * Return: Pointer to the newly allocated PSE power domain or error pointers 526 + */ 527 + static struct pse_power_domain *devm_pse_alloc_pw_d(struct device *dev) 528 + { 529 + struct pse_power_domain *pw_d; 530 + int index, ret; 531 + 532 + pw_d = devm_kzalloc(dev, sizeof(*pw_d), GFP_KERNEL); 533 + if (!pw_d) 534 + return ERR_PTR(-ENOMEM); 535 + 536 + ret = xa_alloc(&pse_pw_d_map, &index, pw_d, XA_LIMIT(1, PSE_PW_D_LIMIT), 537 + GFP_KERNEL); 538 + if (ret) 539 + return ERR_PTR(ret); 540 + 541 + kref_init(&pw_d->refcnt); 542 + pw_d->id = index; 543 + return pw_d; 544 + } 545 + 546 + /** 547 + * pse_register_pw_ds - register the PSE power domains for a PSE 548 + * @pcdev: a pointer to the PSE controller device 549 + * 550 + * Return: 0 on success and failure value on error 551 + */ 552 + static int pse_register_pw_ds(struct pse_controller_dev *pcdev) 553 + { 554 + int i, ret = 0; 555 + 556 + mutex_lock(&pse_pw_d_mutex); 557 + for (i = 0; i < pcdev->nr_lines; i++) { 558 + struct regulator_dev *rdev = pcdev->pi[i].rdev; 559 + struct pse_power_domain *pw_d; 560 + struct regulator *supply; 561 + bool present = false; 562 + unsigned long index; 563 + 564 + /* No regulator or regulator parent supply registered. 565 + * We need a regulator parent to register a PSE power domain 566 + */ 567 + if (!rdev || !rdev->supply) 568 + continue; 569 + 570 + xa_for_each(&pse_pw_d_map, index, pw_d) { 571 + /* Power supply already registered as a PSE power 572 + * domain. 573 + */ 574 + if (regulator_is_equal(pw_d->supply, rdev->supply)) { 575 + present = true; 576 + pcdev->pi[i].pw_d = pw_d; 577 + break; 578 + } 579 + } 580 + if (present) { 581 + kref_get(&pw_d->refcnt); 582 + continue; 583 + } 584 + 585 + pw_d = devm_pse_alloc_pw_d(pcdev->dev); 586 + if (IS_ERR(pw_d)) { 587 + ret = PTR_ERR(pw_d); 588 + goto out; 589 + } 590 + 591 + supply = regulator_get(&rdev->dev, rdev->supply_name); 592 + if (IS_ERR(supply)) { 593 + xa_erase(&pse_pw_d_map, pw_d->id); 594 + ret = PTR_ERR(supply); 595 + goto out; 596 + } 597 + 598 + pw_d->supply = supply; 599 + pcdev->pi[i].pw_d = pw_d; 600 + } 601 + 602 + out: 603 + mutex_unlock(&pse_pw_d_mutex); 604 + return ret; 605 + } 606 + 504 607 /** 505 608 * pse_controller_register - register a PSE controller device 506 609 * @pcdev: a pointer to the initialized PSE controller device ··· 679 544 return ret; 680 545 } 681 546 547 + ret = pse_register_pw_ds(pcdev); 548 + if (ret) 549 + return ret; 550 + 682 551 mutex_lock(&pse_list_mutex); 683 552 list_add(&pcdev->list, &pse_controller_list); 684 553 mutex_unlock(&pse_list_mutex); ··· 697 558 */ 698 559 void pse_controller_unregister(struct pse_controller_dev *pcdev) 699 560 { 561 + pse_flush_pw_ds(pcdev); 700 562 pse_release_pis(pcdev); 701 563 mutex_lock(&pse_list_mutex); 702 564 list_del(&pcdev->list);
+2
include/linux/pse-pd/pse.h
··· 222 222 * @np: device node pointer of the PSE PI node 223 223 * @rdev: regulator represented by the PSE PI 224 224 * @admin_state_enabled: PI enabled state 225 + * @pw_d: Power domain of the PSE PI 225 226 */ 226 227 struct pse_pi { 227 228 struct pse_pi_pairset pairset[2]; 228 229 struct device_node *np; 229 230 struct regulator_dev *rdev; 230 231 bool admin_state_enabled; 232 + struct pse_power_domain *pw_d; 231 233 }; 232 234 233 235 /**