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.

Merge branch 'add-support-for-pse-budget-evaluation-strategy'

Kory Maincent says:

====================
Add support for PSE budget evaluation strategy

This series brings support for budget evaluation strategy in the PSE
subsystem. PSE controllers can set priorities to decide which ports should
be turned off in case of special events like over-current.

This patch series adds support for two budget evaluation strategy.
1. Static Method:

This method involves distributing power based on PD classification.
It’s straightforward and stable, the PSE core keeping track of the
budget and subtracting the power requested by each PD’s class.

Advantages: Every PD gets its promised power at any time, which
guarantees reliability.

Disadvantages: PD classification steps are large, meaning devices
request much more power than they actually need. As a result, the power
supply may only operate at, say, 50% capacity, which is inefficient and
wastes money.

2. Dynamic Method:

To address the inefficiencies of the static method, vendors like
Microchip have introduced dynamic power budgeting, as seen in the
PD692x0 firmware. This method monitors the current consumption per port
and subtracts it from the available power budget. When the budget is
exceeded, lower-priority ports are shut down.

Advantages: This method optimizes resource utilization, saving costs.

Disadvantages: Low-priority devices may experience instability.

The UAPI allows adding support for software port priority mode managed from
userspace later if needed.

Patches 1-2: Add support for interrupt event report in PSE core, ethtool
and ethtool specs.
Patch 3: Adds support for interrupt and event report in TPS23881 driver.
Patches 4,5: Add support for PSE power domain in PSE core and ethtool.
Patches 6-8: Add support for budget evaluation strategy in PSE core,
ethtool and ethtool specs.
Patches 9-11: Add support for port priority and power supplies in PD692x0
drivers.
Patches 12,13: Add support for port priority in TPS23881 drivers.
====================

Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-0-78a1a645e2ee@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+2037 -53
+19 -3
Documentation/devicetree/bindings/net/pse-pd/microchip,pd692x0.yaml
··· 22 22 reg: 23 23 maxItems: 1 24 24 25 + vdd-supply: 26 + description: Regulator that provides 3.3V VDD power supply. 27 + 28 + vdda-supply: 29 + description: Regulator that provides 3.3V VDDA power supply. 30 + 25 31 managers: 26 32 type: object 27 33 additionalProperties: false ··· 74 68 "#size-cells": 75 69 const: 0 76 70 71 + vmain-supply: 72 + description: Regulator that provides 44-57V VMAIN power supply. 73 + 74 + vaux5-supply: 75 + description: Regulator that provides 5V VAUX5 power supply. 76 + 77 + vaux3p3-supply: 78 + description: Regulator that provides 3.3V VAUX3P3 power supply. 79 + 77 80 patternProperties: 78 81 '^port@[0-7]$': 79 82 type: object ··· 121 106 #address-cells = <1>; 122 107 #size-cells = <0>; 123 108 124 - manager@0 { 109 + manager0: manager@0 { 125 110 reg = <0>; 126 111 #address-cells = <1>; 127 112 #size-cells = <0>; 113 + vmain-supply = <&pse1_supply>; 128 114 129 115 phys0: port@0 { 130 116 reg = <0>; ··· 177 161 pairset-names = "alternative-a", "alternative-b"; 178 162 pairsets = <&phys0>, <&phys1>; 179 163 polarity-supported = "MDI", "S"; 180 - vpwr-supply = <&vpwr1>; 164 + vpwr-supply = <&manager0>; 181 165 }; 182 166 pse_pi1: pse-pi@1 { 183 167 reg = <1>; ··· 185 169 pairset-names = "alternative-a"; 186 170 pairsets = <&phys2>; 187 171 polarity-supported = "MDI"; 188 - vpwr-supply = <&vpwr2>; 172 + vpwr-supply = <&manager0>; 189 173 }; 190 174 }; 191 175 };
+8
Documentation/devicetree/bindings/net/pse-pd/ti,tps23881.yaml
··· 20 20 reg: 21 21 maxItems: 1 22 22 23 + interrupts: 24 + maxItems: 1 25 + 23 26 '#pse-cells': 24 27 const: 1 25 28 ··· 65 62 required: 66 63 - compatible 67 64 - reg 65 + - interrupts 68 66 69 67 examples: 70 68 - | 69 + #include <dt-bindings/interrupt-controller/irq.h> 70 + 71 71 i2c { 72 72 #address-cells = <1>; 73 73 #size-cells = <0>; ··· 78 72 ethernet-pse@20 { 79 73 compatible = "ti,tps23881"; 80 74 reg = <0x20>; 75 + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; 76 + interrupt-parent = <&gpiog>; 81 77 82 78 channels { 83 79 #address-cells = <1>;
+76
Documentation/netlink/specs/ethtool.yaml
··· 118 118 doc: | 119 119 Hardware timestamp comes from one PHY device 120 120 of the network topology 121 + - 122 + name: pse-event 123 + doc: PSE event list for the PSE controller 124 + type: flags 125 + name-prefix: ethtool- 126 + entries: 127 + - 128 + name: pse-event-over-current 129 + doc: PSE output current is too high 130 + - 131 + name: pse-event-over-temp 132 + doc: PSE in over temperature state 133 + - 134 + name: c33-pse-event-detection 135 + doc: | 136 + detection process occur on the PSE. IEEE 802.3-2022 33.2.5 and 137 + 145.2.6 PSE detection of PDs. IEEE 802.3-202 30.9.1.1.5 138 + aPSEPowerDetectionStatus 139 + - 140 + name: c33-pse-event-classification 141 + doc: | 142 + classification process occur on the PSE. IEEE 802.3-2022 33.2.6 143 + and 145.2.8 classification of PDs mutual identification. 144 + IEEE 802.3-2022 30.9.1.1.8 aPSEPowerClassification. 145 + - 146 + name: c33-pse-event-disconnection 147 + doc: | 148 + PD has been disconnected on the PSE. IEEE 802.3-2022 33.3.8 149 + and 145.3.9 PD Maintain Power Signature. IEEE 802.3-2022 150 + 33.5.1.2.9 MPS Absent. IEEE 802.3-2022 30.9.1.1.20 151 + aPSEMPSAbsentCounter. 152 + - 153 + name: pse-event-over-budget 154 + doc: PSE turned off due to over budget situation 155 + - 156 + name: pse-event-sw-pw-control-error 157 + doc: PSE faced an error managing the power control from software 121 158 122 159 attribute-sets: 123 160 - ··· 1432 1395 type: nest 1433 1396 multi-attr: true 1434 1397 nested-attributes: c33-pse-pw-limit 1398 + - 1399 + name: pse-pw-d-id 1400 + type: u32 1401 + name-prefix: ethtool-a- 1402 + - 1403 + name: pse-prio-max 1404 + type: u32 1405 + name-prefix: ethtool-a- 1406 + - 1407 + name: pse-prio 1408 + type: u32 1409 + name-prefix: ethtool-a- 1435 1410 - 1436 1411 name: rss 1437 1412 attr-cnt-name: __ethtool-a-rss-cnt ··· 1604 1555 name: hwtstamp-flags 1605 1556 type: nest 1606 1557 nested-attributes: bitset 1558 + - 1559 + name: pse-ntf 1560 + attr-cnt-name: --ethtool-a-pse-ntf-cnt 1561 + attributes: 1562 + - 1563 + name: header 1564 + type: nest 1565 + nested-attributes: header 1566 + - 1567 + name: events 1568 + type: uint 1569 + enum: pse-event 1570 + doc: List of events reported by the PSE controller 1607 1571 1608 1572 operations: 1609 1573 enum-model: directional ··· 2267 2205 - c33-pse-ext-substate 2268 2206 - c33-pse-avail-pw-limit 2269 2207 - c33-pse-pw-limit-ranges 2208 + - pse-pw-d-id 2209 + - pse-prio-max 2210 + - pse-prio 2270 2211 dump: *pse-get-op 2271 2212 - 2272 2213 name: pse-set ··· 2284 2219 - podl-pse-admin-control 2285 2220 - c33-pse-admin-control 2286 2221 - c33-pse-avail-pw-limit 2222 + - pse-prio 2287 2223 - 2288 2224 name: rss-get 2289 2225 doc: Get RSS params. ··· 2479 2413 attributes: *tsconfig 2480 2414 reply: 2481 2415 attributes: *tsconfig 2416 + - 2417 + name: pse-ntf 2418 + doc: Notification for PSE events. 2419 + 2420 + attribute-set: pse-ntf 2421 + 2422 + event: 2423 + attributes: 2424 + - header 2425 + - events
+49
Documentation/networking/ethtool-netlink.rst
··· 290 290 ``ETHTOOL_MSG_PHY_NTF`` Ethernet PHY information change 291 291 ``ETHTOOL_MSG_TSCONFIG_GET_REPLY`` hw timestamping configuration 292 292 ``ETHTOOL_MSG_TSCONFIG_SET_REPLY`` new hw timestamping configuration 293 + ``ETHTOOL_MSG_PSE_NTF`` PSE events notification 293 294 ======================================== ================================= 294 295 295 296 ``GET`` requests are sent by userspace applications to retrieve device ··· 1789 1788 limit of the PoE PSE. 1790 1789 ``ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES`` nested Supported power limit 1791 1790 configuration ranges. 1791 + ``ETHTOOL_A_PSE_PW_D_ID`` u32 Index of the PSE power domain 1792 + ``ETHTOOL_A_PSE_PRIO_MAX`` u32 Priority maximum configurable 1793 + on the PoE PSE 1794 + ``ETHTOOL_A_PSE_PRIO`` u32 Priority of the PoE PSE 1795 + currently configured 1792 1796 ========================================== ====== ============================= 1793 1797 1794 1798 When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` attribute identifies ··· 1867 1861 If the controller works with fixed classes, the min and max values will be 1868 1862 equal. 1869 1863 1864 + The ``ETHTOOL_A_PSE_PW_D_ID`` attribute identifies the index of PSE power 1865 + domain. 1866 + 1867 + When set, the optional ``ETHTOOL_A_PSE_PRIO_MAX`` attribute identifies 1868 + the PSE maximum priority value. 1869 + When set, the optional ``ETHTOOL_A_PSE_PRIO`` attributes is used to 1870 + identifies the currently configured PSE priority. 1871 + For a description of PSE priority attributes, see ``PSE_SET``. 1872 + 1870 1873 PSE_SET 1871 1874 ======= 1872 1875 ··· 1889 1874 ``ETHTOOL_A_C33_PSE_ADMIN_CONTROL`` u32 Control PSE Admin state 1890 1875 ``ETHTOOL_A_C33_PSE_AVAIL_PWR_LIMIT`` u32 Control PoE PSE available 1891 1876 power limit 1877 + ``ETHTOOL_A_PSE_PRIO`` u32 Control priority of the 1878 + PoE PSE 1892 1879 ====================================== ====== ============================= 1893 1880 1894 1881 When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` attribute is used ··· 1912 1895 various existing products that document power consumption in watts rather than 1913 1896 classes. If power limit configuration based on classes is needed, the 1914 1897 conversion can be done in user space, for example by ethtool. 1898 + 1899 + When set, the optional ``ETHTOOL_A_PSE_PRIO`` attributes is used to 1900 + control the PSE priority. Allowed priority value are between zero and 1901 + the value of ``ETHTOOL_A_PSE_PRIO_MAX`` attribute. 1902 + 1903 + A lower value indicates a higher priority, meaning that a priority value 1904 + of 0 corresponds to the highest port priority. 1905 + Port priority serves two functions: 1906 + 1907 + - Power-up Order: After a reset, ports are powered up in order of their 1908 + priority from highest to lowest. Ports with higher priority 1909 + (lower values) power up first. 1910 + - Shutdown Order: When the power budget is exceeded, ports with lower 1911 + priority (higher values) are turned off first. 1912 + 1913 + PSE_NTF 1914 + ======= 1915 + 1916 + Notify PSE events. 1917 + 1918 + Notification contents: 1919 + 1920 + =============================== ====== ======================== 1921 + ``ETHTOOL_A_PSE_HEADER`` nested request header 1922 + ``ETHTOOL_A_PSE_EVENTS`` bitset PSE events 1923 + =============================== ====== ======================== 1924 + 1925 + When set, the optional ``ETHTOOL_A_PSE_EVENTS`` attribute identifies the 1926 + PSE events. 1927 + 1928 + .. kernel-doc:: include/uapi/linux/ethtool_netlink_generated.h 1929 + :identifiers: ethtool_pse_event 1915 1930 1916 1931 RSS_GET 1917 1932 =======
+14 -12
drivers/net/mdio/fwnode_mdio.c
··· 18 18 MODULE_DESCRIPTION("FWNODE MDIO bus (Ethernet PHY) accessors"); 19 19 20 20 static struct pse_control * 21 - fwnode_find_pse_control(struct fwnode_handle *fwnode) 21 + fwnode_find_pse_control(struct fwnode_handle *fwnode, 22 + struct phy_device *phydev) 22 23 { 23 24 struct pse_control *psec; 24 25 struct device_node *np; ··· 31 30 if (!np) 32 31 return NULL; 33 32 34 - psec = of_pse_control_get(np); 33 + psec = of_pse_control_get(np, phydev); 35 34 if (PTR_ERR(psec) == -ENOENT) 36 35 return NULL; 37 36 ··· 129 128 u32 phy_id; 130 129 int rc; 131 130 132 - psec = fwnode_find_pse_control(child); 133 - if (IS_ERR(psec)) 134 - return PTR_ERR(psec); 135 - 136 131 mii_ts = fwnode_find_mii_timestamper(child); 137 - if (IS_ERR(mii_ts)) { 138 - rc = PTR_ERR(mii_ts); 139 - goto clean_pse; 140 - } 132 + if (IS_ERR(mii_ts)) 133 + return PTR_ERR(mii_ts); 141 134 142 135 is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); 143 136 if (is_c45 || fwnode_get_phy_id(child, &phy_id)) ··· 164 169 goto clean_phy; 165 170 } 166 171 172 + psec = fwnode_find_pse_control(child, phy); 173 + if (IS_ERR(psec)) { 174 + rc = PTR_ERR(psec); 175 + goto unregister_phy; 176 + } 177 + 167 178 phy->psec = psec; 168 179 169 180 /* phy->mii_ts may already be defined by the PHY driver. A ··· 181 180 182 181 return 0; 183 182 183 + unregister_phy: 184 + if (is_acpi_node(child) || is_of_node(child)) 185 + phy_device_remove(phy); 184 186 clean_phy: 185 187 phy_device_free(phy); 186 188 clean_mii_ts: 187 189 unregister_mii_timestamper(mii_ts); 188 - clean_pse: 189 - pse_control_put(psec); 190 190 191 191 return rc; 192 192 }
+225
drivers/net/pse-pd/pd692x0.c
··· 12 12 #include <linux/of.h> 13 13 #include <linux/platform_device.h> 14 14 #include <linux/pse-pd/pse.h> 15 + #include <linux/regulator/driver.h> 16 + #include <linux/regulator/machine.h> 15 17 16 18 #define PD692X0_PSE_NAME "pd692x0_pse" 17 19 ··· 78 76 PD692X0_MSG_GET_PORT_CLASS, 79 77 PD692X0_MSG_GET_PORT_MEAS, 80 78 PD692X0_MSG_GET_PORT_PARAM, 79 + PD692X0_MSG_GET_POWER_BANK, 80 + PD692X0_MSG_SET_POWER_BANK, 81 81 82 82 /* add new message above here */ 83 83 PD692X0_MSG_CNT ··· 99 95 unsigned long last_cmd_key_time; 100 96 101 97 enum ethtool_c33_pse_admin_state admin_state[PD692X0_MAX_PIS]; 98 + struct regulator_dev *manager_reg[PD692X0_MAX_MANAGERS]; 99 + int manager_pw_budget[PD692X0_MAX_MANAGERS]; 102 100 }; 103 101 104 102 /* Template list of communication messages. The non-null bytes defined here ··· 175 169 .sub = {0x05, 0xc0}, 176 170 .data = {0x4e, 0x4e, 0x4e, 0x4e, 177 171 0x4e, 0x4e, 0x4e, 0x4e}, 172 + }, 173 + [PD692X0_MSG_GET_POWER_BANK] = { 174 + .key = PD692X0_KEY_REQ, 175 + .sub = {0x07, 0x0b, 0x57}, 176 + .data = { 0, 0x4e, 0x4e, 0x4e, 177 + 0x4e, 0x4e, 0x4e, 0x4e}, 178 + }, 179 + [PD692X0_MSG_SET_POWER_BANK] = { 180 + .key = PD692X0_KEY_CMD, 181 + .sub = {0x07, 0x0b, 0x57}, 178 182 }, 179 183 }; 180 184 ··· 755 739 return (buf.data[0] << 4 | buf.data[1]) * 100; 756 740 } 757 741 742 + static int 743 + pd692x0_pi_get_prio(struct pse_controller_dev *pcdev, int id) 744 + { 745 + struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); 746 + struct pd692x0_msg msg, buf = {0}; 747 + int ret; 748 + 749 + ret = pd692x0_fw_unavailable(priv); 750 + if (ret) 751 + return ret; 752 + 753 + msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM]; 754 + msg.sub[2] = id; 755 + ret = pd692x0_sendrecv_msg(priv, &msg, &buf); 756 + if (ret < 0) 757 + return ret; 758 + if (!buf.data[2] || buf.data[2] > pcdev->pis_prio_max + 1) 759 + return -ERANGE; 760 + 761 + /* PSE core priority start at 0 */ 762 + return buf.data[2] - 1; 763 + } 764 + 758 765 static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv) 759 766 { 760 767 struct device *dev = &priv->client->dev; ··· 805 766 806 767 struct pd692x0_manager { 807 768 struct device_node *port_node[PD692X0_MAX_MANAGER_PORTS]; 769 + struct device_node *node; 808 770 int nports; 809 771 }; 810 772 ··· 897 857 if (ret) 898 858 goto out; 899 859 860 + of_node_get(node); 861 + manager[manager_id].node = node; 900 862 nmanagers++; 901 863 } 902 864 ··· 911 869 of_node_put(manager[i].port_node[j]); 912 870 manager[i].port_node[j] = NULL; 913 871 } 872 + of_node_put(manager[i].node); 873 + manager[i].node = NULL; 914 874 } 915 875 916 876 of_node_put(node); 917 877 of_node_put(managers_node); 918 878 return ret; 879 + } 880 + 881 + static const struct regulator_ops dummy_ops; 882 + 883 + static struct regulator_dev * 884 + pd692x0_register_manager_regulator(struct device *dev, char *reg_name, 885 + struct device_node *node) 886 + { 887 + struct regulator_init_data *rinit_data; 888 + struct regulator_config rconfig = {0}; 889 + struct regulator_desc *rdesc; 890 + struct regulator_dev *rdev; 891 + 892 + rinit_data = devm_kzalloc(dev, sizeof(*rinit_data), 893 + GFP_KERNEL); 894 + if (!rinit_data) 895 + return ERR_PTR(-ENOMEM); 896 + 897 + rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); 898 + if (!rdesc) 899 + return ERR_PTR(-ENOMEM); 900 + 901 + rdesc->name = reg_name; 902 + rdesc->type = REGULATOR_VOLTAGE; 903 + rdesc->ops = &dummy_ops; 904 + rdesc->owner = THIS_MODULE; 905 + 906 + rinit_data->supply_regulator = "vmain"; 907 + 908 + rconfig.dev = dev; 909 + rconfig.init_data = rinit_data; 910 + rconfig.of_node = node; 911 + 912 + rdev = devm_regulator_register(dev, rdesc, &rconfig); 913 + if (IS_ERR(rdev)) { 914 + dev_err_probe(dev, PTR_ERR(rdev), 915 + "Failed to register regulator\n"); 916 + return rdev; 917 + } 918 + 919 + return rdev; 920 + } 921 + 922 + static int 923 + pd692x0_register_managers_regulator(struct pd692x0_priv *priv, 924 + const struct pd692x0_manager *manager, 925 + int nmanagers) 926 + { 927 + struct device *dev = &priv->client->dev; 928 + size_t reg_name_len; 929 + int i; 930 + 931 + /* Each regulator name len is dev name + 12 char + 932 + * int max digit number (10) + 1 933 + */ 934 + reg_name_len = strlen(dev_name(dev)) + 23; 935 + 936 + for (i = 0; i < nmanagers; i++) { 937 + static const char * const regulators[] = { "vaux5", "vaux3p3" }; 938 + struct regulator_dev *rdev; 939 + char *reg_name; 940 + int ret; 941 + 942 + reg_name = devm_kzalloc(dev, reg_name_len, GFP_KERNEL); 943 + if (!reg_name) 944 + return -ENOMEM; 945 + snprintf(reg_name, 26, "pse-%s-manager%d", dev_name(dev), i); 946 + rdev = pd692x0_register_manager_regulator(dev, reg_name, 947 + manager[i].node); 948 + if (IS_ERR(rdev)) 949 + return PTR_ERR(rdev); 950 + 951 + /* VMAIN is described as main supply for the manager. 952 + * Add other VAUX power supplies and link them to the 953 + * virtual device rdev->dev. 954 + */ 955 + ret = devm_regulator_bulk_get_enable(&rdev->dev, 956 + ARRAY_SIZE(regulators), 957 + regulators); 958 + if (ret) 959 + return dev_err_probe(&rdev->dev, ret, 960 + "Failed to enable regulators\n"); 961 + 962 + priv->manager_reg[i] = rdev; 963 + } 964 + 965 + return 0; 966 + } 967 + 968 + static int 969 + pd692x0_conf_manager_power_budget(struct pd692x0_priv *priv, int id, int pw) 970 + { 971 + struct pd692x0_msg msg, buf; 972 + int ret, pw_mW = pw / 1000; 973 + 974 + msg = pd692x0_msg_template_list[PD692X0_MSG_GET_POWER_BANK]; 975 + msg.data[0] = id; 976 + ret = pd692x0_sendrecv_msg(priv, &msg, &buf); 977 + if (ret < 0) 978 + return ret; 979 + 980 + msg = pd692x0_msg_template_list[PD692X0_MSG_SET_POWER_BANK]; 981 + msg.data[0] = id; 982 + msg.data[1] = pw_mW >> 8; 983 + msg.data[2] = pw_mW & 0xff; 984 + msg.data[3] = buf.sub[2]; 985 + msg.data[4] = buf.data[0]; 986 + msg.data[5] = buf.data[1]; 987 + msg.data[6] = buf.data[2]; 988 + msg.data[7] = buf.data[3]; 989 + return pd692x0_sendrecv_msg(priv, &msg, &buf); 990 + } 991 + 992 + static int 993 + pd692x0_configure_managers(struct pd692x0_priv *priv, int nmanagers) 994 + { 995 + int i, ret; 996 + 997 + for (i = 0; i < nmanagers; i++) { 998 + struct regulator *supply = priv->manager_reg[i]->supply; 999 + int pw_budget; 1000 + 1001 + pw_budget = regulator_get_unclaimed_power_budget(supply); 1002 + /* Max power budget per manager */ 1003 + if (pw_budget > 6000000) 1004 + pw_budget = 6000000; 1005 + ret = regulator_request_power_budget(supply, pw_budget); 1006 + if (ret < 0) 1007 + return ret; 1008 + 1009 + priv->manager_pw_budget[i] = pw_budget; 1010 + ret = pd692x0_conf_manager_power_budget(priv, i, pw_budget); 1011 + if (ret < 0) 1012 + return ret; 1013 + } 1014 + 1015 + return 0; 919 1016 } 920 1017 921 1018 static int ··· 1179 998 return ret; 1180 999 1181 1000 nmanagers = ret; 1001 + ret = pd692x0_register_managers_regulator(priv, manager, nmanagers); 1002 + if (ret) 1003 + goto out; 1004 + 1005 + ret = pd692x0_configure_managers(priv, nmanagers); 1006 + if (ret) 1007 + goto out; 1008 + 1182 1009 ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix); 1183 1010 if (ret) 1184 1011 goto out; ··· 1197 1008 1198 1009 out: 1199 1010 for (i = 0; i < nmanagers; i++) { 1011 + struct regulator *supply = priv->manager_reg[i]->supply; 1012 + 1013 + regulator_free_power_budget(supply, 1014 + priv->manager_pw_budget[i]); 1015 + 1200 1016 for (j = 0; j < manager[i].nports; j++) 1201 1017 of_node_put(manager[i].port_node[j]); 1018 + of_node_put(manager[i].node); 1202 1019 } 1203 1020 return ret; 1204 1021 } ··· 1266 1071 return pd692x0_sendrecv_msg(priv, &msg, &buf); 1267 1072 } 1268 1073 1074 + static int pd692x0_pi_set_prio(struct pse_controller_dev *pcdev, int id, 1075 + unsigned int prio) 1076 + { 1077 + struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); 1078 + struct pd692x0_msg msg, buf = {0}; 1079 + int ret; 1080 + 1081 + ret = pd692x0_fw_unavailable(priv); 1082 + if (ret) 1083 + return ret; 1084 + 1085 + msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM]; 1086 + msg.sub[2] = id; 1087 + /* Controller priority from 1 to 3 */ 1088 + msg.data[4] = prio + 1; 1089 + 1090 + return pd692x0_sendrecv_msg(priv, &msg, &buf); 1091 + } 1092 + 1269 1093 static const struct pse_controller_ops pd692x0_ops = { 1270 1094 .setup_pi_matrix = pd692x0_setup_pi_matrix, 1271 1095 .pi_get_admin_state = pd692x0_pi_get_admin_state, ··· 1298 1084 .pi_get_pw_limit = pd692x0_pi_get_pw_limit, 1299 1085 .pi_set_pw_limit = pd692x0_pi_set_pw_limit, 1300 1086 .pi_get_pw_limit_ranges = pd692x0_pi_get_pw_limit_ranges, 1087 + .pi_get_prio = pd692x0_pi_get_prio, 1088 + .pi_set_prio = pd692x0_pi_set_prio, 1301 1089 }; 1302 1090 1303 1091 #define PD692X0_FW_LINE_MAX_SZ 0xff ··· 1653 1437 1654 1438 static int pd692x0_i2c_probe(struct i2c_client *client) 1655 1439 { 1440 + static const char * const regulators[] = { "vdd", "vdda" }; 1656 1441 struct pd692x0_msg msg, buf = {0}, zero = {0}; 1657 1442 struct device *dev = &client->dev; 1658 1443 struct pd692x0_msg_ver ver; 1659 1444 struct pd692x0_priv *priv; 1660 1445 struct fw_upload *fwl; 1661 1446 int ret; 1447 + 1448 + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators), 1449 + regulators); 1450 + if (ret) 1451 + return dev_err_probe(dev, ret, 1452 + "Failed to enable regulators\n"); 1662 1453 1663 1454 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 1664 1455 dev_err(dev, "i2c check functionality failed\n"); ··· 1723 1500 priv->pcdev.ops = &pd692x0_ops; 1724 1501 priv->pcdev.dev = dev; 1725 1502 priv->pcdev.types = ETHTOOL_PSE_C33; 1503 + priv->pcdev.supp_budget_eval_strategies = PSE_BUDGET_EVAL_STRAT_DYNAMIC; 1504 + priv->pcdev.pis_prio_max = 2; 1726 1505 ret = devm_pse_controller_register(dev, &priv->pcdev); 1727 1506 if (ret) 1728 1507 return dev_err_probe(dev, ret,
+1032 -34
drivers/net/pse-pd/pse_core.c
··· 7 7 8 8 #include <linux/device.h> 9 9 #include <linux/ethtool.h> 10 + #include <linux/ethtool_netlink.h> 10 11 #include <linux/of.h> 12 + #include <linux/phy.h> 11 13 #include <linux/pse-pd/pse.h> 12 14 #include <linux/regulator/driver.h> 13 15 #include <linux/regulator/machine.h> 16 + #include <linux/rtnetlink.h> 17 + #include <net/net_trackers.h> 18 + 19 + #define PSE_PW_D_LIMIT INT_MAX 14 20 15 21 static DEFINE_MUTEX(pse_list_mutex); 16 22 static LIST_HEAD(pse_controller_list); 23 + static DEFINE_XARRAY_ALLOC(pse_pw_d_map); 24 + static DEFINE_MUTEX(pse_pw_d_mutex); 17 25 18 26 /** 19 27 * struct pse_control - a PSE control ··· 31 23 * @list: list entry for the pcdev's PSE controller list 32 24 * @id: ID of the PSE line in the PSE controller device 33 25 * @refcnt: Number of gets of this pse_control 26 + * @attached_phydev: PHY device pointer attached by the PSE control 34 27 */ 35 28 struct pse_control { 36 29 struct pse_controller_dev *pcdev; ··· 39 30 struct list_head list; 40 31 unsigned int id; 41 32 struct kref refcnt; 33 + struct phy_device *attached_phydev; 34 + }; 35 + 36 + /** 37 + * struct pse_power_domain - a PSE power domain 38 + * @id: ID of the power domain 39 + * @supply: Power supply the Power Domain 40 + * @refcnt: Number of gets of this pse_power_domain 41 + * @budget_eval_strategy: Current power budget evaluation strategy of the 42 + * power domain 43 + */ 44 + struct pse_power_domain { 45 + int id; 46 + struct regulator *supply; 47 + struct kref refcnt; 48 + u32 budget_eval_strategy; 42 49 }; 43 50 44 51 static int of_load_single_pse_pi_pairset(struct device_node *node, ··· 233 208 return ret; 234 209 } 235 210 211 + /** 212 + * pse_control_find_net_by_id - Find net attached to the pse control id 213 + * @pcdev: a pointer to the PSE 214 + * @id: index of the PSE control 215 + * 216 + * Return: pse_control pointer or NULL. The device returned has had a 217 + * reference added and the pointer is safe until the user calls 218 + * pse_control_put() to indicate they have finished with it. 219 + */ 220 + static struct pse_control * 221 + pse_control_find_by_id(struct pse_controller_dev *pcdev, int id) 222 + { 223 + struct pse_control *psec; 224 + 225 + mutex_lock(&pse_list_mutex); 226 + list_for_each_entry(psec, &pcdev->pse_control_head, list) { 227 + if (psec->id == id) { 228 + kref_get(&psec->refcnt); 229 + mutex_unlock(&pse_list_mutex); 230 + return psec; 231 + } 232 + } 233 + mutex_unlock(&pse_list_mutex); 234 + return NULL; 235 + } 236 + 237 + /** 238 + * pse_control_get_netdev - Return netdev associated to a PSE control 239 + * @psec: PSE control pointer 240 + * 241 + * Return: netdev pointer or NULL 242 + */ 243 + static struct net_device *pse_control_get_netdev(struct pse_control *psec) 244 + { 245 + ASSERT_RTNL(); 246 + 247 + if (!psec || !psec->attached_phydev) 248 + return NULL; 249 + 250 + return psec->attached_phydev->attached_dev; 251 + } 252 + 253 + /** 254 + * pse_pi_is_hw_enabled - Is PI enabled at the hardware level 255 + * @pcdev: a pointer to the PSE controller device 256 + * @id: Index of the PI 257 + * 258 + * Return: 1 if the PI is enabled at the hardware level, 0 if not, and 259 + * a failure value on error 260 + */ 261 + static int pse_pi_is_hw_enabled(struct pse_controller_dev *pcdev, int id) 262 + { 263 + struct pse_admin_state admin_state = {0}; 264 + int ret; 265 + 266 + ret = pcdev->ops->pi_get_admin_state(pcdev, id, &admin_state); 267 + if (ret < 0) 268 + return ret; 269 + 270 + /* PI is well enabled at the hardware level */ 271 + if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED || 272 + admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED) 273 + return 1; 274 + 275 + return 0; 276 + } 277 + 278 + /** 279 + * pse_pi_is_admin_enable_pending - Check if PI is in admin enable pending state 280 + * which mean the power is not yet being 281 + * delivered 282 + * @pcdev: a pointer to the PSE controller device 283 + * @id: Index of the PI 284 + * 285 + * Detects if a PI is enabled in software with a PD detected, but the hardware 286 + * admin state hasn't been applied yet. 287 + * 288 + * This function is used in the power delivery and retry mechanisms to determine 289 + * which PIs need to have power delivery attempted again. 290 + * 291 + * Return: true if the PI has admin enable flag set in software but not yet 292 + * reflected in the hardware admin state, false otherwise. 293 + */ 294 + static bool 295 + pse_pi_is_admin_enable_pending(struct pse_controller_dev *pcdev, int id) 296 + { 297 + int ret; 298 + 299 + /* PI not enabled or nothing is plugged */ 300 + if (!pcdev->pi[id].admin_state_enabled || 301 + !pcdev->pi[id].isr_pd_detected) 302 + return false; 303 + 304 + ret = pse_pi_is_hw_enabled(pcdev, id); 305 + /* PSE PI is already enabled at hardware level */ 306 + if (ret == 1) 307 + return false; 308 + 309 + return true; 310 + } 311 + 312 + static int _pse_pi_delivery_power_sw_pw_ctrl(struct pse_controller_dev *pcdev, 313 + int id, 314 + struct netlink_ext_ack *extack); 315 + 316 + /** 317 + * pse_pw_d_retry_power_delivery - Retry power delivery for pending ports in a 318 + * PSE power domain 319 + * @pcdev: a pointer to the PSE controller device 320 + * @pw_d: a pointer to the PSE power domain 321 + * 322 + * Scans all ports in the specified power domain and attempts to enable power 323 + * delivery to any ports that have admin enable state set but don't yet have 324 + * hardware power enabled. Used when there are changes in connection status, 325 + * admin state, or priority that might allow previously unpowered ports to 326 + * receive power, especially in over-budget conditions. 327 + */ 328 + static void pse_pw_d_retry_power_delivery(struct pse_controller_dev *pcdev, 329 + struct pse_power_domain *pw_d) 330 + { 331 + int i, ret = 0; 332 + 333 + for (i = 0; i < pcdev->nr_lines; i++) { 334 + int prio_max = pcdev->nr_lines; 335 + struct netlink_ext_ack extack; 336 + 337 + if (pcdev->pi[i].pw_d != pw_d) 338 + continue; 339 + 340 + if (!pse_pi_is_admin_enable_pending(pcdev, i)) 341 + continue; 342 + 343 + /* Do not try to enable PI with a lower prio (higher value) 344 + * than one which already can't be enabled. 345 + */ 346 + if (pcdev->pi[i].prio > prio_max) 347 + continue; 348 + 349 + ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, i, &extack); 350 + if (ret == -ERANGE) 351 + prio_max = pcdev->pi[i].prio; 352 + } 353 + } 354 + 355 + /** 356 + * pse_pw_d_is_sw_pw_control - Determine if power control is software managed 357 + * @pcdev: a pointer to the PSE controller device 358 + * @pw_d: a pointer to the PSE power domain 359 + * 360 + * This function determines whether the power control for a specific power 361 + * domain is managed by software in the interrupt handler rather than directly 362 + * by hardware. 363 + * 364 + * Software power control is active in the following cases: 365 + * - When the budget evaluation strategy is set to static 366 + * - When the budget evaluation strategy is disabled but the PSE controller 367 + * has an interrupt handler that can report if a Powered Device is connected 368 + * 369 + * Return: true if the power control of the power domain is managed by software, 370 + * false otherwise 371 + */ 372 + static bool pse_pw_d_is_sw_pw_control(struct pse_controller_dev *pcdev, 373 + struct pse_power_domain *pw_d) 374 + { 375 + if (!pw_d) 376 + return false; 377 + 378 + if (pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_STATIC) 379 + return true; 380 + if (pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_DISABLED && 381 + pcdev->ops->pi_enable && pcdev->irq) 382 + return true; 383 + 384 + return false; 385 + } 386 + 236 387 static int pse_pi_is_enabled(struct regulator_dev *rdev) 237 388 { 238 389 struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 239 - struct pse_admin_state admin_state = {0}; 240 390 const struct pse_controller_ops *ops; 241 391 int id, ret; 242 392 ··· 421 221 422 222 id = rdev_get_id(rdev); 423 223 mutex_lock(&pcdev->lock); 424 - ret = ops->pi_get_admin_state(pcdev, id, &admin_state); 425 - if (ret) 224 + if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) { 225 + ret = pcdev->pi[id].admin_state_enabled; 426 226 goto out; 227 + } 427 228 428 - if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED || 429 - admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED) 430 - ret = 1; 229 + ret = pse_pi_is_hw_enabled(pcdev, id); 431 230 432 231 out: 433 232 mutex_unlock(&pcdev->lock); ··· 434 235 return ret; 435 236 } 436 237 238 + /** 239 + * pse_pi_deallocate_pw_budget - Deallocate power budget of the PI 240 + * @pi: a pointer to the PSE PI 241 + */ 242 + static void pse_pi_deallocate_pw_budget(struct pse_pi *pi) 243 + { 244 + if (!pi->pw_d || !pi->pw_allocated_mW) 245 + return; 246 + 247 + regulator_free_power_budget(pi->pw_d->supply, pi->pw_allocated_mW); 248 + pi->pw_allocated_mW = 0; 249 + } 250 + 251 + /** 252 + * _pse_pi_disable - Call disable operation. Assumes the PSE lock has been 253 + * acquired. 254 + * @pcdev: a pointer to the PSE 255 + * @id: index of the PSE control 256 + * 257 + * Return: 0 on success and failure value on error 258 + */ 259 + static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id) 260 + { 261 + const struct pse_controller_ops *ops = pcdev->ops; 262 + int ret; 263 + 264 + if (!ops->pi_disable) 265 + return -EOPNOTSUPP; 266 + 267 + ret = ops->pi_disable(pcdev, id); 268 + if (ret) 269 + return ret; 270 + 271 + pse_pi_deallocate_pw_budget(&pcdev->pi[id]); 272 + 273 + if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) 274 + pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[id].pw_d); 275 + 276 + return 0; 277 + } 278 + 279 + /** 280 + * pse_disable_pi_pol - Disable a PI on a power budget policy 281 + * @pcdev: a pointer to the PSE 282 + * @id: index of the PSE PI 283 + * 284 + * Return: 0 on success and failure value on error 285 + */ 286 + static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id) 287 + { 288 + unsigned long notifs = ETHTOOL_PSE_EVENT_OVER_BUDGET; 289 + struct pse_ntf ntf = {}; 290 + int ret; 291 + 292 + dev_dbg(pcdev->dev, "Disabling PI %d to free power budget\n", id); 293 + 294 + ret = _pse_pi_disable(pcdev, id); 295 + if (ret) 296 + notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR; 297 + 298 + ntf.notifs = notifs; 299 + ntf.id = id; 300 + kfifo_in_spinlocked(&pcdev->ntf_fifo, &ntf, 1, &pcdev->ntf_fifo_lock); 301 + schedule_work(&pcdev->ntf_work); 302 + 303 + return ret; 304 + } 305 + 306 + /** 307 + * pse_disable_pi_prio - Disable all PIs of a given priority inside a PSE 308 + * power domain 309 + * @pcdev: a pointer to the PSE 310 + * @pw_d: a pointer to the PSE power domain 311 + * @prio: priority 312 + * 313 + * Return: 0 on success and failure value on error 314 + */ 315 + static int pse_disable_pi_prio(struct pse_controller_dev *pcdev, 316 + struct pse_power_domain *pw_d, 317 + int prio) 318 + { 319 + int i; 320 + 321 + for (i = 0; i < pcdev->nr_lines; i++) { 322 + int ret; 323 + 324 + if (pcdev->pi[i].prio != prio || 325 + pcdev->pi[i].pw_d != pw_d || 326 + pse_pi_is_hw_enabled(pcdev, i) <= 0) 327 + continue; 328 + 329 + ret = pse_disable_pi_pol(pcdev, i); 330 + if (ret) 331 + return ret; 332 + } 333 + 334 + return 0; 335 + } 336 + 337 + /** 338 + * pse_pi_allocate_pw_budget_static_prio - Allocate power budget for the PI 339 + * when the budget eval strategy is 340 + * static 341 + * @pcdev: a pointer to the PSE 342 + * @id: index of the PSE control 343 + * @pw_req: power requested in mW 344 + * @extack: extack for error reporting 345 + * 346 + * Allocates power using static budget evaluation strategy, where allocation 347 + * is based on PD classification. When insufficient budget is available, 348 + * lower-priority ports (higher priority numbers) are turned off first. 349 + * 350 + * Return: 0 on success and failure value on error 351 + */ 352 + static int 353 + pse_pi_allocate_pw_budget_static_prio(struct pse_controller_dev *pcdev, int id, 354 + int pw_req, struct netlink_ext_ack *extack) 355 + { 356 + struct pse_pi *pi = &pcdev->pi[id]; 357 + int ret, _prio; 358 + 359 + _prio = pcdev->nr_lines; 360 + while (regulator_request_power_budget(pi->pw_d->supply, pw_req) == -ERANGE) { 361 + if (_prio <= pi->prio) { 362 + NL_SET_ERR_MSG_FMT(extack, 363 + "PI %d: not enough power budget available", 364 + id); 365 + return -ERANGE; 366 + } 367 + 368 + ret = pse_disable_pi_prio(pcdev, pi->pw_d, _prio); 369 + if (ret < 0) 370 + return ret; 371 + 372 + _prio--; 373 + } 374 + 375 + pi->pw_allocated_mW = pw_req; 376 + return 0; 377 + } 378 + 379 + /** 380 + * pse_pi_allocate_pw_budget - Allocate power budget for the PI 381 + * @pcdev: a pointer to the PSE 382 + * @id: index of the PSE control 383 + * @pw_req: power requested in mW 384 + * @extack: extack for error reporting 385 + * 386 + * Return: 0 on success and failure value on error 387 + */ 388 + static int pse_pi_allocate_pw_budget(struct pse_controller_dev *pcdev, int id, 389 + int pw_req, struct netlink_ext_ack *extack) 390 + { 391 + struct pse_pi *pi = &pcdev->pi[id]; 392 + 393 + if (!pi->pw_d) 394 + return 0; 395 + 396 + /* PSE_BUDGET_EVAL_STRAT_STATIC */ 397 + if (pi->pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_STATIC) 398 + return pse_pi_allocate_pw_budget_static_prio(pcdev, id, pw_req, 399 + extack); 400 + 401 + return 0; 402 + } 403 + 404 + /** 405 + * _pse_pi_delivery_power_sw_pw_ctrl - Enable PSE PI in case of software power 406 + * control. Assumes the PSE lock has been 407 + * acquired. 408 + * @pcdev: a pointer to the PSE 409 + * @id: index of the PSE control 410 + * @extack: extack for error reporting 411 + * 412 + * Return: 0 on success and failure value on error 413 + */ 414 + static int _pse_pi_delivery_power_sw_pw_ctrl(struct pse_controller_dev *pcdev, 415 + int id, 416 + struct netlink_ext_ack *extack) 417 + { 418 + const struct pse_controller_ops *ops = pcdev->ops; 419 + struct pse_pi *pi = &pcdev->pi[id]; 420 + int ret, pw_req; 421 + 422 + if (!ops->pi_get_pw_req) { 423 + /* No power allocation management */ 424 + ret = ops->pi_enable(pcdev, id); 425 + if (ret) 426 + NL_SET_ERR_MSG_FMT(extack, 427 + "PI %d: enable error %d", 428 + id, ret); 429 + return ret; 430 + } 431 + 432 + ret = ops->pi_get_pw_req(pcdev, id); 433 + if (ret < 0) 434 + return ret; 435 + 436 + pw_req = ret; 437 + 438 + /* Compare requested power with port power limit and use the lowest 439 + * one. 440 + */ 441 + if (ops->pi_get_pw_limit) { 442 + ret = ops->pi_get_pw_limit(pcdev, id); 443 + if (ret < 0) 444 + return ret; 445 + 446 + if (ret < pw_req) 447 + pw_req = ret; 448 + } 449 + 450 + ret = pse_pi_allocate_pw_budget(pcdev, id, pw_req, extack); 451 + if (ret) 452 + return ret; 453 + 454 + ret = ops->pi_enable(pcdev, id); 455 + if (ret) { 456 + pse_pi_deallocate_pw_budget(pi); 457 + NL_SET_ERR_MSG_FMT(extack, 458 + "PI %d: enable error %d", 459 + id, ret); 460 + return ret; 461 + } 462 + 463 + return 0; 464 + } 465 + 437 466 static int pse_pi_enable(struct regulator_dev *rdev) 438 467 { 439 468 struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 440 469 const struct pse_controller_ops *ops; 441 - int id, ret; 470 + int id, ret = 0; 442 471 443 472 ops = pcdev->ops; 444 473 if (!ops->pi_enable) ··· 674 247 675 248 id = rdev_get_id(rdev); 676 249 mutex_lock(&pcdev->lock); 250 + if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) { 251 + /* Manage enabled status by software. 252 + * Real enable process will happen if a port is connected. 253 + */ 254 + if (pcdev->pi[id].isr_pd_detected) { 255 + struct netlink_ext_ack extack; 256 + 257 + ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, id, &extack); 258 + } 259 + if (!ret || ret == -ERANGE) { 260 + pcdev->pi[id].admin_state_enabled = 1; 261 + ret = 0; 262 + } 263 + mutex_unlock(&pcdev->lock); 264 + return ret; 265 + } 266 + 677 267 ret = ops->pi_enable(pcdev, id); 678 268 if (!ret) 679 269 pcdev->pi[id].admin_state_enabled = 1; ··· 702 258 static int pse_pi_disable(struct regulator_dev *rdev) 703 259 { 704 260 struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 705 - const struct pse_controller_ops *ops; 261 + struct pse_pi *pi; 706 262 int id, ret; 707 263 708 - ops = pcdev->ops; 709 - if (!ops->pi_disable) 710 - return -EOPNOTSUPP; 711 - 712 264 id = rdev_get_id(rdev); 265 + pi = &pcdev->pi[id]; 713 266 mutex_lock(&pcdev->lock); 714 - ret = ops->pi_disable(pcdev, id); 267 + ret = _pse_pi_disable(pcdev, id); 715 268 if (!ret) 716 - pcdev->pi[id].admin_state_enabled = 0; 717 - mutex_unlock(&pcdev->lock); 269 + pi->admin_state_enabled = 0; 718 270 719 - return ret; 271 + mutex_unlock(&pcdev->lock); 272 + return 0; 720 273 } 721 274 722 275 static int _pse_pi_get_voltage(struct regulator_dev *rdev) ··· 878 437 return 0; 879 438 } 880 439 440 + static void __pse_pw_d_release(struct kref *kref) 441 + { 442 + struct pse_power_domain *pw_d = container_of(kref, 443 + struct pse_power_domain, 444 + refcnt); 445 + 446 + regulator_put(pw_d->supply); 447 + xa_erase(&pse_pw_d_map, pw_d->id); 448 + mutex_unlock(&pse_pw_d_mutex); 449 + } 450 + 451 + /** 452 + * pse_flush_pw_ds - flush all PSE power domains of a PSE 453 + * @pcdev: a pointer to the initialized PSE controller device 454 + */ 455 + static void pse_flush_pw_ds(struct pse_controller_dev *pcdev) 456 + { 457 + struct pse_power_domain *pw_d; 458 + int i; 459 + 460 + for (i = 0; i < pcdev->nr_lines; i++) { 461 + if (!pcdev->pi[i].pw_d) 462 + continue; 463 + 464 + pw_d = xa_load(&pse_pw_d_map, pcdev->pi[i].pw_d->id); 465 + if (!pw_d) 466 + continue; 467 + 468 + kref_put_mutex(&pw_d->refcnt, __pse_pw_d_release, 469 + &pse_pw_d_mutex); 470 + } 471 + } 472 + 473 + /** 474 + * devm_pse_alloc_pw_d - allocate a new PSE power domain for a device 475 + * @dev: device that is registering this PSE power domain 476 + * 477 + * Return: Pointer to the newly allocated PSE power domain or error pointers 478 + */ 479 + static struct pse_power_domain *devm_pse_alloc_pw_d(struct device *dev) 480 + { 481 + struct pse_power_domain *pw_d; 482 + int index, ret; 483 + 484 + pw_d = devm_kzalloc(dev, sizeof(*pw_d), GFP_KERNEL); 485 + if (!pw_d) 486 + return ERR_PTR(-ENOMEM); 487 + 488 + ret = xa_alloc(&pse_pw_d_map, &index, pw_d, XA_LIMIT(1, PSE_PW_D_LIMIT), 489 + GFP_KERNEL); 490 + if (ret) 491 + return ERR_PTR(ret); 492 + 493 + kref_init(&pw_d->refcnt); 494 + pw_d->id = index; 495 + return pw_d; 496 + } 497 + 498 + /** 499 + * pse_register_pw_ds - register the PSE power domains for a PSE 500 + * @pcdev: a pointer to the PSE controller device 501 + * 502 + * Return: 0 on success and failure value on error 503 + */ 504 + static int pse_register_pw_ds(struct pse_controller_dev *pcdev) 505 + { 506 + int i, ret = 0; 507 + 508 + mutex_lock(&pse_pw_d_mutex); 509 + for (i = 0; i < pcdev->nr_lines; i++) { 510 + struct regulator_dev *rdev = pcdev->pi[i].rdev; 511 + struct pse_power_domain *pw_d; 512 + struct regulator *supply; 513 + bool present = false; 514 + unsigned long index; 515 + 516 + /* No regulator or regulator parent supply registered. 517 + * We need a regulator parent to register a PSE power domain 518 + */ 519 + if (!rdev || !rdev->supply) 520 + continue; 521 + 522 + xa_for_each(&pse_pw_d_map, index, pw_d) { 523 + /* Power supply already registered as a PSE power 524 + * domain. 525 + */ 526 + if (regulator_is_equal(pw_d->supply, rdev->supply)) { 527 + present = true; 528 + pcdev->pi[i].pw_d = pw_d; 529 + break; 530 + } 531 + } 532 + if (present) { 533 + kref_get(&pw_d->refcnt); 534 + continue; 535 + } 536 + 537 + pw_d = devm_pse_alloc_pw_d(pcdev->dev); 538 + if (IS_ERR(pw_d)) { 539 + ret = PTR_ERR(pw_d); 540 + goto out; 541 + } 542 + 543 + supply = regulator_get(&rdev->dev, rdev->supply_name); 544 + if (IS_ERR(supply)) { 545 + xa_erase(&pse_pw_d_map, pw_d->id); 546 + ret = PTR_ERR(supply); 547 + goto out; 548 + } 549 + 550 + pw_d->supply = supply; 551 + if (pcdev->supp_budget_eval_strategies) 552 + pw_d->budget_eval_strategy = pcdev->supp_budget_eval_strategies; 553 + else 554 + pw_d->budget_eval_strategy = PSE_BUDGET_EVAL_STRAT_DISABLED; 555 + kref_init(&pw_d->refcnt); 556 + pcdev->pi[i].pw_d = pw_d; 557 + } 558 + 559 + out: 560 + mutex_unlock(&pse_pw_d_mutex); 561 + return ret; 562 + } 563 + 564 + /** 565 + * pse_send_ntf_worker - Worker to send PSE notifications 566 + * @work: work object 567 + * 568 + * Manage and send PSE netlink notifications using a workqueue to avoid 569 + * deadlock between pcdev_lock and pse_list_mutex. 570 + */ 571 + static void pse_send_ntf_worker(struct work_struct *work) 572 + { 573 + struct pse_controller_dev *pcdev; 574 + struct pse_ntf ntf; 575 + 576 + pcdev = container_of(work, struct pse_controller_dev, ntf_work); 577 + 578 + while (kfifo_out(&pcdev->ntf_fifo, &ntf, 1)) { 579 + struct net_device *netdev; 580 + struct pse_control *psec; 581 + 582 + psec = pse_control_find_by_id(pcdev, ntf.id); 583 + rtnl_lock(); 584 + netdev = pse_control_get_netdev(psec); 585 + if (netdev) 586 + ethnl_pse_send_ntf(netdev, ntf.notifs); 587 + rtnl_unlock(); 588 + pse_control_put(psec); 589 + } 590 + } 591 + 881 592 /** 882 593 * pse_controller_register - register a PSE controller device 883 594 * @pcdev: a pointer to the initialized PSE controller device ··· 1043 450 1044 451 mutex_init(&pcdev->lock); 1045 452 INIT_LIST_HEAD(&pcdev->pse_control_head); 453 + spin_lock_init(&pcdev->ntf_fifo_lock); 454 + ret = kfifo_alloc(&pcdev->ntf_fifo, pcdev->nr_lines, GFP_KERNEL); 455 + if (ret) { 456 + dev_err(pcdev->dev, "failed to allocate kfifo notifications\n"); 457 + return ret; 458 + } 459 + INIT_WORK(&pcdev->ntf_work, pse_send_ntf_worker); 1046 460 1047 461 if (!pcdev->nr_lines) 1048 462 pcdev->nr_lines = 1; ··· 1096 496 return ret; 1097 497 } 1098 498 499 + ret = pse_register_pw_ds(pcdev); 500 + if (ret) 501 + return ret; 502 + 1099 503 mutex_lock(&pse_list_mutex); 1100 504 list_add(&pcdev->list, &pse_controller_list); 1101 505 mutex_unlock(&pse_list_mutex); ··· 1114 510 */ 1115 511 void pse_controller_unregister(struct pse_controller_dev *pcdev) 1116 512 { 513 + pse_flush_pw_ds(pcdev); 1117 514 pse_release_pis(pcdev); 515 + if (pcdev->irq) 516 + disable_irq(pcdev->irq); 517 + cancel_work_sync(&pcdev->ntf_work); 518 + kfifo_free(&pcdev->ntf_fifo); 1118 519 mutex_lock(&pse_list_mutex); 1119 520 list_del(&pcdev->list); 1120 521 mutex_unlock(&pse_list_mutex); ··· 1166 557 } 1167 558 EXPORT_SYMBOL_GPL(devm_pse_controller_register); 1168 559 560 + struct pse_irq { 561 + struct pse_controller_dev *pcdev; 562 + struct pse_irq_desc desc; 563 + unsigned long *notifs; 564 + }; 565 + 566 + /** 567 + * pse_to_regulator_notifs - Convert PSE notifications to Regulator 568 + * notifications 569 + * @notifs: PSE notifications 570 + * 571 + * Return: Regulator notifications 572 + */ 573 + static unsigned long pse_to_regulator_notifs(unsigned long notifs) 574 + { 575 + unsigned long rnotifs = 0; 576 + 577 + if (notifs & ETHTOOL_PSE_EVENT_OVER_CURRENT) 578 + rnotifs |= REGULATOR_EVENT_OVER_CURRENT; 579 + if (notifs & ETHTOOL_PSE_EVENT_OVER_TEMP) 580 + rnotifs |= REGULATOR_EVENT_OVER_TEMP; 581 + 582 + return rnotifs; 583 + } 584 + 585 + /** 586 + * pse_set_config_isr - Set PSE control config according to the PSE 587 + * notifications 588 + * @pcdev: a pointer to the PSE 589 + * @id: index of the PSE control 590 + * @notifs: PSE event notifications 591 + * 592 + * Return: 0 on success and failure value on error 593 + */ 594 + static int pse_set_config_isr(struct pse_controller_dev *pcdev, int id, 595 + unsigned long notifs) 596 + { 597 + int ret = 0; 598 + 599 + if (notifs & PSE_BUDGET_EVAL_STRAT_DYNAMIC) 600 + return 0; 601 + 602 + if ((notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) && 603 + ((notifs & ETHTOOL_C33_PSE_EVENT_DETECTION) || 604 + (notifs & ETHTOOL_C33_PSE_EVENT_CLASSIFICATION))) { 605 + dev_dbg(pcdev->dev, 606 + "PI %d: error, connection and disconnection reported simultaneously", 607 + id); 608 + return -EINVAL; 609 + } 610 + 611 + if (notifs & ETHTOOL_C33_PSE_EVENT_CLASSIFICATION) { 612 + struct netlink_ext_ack extack; 613 + 614 + pcdev->pi[id].isr_pd_detected = true; 615 + if (pcdev->pi[id].admin_state_enabled) { 616 + ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, id, 617 + &extack); 618 + if (ret == -ERANGE) 619 + ret = 0; 620 + } 621 + } else if (notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) { 622 + if (pcdev->pi[id].admin_state_enabled && 623 + pcdev->pi[id].isr_pd_detected) 624 + ret = _pse_pi_disable(pcdev, id); 625 + pcdev->pi[id].isr_pd_detected = false; 626 + } 627 + 628 + return ret; 629 + } 630 + 631 + /** 632 + * pse_isr - IRQ handler for PSE 633 + * @irq: irq number 634 + * @data: pointer to user interrupt structure 635 + * 636 + * Return: irqreturn_t - status of IRQ 637 + */ 638 + static irqreturn_t pse_isr(int irq, void *data) 639 + { 640 + struct pse_controller_dev *pcdev; 641 + unsigned long notifs_mask = 0; 642 + struct pse_irq_desc *desc; 643 + struct pse_irq *h = data; 644 + int ret, i; 645 + 646 + desc = &h->desc; 647 + pcdev = h->pcdev; 648 + 649 + /* Clear notifs mask */ 650 + memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs)); 651 + mutex_lock(&pcdev->lock); 652 + ret = desc->map_event(irq, pcdev, h->notifs, &notifs_mask); 653 + if (ret || !notifs_mask) { 654 + mutex_unlock(&pcdev->lock); 655 + return IRQ_NONE; 656 + } 657 + 658 + for_each_set_bit(i, &notifs_mask, pcdev->nr_lines) { 659 + unsigned long notifs, rnotifs; 660 + struct pse_ntf ntf = {}; 661 + 662 + /* Do nothing PI not described */ 663 + if (!pcdev->pi[i].rdev) 664 + continue; 665 + 666 + notifs = h->notifs[i]; 667 + if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[i].pw_d)) { 668 + ret = pse_set_config_isr(pcdev, i, notifs); 669 + if (ret) 670 + notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR; 671 + } 672 + 673 + dev_dbg(h->pcdev->dev, 674 + "Sending PSE notification EVT 0x%lx\n", notifs); 675 + 676 + ntf.notifs = notifs; 677 + ntf.id = i; 678 + kfifo_in_spinlocked(&pcdev->ntf_fifo, &ntf, 1, 679 + &pcdev->ntf_fifo_lock); 680 + schedule_work(&pcdev->ntf_work); 681 + 682 + rnotifs = pse_to_regulator_notifs(notifs); 683 + regulator_notifier_call_chain(pcdev->pi[i].rdev, rnotifs, 684 + NULL); 685 + } 686 + 687 + mutex_unlock(&pcdev->lock); 688 + 689 + return IRQ_HANDLED; 690 + } 691 + 692 + /** 693 + * devm_pse_irq_helper - Register IRQ based PSE event notifier 694 + * @pcdev: a pointer to the PSE 695 + * @irq: the irq value to be passed to request_irq 696 + * @irq_flags: the flags to be passed to request_irq 697 + * @d: PSE interrupt description 698 + * 699 + * Return: 0 on success and errno on failure 700 + */ 701 + int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq, 702 + int irq_flags, const struct pse_irq_desc *d) 703 + { 704 + struct device *dev = pcdev->dev; 705 + size_t irq_name_len; 706 + struct pse_irq *h; 707 + char *irq_name; 708 + int ret; 709 + 710 + if (!d || !d->map_event || !d->name) 711 + return -EINVAL; 712 + 713 + h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); 714 + if (!h) 715 + return -ENOMEM; 716 + 717 + h->pcdev = pcdev; 718 + h->desc = *d; 719 + 720 + /* IRQ name len is pcdev dev name + 5 char + irq desc name + 1 */ 721 + irq_name_len = strlen(dev_name(pcdev->dev)) + 5 + strlen(d->name) + 1; 722 + irq_name = devm_kzalloc(dev, irq_name_len, GFP_KERNEL); 723 + if (!irq_name) 724 + return -ENOMEM; 725 + 726 + snprintf(irq_name, irq_name_len, "pse-%s:%s", dev_name(pcdev->dev), 727 + d->name); 728 + 729 + h->notifs = devm_kcalloc(dev, pcdev->nr_lines, 730 + sizeof(*h->notifs), GFP_KERNEL); 731 + if (!h->notifs) 732 + return -ENOMEM; 733 + 734 + ret = devm_request_threaded_irq(dev, irq, NULL, pse_isr, 735 + IRQF_ONESHOT | irq_flags, 736 + irq_name, h); 737 + if (ret) 738 + dev_err(pcdev->dev, "Failed to request IRQ %d\n", irq); 739 + 740 + pcdev->irq = irq; 741 + return ret; 742 + } 743 + EXPORT_SYMBOL_GPL(devm_pse_irq_helper); 744 + 1169 745 /* PSE control section */ 1170 746 1171 747 static void __pse_control_release(struct kref *kref) ··· 1393 599 EXPORT_SYMBOL_GPL(pse_control_put); 1394 600 1395 601 static struct pse_control * 1396 - pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index) 602 + pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index, 603 + struct phy_device *phydev) 1397 604 { 1398 605 struct pse_control *psec; 1399 606 int ret; ··· 1417 622 goto free_psec; 1418 623 } 1419 624 625 + if (!pcdev->ops->pi_get_admin_state) { 626 + ret = -EOPNOTSUPP; 627 + goto free_psec; 628 + } 629 + 630 + /* Initialize admin_state_enabled before the regulator_get. This 631 + * aims to have the right value reported in the first is_enabled 632 + * call in case of control managed by software. 633 + */ 634 + ret = pse_pi_is_hw_enabled(pcdev, index); 635 + if (ret < 0) 636 + goto free_psec; 637 + 638 + pcdev->pi[index].admin_state_enabled = ret; 1420 639 psec->ps = devm_regulator_get_exclusive(pcdev->dev, 1421 640 rdev_get_name(pcdev->pi[index].rdev)); 1422 641 if (IS_ERR(psec->ps)) { ··· 1438 629 goto put_module; 1439 630 } 1440 631 1441 - ret = regulator_is_enabled(psec->ps); 1442 - if (ret < 0) 1443 - goto regulator_put; 1444 - 1445 - pcdev->pi[index].admin_state_enabled = ret; 1446 - 1447 632 psec->pcdev = pcdev; 1448 633 list_add(&psec->list, &pcdev->pse_control_head); 1449 634 psec->id = index; 635 + psec->attached_phydev = phydev; 1450 636 kref_init(&psec->refcnt); 1451 637 1452 638 return psec; 1453 639 1454 - regulator_put: 1455 - devm_regulator_put(psec->ps); 1456 640 put_module: 1457 641 module_put(pcdev->owner); 1458 642 free_psec: ··· 1495 693 return pse_spec->args[0]; 1496 694 } 1497 695 1498 - struct pse_control *of_pse_control_get(struct device_node *node) 696 + struct pse_control *of_pse_control_get(struct device_node *node, 697 + struct phy_device *phydev) 1499 698 { 1500 699 struct pse_controller_dev *r, *pcdev; 1501 700 struct of_phandle_args args; ··· 1546 743 } 1547 744 1548 745 /* pse_list_mutex also protects the pcdev's pse_control list */ 1549 - psec = pse_control_get_internal(pcdev, psec_id); 746 + psec = pse_control_get_internal(pcdev, psec_id, phydev); 1550 747 1551 748 out: 1552 749 mutex_unlock(&pse_list_mutex); ··· 1555 752 return psec; 1556 753 } 1557 754 EXPORT_SYMBOL_GPL(of_pse_control_get); 755 + 756 + /** 757 + * pse_get_sw_admin_state - Convert the software admin state to c33 or podl 758 + * admin state value used in the standard 759 + * @psec: PSE control pointer 760 + * @admin_state: a pointer to the admin_state structure 761 + */ 762 + static void pse_get_sw_admin_state(struct pse_control *psec, 763 + struct pse_admin_state *admin_state) 764 + { 765 + struct pse_pi *pi = &psec->pcdev->pi[psec->id]; 766 + 767 + if (pse_has_podl(psec)) { 768 + if (pi->admin_state_enabled) 769 + admin_state->podl_admin_state = 770 + ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED; 771 + else 772 + admin_state->podl_admin_state = 773 + ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED; 774 + } 775 + if (pse_has_c33(psec)) { 776 + if (pi->admin_state_enabled) 777 + admin_state->c33_admin_state = 778 + ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; 779 + else 780 + admin_state->c33_admin_state = 781 + ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; 782 + } 783 + } 1558 784 1559 785 /** 1560 786 * pse_ethtool_get_status - get status of PSE control ··· 1601 769 struct pse_pw_status pw_status = {0}; 1602 770 const struct pse_controller_ops *ops; 1603 771 struct pse_controller_dev *pcdev; 772 + struct pse_pi *pi; 1604 773 int ret; 1605 774 1606 775 pcdev = psec->pcdev; 1607 776 ops = pcdev->ops; 777 + 778 + pi = &pcdev->pi[psec->id]; 1608 779 mutex_lock(&pcdev->lock); 1609 - ret = ops->pi_get_admin_state(pcdev, psec->id, &admin_state); 1610 - if (ret) 1611 - goto out; 1612 - status->podl_admin_state = admin_state.podl_admin_state; 1613 - status->c33_admin_state = admin_state.c33_admin_state; 780 + if (pi->pw_d) { 781 + status->pw_d_id = pi->pw_d->id; 782 + if (pse_pw_d_is_sw_pw_control(pcdev, pi->pw_d)) { 783 + pse_get_sw_admin_state(psec, &admin_state); 784 + } else { 785 + ret = ops->pi_get_admin_state(pcdev, psec->id, 786 + &admin_state); 787 + if (ret) 788 + goto out; 789 + } 790 + status->podl_admin_state = admin_state.podl_admin_state; 791 + status->c33_admin_state = admin_state.c33_admin_state; 792 + 793 + switch (pi->pw_d->budget_eval_strategy) { 794 + case PSE_BUDGET_EVAL_STRAT_STATIC: 795 + status->prio_max = pcdev->nr_lines - 1; 796 + status->prio = pi->prio; 797 + break; 798 + case PSE_BUDGET_EVAL_STRAT_DYNAMIC: 799 + status->prio_max = pcdev->pis_prio_max; 800 + if (ops->pi_get_prio) { 801 + ret = ops->pi_get_prio(pcdev, psec->id); 802 + if (ret < 0) 803 + goto out; 804 + 805 + status->prio = ret; 806 + } 807 + break; 808 + default: 809 + break; 810 + } 811 + } 1614 812 1615 813 ret = ops->pi_get_pw_status(pcdev, psec->id, &pw_status); 1616 814 if (ret) ··· 1790 928 EXPORT_SYMBOL_GPL(pse_ethtool_set_config); 1791 929 1792 930 /** 931 + * pse_pi_update_pw_budget - Update PSE power budget allocated with new 932 + * power in mW 933 + * @pcdev: a pointer to the PSE controller device 934 + * @id: index of the PSE PI 935 + * @pw_req: power requested 936 + * @extack: extack for reporting useful error messages 937 + * 938 + * Return: Previous power allocated on success and failure value on error 939 + */ 940 + static int pse_pi_update_pw_budget(struct pse_controller_dev *pcdev, int id, 941 + const unsigned int pw_req, 942 + struct netlink_ext_ack *extack) 943 + { 944 + struct pse_pi *pi = &pcdev->pi[id]; 945 + int previous_pw_allocated; 946 + int pw_diff, ret = 0; 947 + 948 + /* We don't want pw_allocated_mW value change in the middle of an 949 + * power budget update 950 + */ 951 + mutex_lock(&pcdev->lock); 952 + previous_pw_allocated = pi->pw_allocated_mW; 953 + pw_diff = pw_req - previous_pw_allocated; 954 + if (!pw_diff) { 955 + goto out; 956 + } else if (pw_diff > 0) { 957 + ret = regulator_request_power_budget(pi->pw_d->supply, pw_diff); 958 + if (ret) { 959 + NL_SET_ERR_MSG_FMT(extack, 960 + "PI %d: not enough power budget available", 961 + id); 962 + goto out; 963 + } 964 + 965 + } else { 966 + regulator_free_power_budget(pi->pw_d->supply, -pw_diff); 967 + } 968 + pi->pw_allocated_mW = pw_req; 969 + ret = previous_pw_allocated; 970 + 971 + out: 972 + mutex_unlock(&pcdev->lock); 973 + return ret; 974 + } 975 + 976 + /** 1793 977 * pse_ethtool_set_pw_limit - set PSE control power limit 1794 978 * @psec: PSE control pointer 1795 979 * @extack: extack for reporting useful error messages ··· 1847 939 struct netlink_ext_ack *extack, 1848 940 const unsigned int pw_limit) 1849 941 { 1850 - int uV, uA, ret; 942 + int uV, uA, ret, previous_pw_allocated = 0; 1851 943 s64 tmp_64; 1852 944 1853 945 if (pw_limit > MAX_PI_PW) ··· 1871 963 /* uA = mW * 1000000000 / uV */ 1872 964 uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV); 1873 965 1874 - return regulator_set_current_limit(psec->ps, 0, uA); 966 + /* Update power budget only in software power control case and 967 + * if a Power Device is powered. 968 + */ 969 + if (pse_pw_d_is_sw_pw_control(psec->pcdev, 970 + psec->pcdev->pi[psec->id].pw_d) && 971 + psec->pcdev->pi[psec->id].admin_state_enabled && 972 + psec->pcdev->pi[psec->id].isr_pd_detected) { 973 + ret = pse_pi_update_pw_budget(psec->pcdev, psec->id, 974 + pw_limit, extack); 975 + if (ret < 0) 976 + return ret; 977 + previous_pw_allocated = ret; 978 + } 979 + 980 + ret = regulator_set_current_limit(psec->ps, 0, uA); 981 + if (ret < 0 && previous_pw_allocated) { 982 + pse_pi_update_pw_budget(psec->pcdev, psec->id, 983 + previous_pw_allocated, extack); 984 + } 985 + 986 + return ret; 1875 987 } 1876 988 EXPORT_SYMBOL_GPL(pse_ethtool_set_pw_limit); 989 + 990 + /** 991 + * pse_ethtool_set_prio - Set PSE PI priority according to the budget 992 + * evaluation strategy 993 + * @psec: PSE control pointer 994 + * @extack: extack for reporting useful error messages 995 + * @prio: priovity value 996 + * 997 + * Return: 0 on success and failure value on error 998 + */ 999 + int pse_ethtool_set_prio(struct pse_control *psec, 1000 + struct netlink_ext_ack *extack, 1001 + unsigned int prio) 1002 + { 1003 + struct pse_controller_dev *pcdev = psec->pcdev; 1004 + const struct pse_controller_ops *ops; 1005 + int ret = 0; 1006 + 1007 + if (!pcdev->pi[psec->id].pw_d) { 1008 + NL_SET_ERR_MSG(extack, "no power domain attached"); 1009 + return -EOPNOTSUPP; 1010 + } 1011 + 1012 + /* We don't want priority change in the middle of an 1013 + * enable/disable call or a priority mode change 1014 + */ 1015 + mutex_lock(&pcdev->lock); 1016 + switch (pcdev->pi[psec->id].pw_d->budget_eval_strategy) { 1017 + case PSE_BUDGET_EVAL_STRAT_STATIC: 1018 + if (prio >= pcdev->nr_lines) { 1019 + NL_SET_ERR_MSG_FMT(extack, 1020 + "priority %d exceed priority max %d", 1021 + prio, pcdev->nr_lines); 1022 + ret = -ERANGE; 1023 + goto out; 1024 + } 1025 + 1026 + pcdev->pi[psec->id].prio = prio; 1027 + pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[psec->id].pw_d); 1028 + break; 1029 + 1030 + case PSE_BUDGET_EVAL_STRAT_DYNAMIC: 1031 + ops = psec->pcdev->ops; 1032 + if (!ops->pi_set_prio) { 1033 + NL_SET_ERR_MSG(extack, 1034 + "pse driver does not support setting port priority"); 1035 + ret = -EOPNOTSUPP; 1036 + goto out; 1037 + } 1038 + 1039 + if (prio > pcdev->pis_prio_max) { 1040 + NL_SET_ERR_MSG_FMT(extack, 1041 + "priority %d exceed priority max %d", 1042 + prio, pcdev->pis_prio_max); 1043 + ret = -ERANGE; 1044 + goto out; 1045 + } 1046 + 1047 + ret = ops->pi_set_prio(pcdev, psec->id, prio); 1048 + break; 1049 + 1050 + default: 1051 + ret = -EOPNOTSUPP; 1052 + } 1053 + 1054 + out: 1055 + mutex_unlock(&pcdev->lock); 1056 + return ret; 1057 + } 1058 + EXPORT_SYMBOL_GPL(pse_ethtool_set_prio); 1877 1059 1878 1060 bool pse_has_podl(struct pse_control *psec) 1879 1061 {
+399 -2
drivers/net/pse-pd/tps23881.c
··· 16 16 #include <linux/pse-pd/pse.h> 17 17 18 18 #define TPS23881_MAX_CHANS 8 19 + #define TPS23881_MAX_IRQ_RETRIES 10 19 20 21 + #define TPS23881_REG_IT 0x0 22 + #define TPS23881_REG_IT_MASK 0x1 23 + #define TPS23881_REG_IT_DISF BIT(2) 24 + #define TPS23881_REG_IT_DETC BIT(3) 25 + #define TPS23881_REG_IT_CLASC BIT(4) 26 + #define TPS23881_REG_IT_IFAULT BIT(5) 27 + #define TPS23881_REG_IT_SUPF BIT(7) 28 + #define TPS23881_REG_DET_EVENT 0x5 29 + #define TPS23881_REG_FAULT 0x7 30 + #define TPS23881_REG_SUPF_EVENT 0xb 31 + #define TPS23881_REG_TSD BIT(7) 32 + #define TPS23881_REG_DISC 0xc 20 33 #define TPS23881_REG_PW_STATUS 0x10 21 34 #define TPS23881_REG_OP_MODE 0x12 35 + #define TPS23881_REG_DISC_EN 0x13 22 36 #define TPS23881_OP_MODE_SEMIAUTO 0xaaaa 23 37 #define TPS23881_REG_DIS_EN 0x13 24 38 #define TPS23881_REG_DET_CLA_EN 0x14 25 39 #define TPS23881_REG_GEN_MASK 0x17 40 + #define TPS23881_REG_CLCHE BIT(2) 41 + #define TPS23881_REG_DECHE BIT(3) 26 42 #define TPS23881_REG_NBITACC BIT(5) 43 + #define TPS23881_REG_INTEN BIT(7) 27 44 #define TPS23881_REG_PW_EN 0x19 45 + #define TPS23881_REG_RESET 0x1a 46 + #define TPS23881_REG_CLRAIN BIT(7) 28 47 #define TPS23881_REG_2PAIR_POL1 0x1e 29 48 #define TPS23881_REG_PORT_MAP 0x26 30 49 #define TPS23881_REG_PORT_POWER 0x29 ··· 70 51 u8 chan[2]; 71 52 bool is_4p; 72 53 int pw_pol; 54 + bool exist; 73 55 }; 74 56 75 57 struct tps23881_priv { ··· 188 168 struct i2c_client *client = priv->client; 189 169 u8 chan; 190 170 u16 val; 171 + int ret; 191 172 192 173 if (id >= TPS23881_MAX_CHANS) 193 174 return -ERANGE; ··· 202 181 BIT(chan % 4)); 203 182 } 204 183 205 - return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); 184 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); 185 + if (ret) 186 + return ret; 187 + 188 + /* Enable DC disconnect*/ 189 + chan = priv->port[id].chan[0]; 190 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_DISC_EN); 191 + if (ret < 0) 192 + return ret; 193 + 194 + val = tps23881_set_val(ret, chan, 0, BIT(chan % 4), BIT(chan % 4)); 195 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_DISC_EN, val); 196 + if (ret) 197 + return ret; 198 + 199 + return 0; 206 200 } 207 201 208 202 static int tps23881_pi_disable(struct pse_controller_dev *pcdev, int id) ··· 249 213 * of 5ms after PWOFFn command for all register values to be updated" 250 214 */ 251 215 mdelay(5); 216 + 217 + /* Disable DC disconnect*/ 218 + chan = priv->port[id].chan[0]; 219 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_DISC_EN); 220 + if (ret < 0) 221 + return ret; 222 + 223 + val = tps23881_set_val(ret, chan, 0, 0, BIT(chan % 4)); 224 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_DISC_EN, val); 225 + if (ret) 226 + return ret; 252 227 253 228 /* Enable detection and classification */ 254 229 ret = i2c_smbus_read_word_data(client, TPS23881_REG_DET_CLA_EN); ··· 829 782 hw_chan = port_matrix[i].hw_chan[0] % 4; 830 783 831 784 /* Set software port matrix for existing ports */ 832 - if (port_matrix[i].exist) 785 + if (port_matrix[i].exist) { 833 786 priv->port[pi_id].chan[0] = lgcl_chan; 787 + priv->port[pi_id].exist = true; 788 + } 834 789 835 790 /* Initialize power policy internal value */ 836 791 priv->port[pi_id].pw_pol = -1; ··· 956 907 return ret; 957 908 } 958 909 910 + static int tps23881_power_class_table[] = { 911 + -ERANGE, 912 + 4000, 913 + 7000, 914 + 15500, 915 + 30000, 916 + 15500, 917 + 15500, 918 + -ERANGE, 919 + 45000, 920 + 60000, 921 + 75000, 922 + 90000, 923 + 15500, 924 + 45000, 925 + -ERANGE, 926 + -ERANGE, 927 + }; 928 + 929 + static int tps23881_pi_get_pw_req(struct pse_controller_dev *pcdev, int id) 930 + { 931 + struct tps23881_priv *priv = to_tps23881_priv(pcdev); 932 + struct i2c_client *client = priv->client; 933 + u8 reg, chan; 934 + int ret; 935 + u16 val; 936 + 937 + /* For a 4-pair the classification need 5ms to be completed */ 938 + if (priv->port[id].is_4p) 939 + mdelay(5); 940 + 941 + chan = priv->port[id].chan[0]; 942 + reg = TPS23881_REG_DISC + (chan % 4); 943 + ret = i2c_smbus_read_word_data(client, reg); 944 + if (ret < 0) 945 + return ret; 946 + 947 + val = tps23881_calc_val(ret, chan, 4, 0xf); 948 + return tps23881_power_class_table[val]; 949 + } 950 + 959 951 static const struct pse_controller_ops tps23881_ops = { 960 952 .setup_pi_matrix = tps23881_setup_pi_matrix, 961 953 .pi_enable = tps23881_pi_enable, ··· 1009 919 .pi_get_pw_limit = tps23881_pi_get_pw_limit, 1010 920 .pi_set_pw_limit = tps23881_pi_set_pw_limit, 1011 921 .pi_get_pw_limit_ranges = tps23881_pi_get_pw_limit_ranges, 922 + .pi_get_pw_req = tps23881_pi_get_pw_req, 1012 923 }; 1013 924 1014 925 static const char fw_parity_name[] = "ti/tps23881/tps23881-parity-14.bin"; ··· 1108 1017 return 0; 1109 1018 } 1110 1019 1020 + /* Convert interrupt events to 0xff to be aligned with the chan 1021 + * number. 1022 + */ 1023 + static u8 tps23881_irq_export_chans_helper(u16 reg_val, u8 field_offset) 1024 + { 1025 + u8 val; 1026 + 1027 + val = (reg_val >> (4 + field_offset) & 0xf0) | 1028 + (reg_val >> field_offset & 0x0f); 1029 + 1030 + return val; 1031 + } 1032 + 1033 + /* Convert chan number to port number */ 1034 + static void tps23881_set_notifs_helper(struct tps23881_priv *priv, 1035 + u8 chans, 1036 + unsigned long *notifs, 1037 + unsigned long *notifs_mask, 1038 + enum ethtool_pse_event event) 1039 + { 1040 + u8 chan; 1041 + int i; 1042 + 1043 + if (!chans) 1044 + return; 1045 + 1046 + for (i = 0; i < TPS23881_MAX_CHANS; i++) { 1047 + if (!priv->port[i].exist) 1048 + continue; 1049 + /* No need to look at the 2nd channel in case of PoE4 as 1050 + * both registers are set. 1051 + */ 1052 + chan = priv->port[i].chan[0]; 1053 + 1054 + if (BIT(chan) & chans) { 1055 + *notifs_mask |= BIT(i); 1056 + notifs[i] |= event; 1057 + } 1058 + } 1059 + } 1060 + 1061 + static void tps23881_irq_event_over_temp(struct tps23881_priv *priv, 1062 + u16 reg_val, 1063 + unsigned long *notifs, 1064 + unsigned long *notifs_mask) 1065 + { 1066 + int i; 1067 + 1068 + if (reg_val & TPS23881_REG_TSD) { 1069 + for (i = 0; i < TPS23881_MAX_CHANS; i++) { 1070 + if (!priv->port[i].exist) 1071 + continue; 1072 + 1073 + *notifs_mask |= BIT(i); 1074 + notifs[i] |= ETHTOOL_PSE_EVENT_OVER_TEMP; 1075 + } 1076 + } 1077 + } 1078 + 1079 + static int tps23881_irq_event_over_current(struct tps23881_priv *priv, 1080 + u16 reg_val, 1081 + unsigned long *notifs, 1082 + unsigned long *notifs_mask) 1083 + { 1084 + int i, ret; 1085 + u8 chans; 1086 + 1087 + chans = tps23881_irq_export_chans_helper(reg_val, 0); 1088 + if (!chans) 1089 + return 0; 1090 + 1091 + tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, 1092 + ETHTOOL_PSE_EVENT_OVER_CURRENT | 1093 + ETHTOOL_C33_PSE_EVENT_DISCONNECTION); 1094 + 1095 + /* Over Current event resets the power limit registers so we need 1096 + * to configured it again. 1097 + */ 1098 + for_each_set_bit(i, notifs_mask, priv->pcdev.nr_lines) { 1099 + if (priv->port[i].pw_pol < 0) 1100 + continue; 1101 + 1102 + ret = tps23881_pi_enable_manual_pol(priv, i); 1103 + if (ret < 0) 1104 + return ret; 1105 + 1106 + /* Set power policy */ 1107 + ret = tps23881_pi_set_pw_pol_limit(priv, i, 1108 + priv->port[i].pw_pol, 1109 + priv->port[i].is_4p); 1110 + if (ret < 0) 1111 + return ret; 1112 + } 1113 + 1114 + return 0; 1115 + } 1116 + 1117 + static void tps23881_irq_event_disconnection(struct tps23881_priv *priv, 1118 + u16 reg_val, 1119 + unsigned long *notifs, 1120 + unsigned long *notifs_mask) 1121 + { 1122 + u8 chans; 1123 + 1124 + chans = tps23881_irq_export_chans_helper(reg_val, 4); 1125 + if (chans) 1126 + tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, 1127 + ETHTOOL_C33_PSE_EVENT_DISCONNECTION); 1128 + } 1129 + 1130 + static int tps23881_irq_event_detection(struct tps23881_priv *priv, 1131 + u16 reg_val, 1132 + unsigned long *notifs, 1133 + unsigned long *notifs_mask) 1134 + { 1135 + enum ethtool_pse_event event; 1136 + int reg, ret, i, val; 1137 + unsigned long chans; 1138 + 1139 + chans = tps23881_irq_export_chans_helper(reg_val, 0); 1140 + for_each_set_bit(i, &chans, TPS23881_MAX_CHANS) { 1141 + reg = TPS23881_REG_DISC + (i % 4); 1142 + ret = i2c_smbus_read_word_data(priv->client, reg); 1143 + if (ret < 0) 1144 + return ret; 1145 + 1146 + val = tps23881_calc_val(ret, i, 0, 0xf); 1147 + /* If detection valid */ 1148 + if (val == 0x4) 1149 + event = ETHTOOL_C33_PSE_EVENT_DETECTION; 1150 + else 1151 + event = ETHTOOL_C33_PSE_EVENT_DISCONNECTION; 1152 + 1153 + tps23881_set_notifs_helper(priv, BIT(i), notifs, 1154 + notifs_mask, event); 1155 + } 1156 + 1157 + return 0; 1158 + } 1159 + 1160 + static int tps23881_irq_event_classification(struct tps23881_priv *priv, 1161 + u16 reg_val, 1162 + unsigned long *notifs, 1163 + unsigned long *notifs_mask) 1164 + { 1165 + int reg, ret, val, i; 1166 + unsigned long chans; 1167 + 1168 + chans = tps23881_irq_export_chans_helper(reg_val, 4); 1169 + for_each_set_bit(i, &chans, TPS23881_MAX_CHANS) { 1170 + reg = TPS23881_REG_DISC + (i % 4); 1171 + ret = i2c_smbus_read_word_data(priv->client, reg); 1172 + if (ret < 0) 1173 + return ret; 1174 + 1175 + val = tps23881_calc_val(ret, i, 4, 0xf); 1176 + /* Do not report classification event for unknown class */ 1177 + if (!val || val == 0x8 || val == 0xf) 1178 + continue; 1179 + 1180 + tps23881_set_notifs_helper(priv, BIT(i), notifs, 1181 + notifs_mask, 1182 + ETHTOOL_C33_PSE_EVENT_CLASSIFICATION); 1183 + } 1184 + 1185 + return 0; 1186 + } 1187 + 1188 + static int tps23881_irq_event_handler(struct tps23881_priv *priv, u16 reg, 1189 + unsigned long *notifs, 1190 + unsigned long *notifs_mask) 1191 + { 1192 + struct i2c_client *client = priv->client; 1193 + int ret, val; 1194 + 1195 + /* The Supply event bit is repeated twice so we only need to read 1196 + * the one from the first byte. 1197 + */ 1198 + if (reg & TPS23881_REG_IT_SUPF) { 1199 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_SUPF_EVENT); 1200 + if (ret < 0) 1201 + return ret; 1202 + tps23881_irq_event_over_temp(priv, ret, notifs, notifs_mask); 1203 + } 1204 + 1205 + if (reg & (TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_IFAULT << 8 | 1206 + TPS23881_REG_IT_DISF | TPS23881_REG_IT_DISF << 8)) { 1207 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_FAULT); 1208 + if (ret < 0) 1209 + return ret; 1210 + ret = tps23881_irq_event_over_current(priv, ret, notifs, 1211 + notifs_mask); 1212 + if (ret) 1213 + return ret; 1214 + 1215 + tps23881_irq_event_disconnection(priv, ret, notifs, notifs_mask); 1216 + } 1217 + 1218 + if (reg & (TPS23881_REG_IT_DETC | TPS23881_REG_IT_DETC << 8 | 1219 + TPS23881_REG_IT_CLASC | TPS23881_REG_IT_CLASC << 8)) { 1220 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_DET_EVENT); 1221 + if (ret < 0) 1222 + return ret; 1223 + 1224 + val = ret; 1225 + ret = tps23881_irq_event_detection(priv, val, notifs, 1226 + notifs_mask); 1227 + if (ret) 1228 + return ret; 1229 + 1230 + ret = tps23881_irq_event_classification(priv, val, notifs, 1231 + notifs_mask); 1232 + if (ret) 1233 + return ret; 1234 + } 1235 + return 0; 1236 + } 1237 + 1238 + static int tps23881_irq_handler(int irq, struct pse_controller_dev *pcdev, 1239 + unsigned long *notifs, 1240 + unsigned long *notifs_mask) 1241 + { 1242 + struct tps23881_priv *priv = to_tps23881_priv(pcdev); 1243 + struct i2c_client *client = priv->client; 1244 + int ret, it_mask, retry; 1245 + 1246 + /* Get interruption mask */ 1247 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT_MASK); 1248 + if (ret < 0) 1249 + return ret; 1250 + it_mask = ret; 1251 + 1252 + /* Read interrupt register until it frees the interruption pin. */ 1253 + retry = 0; 1254 + while (true) { 1255 + if (retry > TPS23881_MAX_IRQ_RETRIES) { 1256 + dev_err(&client->dev, "interrupt never freed"); 1257 + return -ETIMEDOUT; 1258 + } 1259 + 1260 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT); 1261 + if (ret < 0) 1262 + return ret; 1263 + 1264 + /* No more relevant interruption */ 1265 + if (!(ret & it_mask)) 1266 + return 0; 1267 + 1268 + ret = tps23881_irq_event_handler(priv, (u16)ret, notifs, 1269 + notifs_mask); 1270 + if (ret) 1271 + return ret; 1272 + 1273 + retry++; 1274 + } 1275 + return 0; 1276 + } 1277 + 1278 + static int tps23881_setup_irq(struct tps23881_priv *priv, int irq) 1279 + { 1280 + struct i2c_client *client = priv->client; 1281 + struct pse_irq_desc irq_desc = { 1282 + .name = "tps23881-irq", 1283 + .map_event = tps23881_irq_handler, 1284 + }; 1285 + int ret; 1286 + u16 val; 1287 + 1288 + if (!irq) { 1289 + dev_err(&client->dev, "interrupt is missing"); 1290 + return -EINVAL; 1291 + } 1292 + 1293 + val = TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_SUPF | 1294 + TPS23881_REG_IT_DETC | TPS23881_REG_IT_CLASC | 1295 + TPS23881_REG_IT_DISF; 1296 + val |= val << 8; 1297 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_IT_MASK, val); 1298 + if (ret) 1299 + return ret; 1300 + 1301 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_GEN_MASK); 1302 + if (ret < 0) 1303 + return ret; 1304 + 1305 + val = TPS23881_REG_INTEN | TPS23881_REG_CLCHE | TPS23881_REG_DECHE; 1306 + val |= val << 8; 1307 + val |= (u16)ret; 1308 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_GEN_MASK, val); 1309 + if (ret < 0) 1310 + return ret; 1311 + 1312 + /* Reset interrupts registers */ 1313 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_RESET, 1314 + TPS23881_REG_CLRAIN); 1315 + if (ret < 0) 1316 + return ret; 1317 + 1318 + return devm_pse_irq_helper(&priv->pcdev, irq, 0, &irq_desc); 1319 + } 1320 + 1111 1321 static int tps23881_i2c_probe(struct i2c_client *client) 1112 1322 { 1113 1323 struct device *dev = &client->dev; ··· 1483 1091 priv->pcdev.dev = dev; 1484 1092 priv->pcdev.types = ETHTOOL_PSE_C33; 1485 1093 priv->pcdev.nr_lines = TPS23881_MAX_CHANS; 1094 + priv->pcdev.supp_budget_eval_strategies = PSE_BUDGET_EVAL_STRAT_STATIC; 1486 1095 ret = devm_pse_controller_register(dev, &priv->pcdev); 1487 1096 if (ret) { 1488 1097 return dev_err_probe(dev, ret, 1489 1098 "failed to register PSE controller\n"); 1490 1099 } 1100 + 1101 + ret = tps23881_setup_irq(priv, client->irq); 1102 + if (ret) 1103 + return ret; 1491 1104 1492 1105 return ret; 1493 1106 }
+7
include/linux/ethtool_netlink.h
··· 43 43 struct ethtool_rmon_stats *rmon_stats); 44 44 bool ethtool_dev_mm_supported(struct net_device *dev); 45 45 46 + void ethnl_pse_send_ntf(struct net_device *netdev, unsigned long notif); 47 + 46 48 #else 47 49 static inline int ethnl_cable_test_alloc(struct phy_device *phydev, u8 cmd) 48 50 { ··· 120 118 static inline bool ethtool_dev_mm_supported(struct net_device *dev) 121 119 { 122 120 return false; 121 + } 122 + 123 + static inline void ethnl_pse_send_ntf(struct phy_device *phydev, 124 + unsigned long notif) 125 + { 123 126 } 124 127 125 128 #endif /* IS_ENABLED(CONFIG_ETHTOOL_NETLINK) */
+104 -2
include/linux/pse-pd/pse.h
··· 6 6 #define _LINUX_PSE_CONTROLLER_H 7 7 8 8 #include <linux/list.h> 9 + #include <linux/netlink.h> 10 + #include <linux/kfifo.h> 9 11 #include <uapi/linux/ethtool.h> 12 + #include <uapi/linux/ethtool_netlink_generated.h> 13 + #include <linux/regulator/driver.h> 10 14 11 15 /* Maximum current in uA according to IEEE 802.3-2022 Table 145-1 */ 12 16 #define MAX_PI_CURRENT 1920000 13 17 /* Maximum power in mW according to IEEE 802.3-2022 Table 145-16 */ 14 18 #define MAX_PI_PW 99900 15 19 20 + struct net_device; 16 21 struct phy_device; 17 22 struct pse_controller_dev; 18 23 struct netlink_ext_ack; ··· 40 35 struct ethtool_c33_pse_pw_limit_range { 41 36 u32 min; 42 37 u32 max; 38 + }; 39 + 40 + /** 41 + * struct pse_irq_desc - notification sender description for IRQ based events. 42 + * 43 + * @name: the visible name for the IRQ 44 + * @map_event: driver callback to map IRQ status into PSE devices with events. 45 + */ 46 + struct pse_irq_desc { 47 + const char *name; 48 + int (*map_event)(int irq, struct pse_controller_dev *pcdev, 49 + unsigned long *notifs, 50 + unsigned long *notifs_mask); 43 51 }; 44 52 45 53 /** ··· 116 98 /** 117 99 * struct ethtool_pse_control_status - PSE control/channel status. 118 100 * 101 + * @pw_d_id: PSE power domain index. 119 102 * @podl_admin_state: operational state of the PoDL PSE 120 103 * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState 121 104 * @podl_pw_status: power detection status of the PoDL PSE. ··· 136 117 * is in charge of the memory allocation 137 118 * @c33_pw_limit_nb_ranges: number of supported power limit configuration 138 119 * ranges 120 + * @prio_max: max priority allowed for the c33_prio variable value. 121 + * @prio: priority of the PSE. Managed by PSE core in case of static budget 122 + * evaluation strategy. 139 123 */ 140 124 struct ethtool_pse_control_status { 125 + u32 pw_d_id; 141 126 enum ethtool_podl_pse_admin_state podl_admin_state; 142 127 enum ethtool_podl_pse_pw_d_status podl_pw_status; 143 128 enum ethtool_c33_pse_admin_state c33_admin_state; ··· 152 129 u32 c33_avail_pw_limit; 153 130 struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges; 154 131 u32 c33_pw_limit_nb_ranges; 132 + u32 prio_max; 133 + u32 prio; 155 134 }; 156 135 157 136 /** ··· 177 152 * range. The driver is in charge of the memory 178 153 * allocation and should return the number of 179 154 * ranges. 155 + * @pi_get_prio: Get the PSE PI priority. 156 + * @pi_set_prio: Configure the PSE PI priority. 157 + * @pi_get_pw_req: Get the power requested by a PD before enabling the PSE PI. 158 + * This is only relevant when an interrupt is registered using 159 + * devm_pse_irq_helper helper. 180 160 */ 181 161 struct pse_controller_ops { 182 162 int (*setup_pi_matrix)(struct pse_controller_dev *pcdev); ··· 202 172 int id, int max_mW); 203 173 int (*pi_get_pw_limit_ranges)(struct pse_controller_dev *pcdev, int id, 204 174 struct pse_pw_limit_ranges *pw_limit_ranges); 175 + int (*pi_get_prio)(struct pse_controller_dev *pcdev, int id); 176 + int (*pi_set_prio)(struct pse_controller_dev *pcdev, int id, 177 + unsigned int prio); 178 + int (*pi_get_pw_req)(struct pse_controller_dev *pcdev, int id); 205 179 }; 206 180 207 181 struct module; ··· 240 206 * @np: device node pointer of the PSE PI node 241 207 * @rdev: regulator represented by the PSE PI 242 208 * @admin_state_enabled: PI enabled state 209 + * @pw_d: Power domain of the PSE PI 210 + * @prio: Priority of the PSE PI. Used in static budget evaluation strategy 211 + * @isr_pd_detected: PSE PI detection status managed by the interruption 212 + * handler. This variable is relevant when the power enabled 213 + * management is managed in software like the static 214 + * budget evaluation strategy. 215 + * @pw_allocated_mW: Power allocated to a PSE PI to manage power budget in 216 + * static budget evaluation strategy. 243 217 */ 244 218 struct pse_pi { 245 219 struct pse_pi_pairset pairset[2]; 246 220 struct device_node *np; 247 221 struct regulator_dev *rdev; 248 222 bool admin_state_enabled; 223 + struct pse_power_domain *pw_d; 224 + int prio; 225 + bool isr_pd_detected; 226 + int pw_allocated_mW; 227 + }; 228 + 229 + /** 230 + * struct pse_ntf - PSE notification element 231 + * 232 + * @id: ID of the PSE control 233 + * @notifs: PSE notifications to be reported 234 + */ 235 + struct pse_ntf { 236 + int id; 237 + unsigned long notifs; 249 238 }; 250 239 251 240 /** ··· 285 228 * @types: types of the PSE controller 286 229 * @pi: table of PSE PIs described in this controller device 287 230 * @no_of_pse_pi: flag set if the pse_pis devicetree node is not used 231 + * @irq: PSE interrupt 232 + * @pis_prio_max: Maximum value allowed for the PSE PIs priority 233 + * @supp_budget_eval_strategies: budget evaluation strategies supported 234 + * by the PSE 235 + * @ntf_work: workqueue for PSE notification management 236 + * @ntf_fifo: PSE notifications FIFO 237 + * @ntf_fifo_lock: protect @ntf_fifo writer 288 238 */ 289 239 struct pse_controller_dev { 290 240 const struct pse_controller_ops *ops; ··· 305 241 enum ethtool_pse_types types; 306 242 struct pse_pi *pi; 307 243 bool no_of_pse_pi; 244 + int irq; 245 + unsigned int pis_prio_max; 246 + u32 supp_budget_eval_strategies; 247 + struct work_struct ntf_work; 248 + DECLARE_KFIFO_PTR(ntf_fifo, struct pse_ntf); 249 + spinlock_t ntf_fifo_lock; /* Protect @ntf_fifo writer */ 250 + }; 251 + 252 + /** 253 + * enum pse_budget_eval_strategies - PSE budget evaluation strategies. 254 + * @PSE_BUDGET_EVAL_STRAT_DISABLED: Budget evaluation strategy disabled. 255 + * @PSE_BUDGET_EVAL_STRAT_STATIC: PSE static budget evaluation strategy. 256 + * Budget evaluation strategy based on the power requested during PD 257 + * classification. This strategy is managed by the PSE core. 258 + * @PSE_BUDGET_EVAL_STRAT_DYNAMIC: PSE dynamic budget evaluation 259 + * strategy. Budget evaluation strategy based on the current consumption 260 + * per ports compared to the total power budget. This mode is managed by 261 + * the PSE controller. 262 + */ 263 + 264 + enum pse_budget_eval_strategies { 265 + PSE_BUDGET_EVAL_STRAT_DISABLED = 1 << 0, 266 + PSE_BUDGET_EVAL_STRAT_STATIC = 1 << 1, 267 + PSE_BUDGET_EVAL_STRAT_DYNAMIC = 1 << 2, 308 268 }; 309 269 310 270 #if IS_ENABLED(CONFIG_PSE_CONTROLLER) ··· 337 249 struct device; 338 250 int devm_pse_controller_register(struct device *dev, 339 251 struct pse_controller_dev *pcdev); 252 + int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq, 253 + int irq_flags, const struct pse_irq_desc *d); 340 254 341 - struct pse_control *of_pse_control_get(struct device_node *node); 255 + struct pse_control *of_pse_control_get(struct device_node *node, 256 + struct phy_device *phydev); 342 257 void pse_control_put(struct pse_control *psec); 343 258 344 259 int pse_ethtool_get_status(struct pse_control *psec, ··· 353 262 int pse_ethtool_set_pw_limit(struct pse_control *psec, 354 263 struct netlink_ext_ack *extack, 355 264 const unsigned int pw_limit); 265 + int pse_ethtool_set_prio(struct pse_control *psec, 266 + struct netlink_ext_ack *extack, 267 + unsigned int prio); 356 268 357 269 bool pse_has_podl(struct pse_control *psec); 358 270 bool pse_has_c33(struct pse_control *psec); 359 271 360 272 #else 361 273 362 - static inline struct pse_control *of_pse_control_get(struct device_node *node) 274 + static inline struct pse_control *of_pse_control_get(struct device_node *node, 275 + struct phy_device *phydev) 363 276 { 364 277 return ERR_PTR(-ENOENT); 365 278 } ··· 389 294 static inline int pse_ethtool_set_pw_limit(struct pse_control *psec, 390 295 struct netlink_ext_ack *extack, 391 296 const unsigned int pw_limit) 297 + { 298 + return -EOPNOTSUPP; 299 + } 300 + 301 + static inline int pse_ethtool_set_prio(struct pse_control *psec, 302 + struct netlink_ext_ack *extack, 303 + unsigned int prio) 392 304 { 393 305 return -EOPNOTSUPP; 394 306 }
+64
net/ethtool/pse-pd.c
··· 83 83 const struct ethtool_pse_control_status *st = &data->status; 84 84 int len = 0; 85 85 86 + if (st->pw_d_id) 87 + len += nla_total_size(sizeof(u32)); /* _PSE_PW_D_ID */ 86 88 if (st->podl_admin_state > 0) 87 89 len += nla_total_size(sizeof(u32)); /* _PODL_PSE_ADMIN_STATE */ 88 90 if (st->podl_pw_status > 0) ··· 111 109 len += st->c33_pw_limit_nb_ranges * 112 110 (nla_total_size(0) + 113 111 nla_total_size(sizeof(u32)) * 2); 112 + if (st->prio_max) 113 + /* _PSE_PRIO_MAX + _PSE_PRIO */ 114 + len += nla_total_size(sizeof(u32)) * 2; 114 115 115 116 return len; 116 117 } ··· 152 147 { 153 148 const struct pse_reply_data *data = PSE_REPDATA(reply_base); 154 149 const struct ethtool_pse_control_status *st = &data->status; 150 + 151 + if (st->pw_d_id && 152 + nla_put_u32(skb, ETHTOOL_A_PSE_PW_D_ID, 153 + st->pw_d_id)) 154 + return -EMSGSIZE; 155 155 156 156 if (st->podl_admin_state > 0 && 157 157 nla_put_u32(skb, ETHTOOL_A_PODL_PSE_ADMIN_STATE, ··· 208 198 pse_put_pw_limit_ranges(skb, st)) 209 199 return -EMSGSIZE; 210 200 201 + if (st->prio_max && 202 + (nla_put_u32(skb, ETHTOOL_A_PSE_PRIO_MAX, st->prio_max) || 203 + nla_put_u32(skb, ETHTOOL_A_PSE_PRIO, st->prio))) 204 + return -EMSGSIZE; 205 + 211 206 return 0; 212 207 } 213 208 ··· 234 219 NLA_POLICY_RANGE(NLA_U32, ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED, 235 220 ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED), 236 221 [ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT] = { .type = NLA_U32 }, 222 + [ETHTOOL_A_PSE_PRIO] = { .type = NLA_U32 }, 237 223 }; 238 224 239 225 static int ··· 282 266 ret = ethnl_set_pse_validate(phydev, info); 283 267 if (ret) 284 268 return ret; 269 + 270 + if (tb[ETHTOOL_A_PSE_PRIO]) { 271 + unsigned int prio; 272 + 273 + prio = nla_get_u32(tb[ETHTOOL_A_PSE_PRIO]); 274 + ret = pse_ethtool_set_prio(phydev->psec, info->extack, prio); 275 + if (ret) 276 + return ret; 277 + } 285 278 286 279 if (tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]) { 287 280 unsigned int pw_limit; ··· 340 315 .set = ethnl_set_pse, 341 316 /* PSE has no notification */ 342 317 }; 318 + 319 + void ethnl_pse_send_ntf(struct net_device *netdev, unsigned long notifs) 320 + { 321 + void *reply_payload; 322 + struct sk_buff *skb; 323 + int reply_len; 324 + int ret; 325 + 326 + ASSERT_RTNL(); 327 + 328 + if (!netdev || !notifs) 329 + return; 330 + 331 + reply_len = ethnl_reply_header_size() + 332 + nla_total_size(sizeof(u32)); /* _PSE_NTF_EVENTS */ 333 + 334 + skb = genlmsg_new(reply_len, GFP_KERNEL); 335 + if (!skb) 336 + return; 337 + 338 + reply_payload = ethnl_bcastmsg_put(skb, ETHTOOL_MSG_PSE_NTF); 339 + if (!reply_payload) 340 + goto err_skb; 341 + 342 + ret = ethnl_fill_reply_header(skb, netdev, ETHTOOL_A_PSE_NTF_HEADER); 343 + if (ret < 0) 344 + goto err_skb; 345 + 346 + if (nla_put_uint(skb, ETHTOOL_A_PSE_NTF_EVENTS, notifs)) 347 + goto err_skb; 348 + 349 + genlmsg_end(skb, reply_payload); 350 + ethnl_multicast(skb, netdev); 351 + return; 352 + 353 + err_skb: 354 + nlmsg_free(skb); 355 + } 356 + EXPORT_SYMBOL_GPL(ethnl_pse_send_ntf);