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

net: pse-pd: Use regulator framework within PSE framework

Integrate the regulator framework to the PSE framework for enhanced
access to features such as voltage, power measurement, and limits, which
are akin to regulators. Additionally, PSE features like port priorities
could potentially enhance the regulator framework. Note that this
integration introduces some implementation complexity, including wrapper
callbacks, but the potential benefits make it worthwhile.

Regulator are using enable counter with specific behavior.
Two calls to regulator_disable will trigger kernel warnings.
If the counter exceeds one, regulator_disable call won't disable the
PSE PI. These behavior isn't suitable for PSE control.
Added a boolean 'enabled' state to prevent multiple calls to
regulator_enable/disable. These calls will only be called from PSE
framework as it won't have any regulator children, therefore no mutex are
needed to safeguards this boolean.

regulator_get needs the consumer device pointer. Use PSE as regulator
provider and consumer device until we have RJ45 ports represented in
the Kernel.

Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20240417-feature_poe-v9-10-242293fd1900@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kory Maincent (Dent Project) and committed by
Jakub Kicinski
d83e1376 29e28d1d

+268 -46
+229 -20
drivers/net/pse-pd/pse_core.c
··· 8 8 #include <linux/device.h> 9 9 #include <linux/of.h> 10 10 #include <linux/pse-pd/pse.h> 11 + #include <linux/regulator/driver.h> 12 + #include <linux/regulator/machine.h> 11 13 12 14 static DEFINE_MUTEX(pse_list_mutex); 13 15 static LIST_HEAD(pse_controller_list); ··· 18 16 * struct pse_control - a PSE control 19 17 * @pcdev: a pointer to the PSE controller device 20 18 * this PSE control belongs to 19 + * @ps: PSE PI supply of the PSE control 21 20 * @list: list entry for the pcdev's PSE controller list 22 21 * @id: ID of the PSE line in the PSE controller device 23 22 * @refcnt: Number of gets of this pse_control 24 23 */ 25 24 struct pse_control { 26 25 struct pse_controller_dev *pcdev; 26 + struct regulator *ps; 27 27 struct list_head list; 28 28 unsigned int id; 29 29 struct kref refcnt; ··· 136 132 if (!np) 137 133 return -ENODEV; 138 134 135 + pcdev->pi = kcalloc(pcdev->nr_lines, sizeof(*pcdev->pi), GFP_KERNEL); 136 + if (!pcdev->pi) 137 + return -ENOMEM; 138 + 139 139 pis = of_get_child_by_name(np, "pse-pis"); 140 140 if (!pis) { 141 141 /* no description of PSE PIs */ 142 142 pcdev->no_of_pse_pi = true; 143 143 return 0; 144 - } 145 - 146 - pcdev->pi = kcalloc(pcdev->nr_lines, sizeof(*pcdev->pi), GFP_KERNEL); 147 - if (!pcdev->pi) { 148 - of_node_put(pis); 149 - return -ENOMEM; 150 144 } 151 145 152 146 for_each_child_of_node(pis, node) { ··· 207 205 return ret; 208 206 } 209 207 208 + static int pse_pi_is_enabled(struct regulator_dev *rdev) 209 + { 210 + struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 211 + const struct pse_controller_ops *ops; 212 + int id, ret; 213 + 214 + ops = pcdev->ops; 215 + if (!ops->pi_is_enabled) 216 + return -EOPNOTSUPP; 217 + 218 + id = rdev_get_id(rdev); 219 + mutex_lock(&pcdev->lock); 220 + ret = ops->pi_is_enabled(pcdev, id); 221 + mutex_unlock(&pcdev->lock); 222 + 223 + return ret; 224 + } 225 + 226 + static int pse_pi_enable(struct regulator_dev *rdev) 227 + { 228 + struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 229 + const struct pse_controller_ops *ops; 230 + int id, ret; 231 + 232 + ops = pcdev->ops; 233 + if (!ops->pi_enable) 234 + return -EOPNOTSUPP; 235 + 236 + id = rdev_get_id(rdev); 237 + mutex_lock(&pcdev->lock); 238 + ret = ops->pi_enable(pcdev, id); 239 + if (!ret) 240 + pcdev->pi[id].admin_state_enabled = 1; 241 + mutex_unlock(&pcdev->lock); 242 + 243 + return ret; 244 + } 245 + 246 + static int pse_pi_disable(struct regulator_dev *rdev) 247 + { 248 + struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); 249 + const struct pse_controller_ops *ops; 250 + int id, ret; 251 + 252 + ops = pcdev->ops; 253 + if (!ops->pi_disable) 254 + return -EOPNOTSUPP; 255 + 256 + id = rdev_get_id(rdev); 257 + mutex_lock(&pcdev->lock); 258 + ret = ops->pi_disable(pcdev, id); 259 + if (!ret) 260 + pcdev->pi[id].admin_state_enabled = 0; 261 + mutex_unlock(&pcdev->lock); 262 + 263 + return ret; 264 + } 265 + 266 + static const struct regulator_ops pse_pi_ops = { 267 + .is_enabled = pse_pi_is_enabled, 268 + .enable = pse_pi_enable, 269 + .disable = pse_pi_disable, 270 + }; 271 + 272 + static int 273 + devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev, 274 + char *name, int id) 275 + { 276 + struct regulator_init_data *rinit_data; 277 + struct regulator_config rconfig = {0}; 278 + struct regulator_desc *rdesc; 279 + struct regulator_dev *rdev; 280 + 281 + rinit_data = devm_kzalloc(pcdev->dev, sizeof(*rinit_data), 282 + GFP_KERNEL); 283 + if (!rinit_data) 284 + return -ENOMEM; 285 + 286 + rdesc = devm_kzalloc(pcdev->dev, sizeof(*rdesc), GFP_KERNEL); 287 + if (!rdesc) 288 + return -ENOMEM; 289 + 290 + /* Regulator descriptor id have to be the same as its associated 291 + * PSE PI id for the well functioning of the PSE controls. 292 + */ 293 + rdesc->id = id; 294 + rdesc->name = name; 295 + rdesc->type = REGULATOR_CURRENT; 296 + rdesc->ops = &pse_pi_ops; 297 + rdesc->owner = pcdev->owner; 298 + 299 + rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; 300 + rinit_data->supply_regulator = "vpwr"; 301 + 302 + rconfig.dev = pcdev->dev; 303 + rconfig.driver_data = pcdev; 304 + rconfig.init_data = rinit_data; 305 + 306 + rdev = devm_regulator_register(pcdev->dev, rdesc, &rconfig); 307 + if (IS_ERR(rdev)) { 308 + dev_err_probe(pcdev->dev, PTR_ERR(rdev), 309 + "Failed to register regulator\n"); 310 + return PTR_ERR(rdev); 311 + } 312 + 313 + pcdev->pi[id].rdev = rdev; 314 + 315 + return 0; 316 + } 317 + 210 318 /** 211 319 * pse_controller_register - register a PSE controller device 212 320 * @pcdev: a pointer to the initialized PSE controller device 213 321 */ 214 322 int pse_controller_register(struct pse_controller_dev *pcdev) 215 323 { 216 - int ret; 324 + size_t reg_name_len; 325 + int ret, i; 217 326 218 327 mutex_init(&pcdev->lock); 219 328 INIT_LIST_HEAD(&pcdev->pse_control_head); ··· 338 225 339 226 if (pcdev->ops->setup_pi_matrix) { 340 227 ret = pcdev->ops->setup_pi_matrix(pcdev); 228 + if (ret) 229 + return ret; 230 + } 231 + 232 + /* Each regulator name len is pcdev dev name + 7 char + 233 + * int max digit number (10) + 1 234 + */ 235 + reg_name_len = strlen(dev_name(pcdev->dev)) + 18; 236 + 237 + /* Register PI regulators */ 238 + for (i = 0; i < pcdev->nr_lines; i++) { 239 + char *reg_name; 240 + 241 + /* Do not register regulator for PIs not described */ 242 + if (!pcdev->no_of_pse_pi && !pcdev->pi[i].np) 243 + continue; 244 + 245 + reg_name = devm_kzalloc(pcdev->dev, reg_name_len, GFP_KERNEL); 246 + if (!reg_name) 247 + return -ENOMEM; 248 + 249 + snprintf(reg_name, reg_name_len, "pse-%s_pi%d", 250 + dev_name(pcdev->dev), i); 251 + 252 + ret = devm_pse_pi_regulator_register(pcdev, reg_name, i); 341 253 if (ret) 342 254 return ret; 343 255 } ··· 435 297 436 298 lockdep_assert_held(&pse_list_mutex); 437 299 300 + if (psec->pcdev->pi[psec->id].admin_state_enabled) 301 + regulator_disable(psec->ps); 302 + devm_regulator_put(psec->ps); 303 + 438 304 module_put(psec->pcdev->owner); 439 305 440 306 list_del(&psec->list); ··· 471 329 pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index) 472 330 { 473 331 struct pse_control *psec; 332 + int ret; 474 333 475 334 lockdep_assert_held(&pse_list_mutex); 476 335 ··· 487 344 return ERR_PTR(-ENOMEM); 488 345 489 346 if (!try_module_get(pcdev->owner)) { 490 - kfree(psec); 491 - return ERR_PTR(-ENODEV); 347 + ret = -ENODEV; 348 + goto free_psec; 492 349 } 350 + 351 + psec->ps = devm_regulator_get_exclusive(pcdev->dev, 352 + rdev_get_name(pcdev->pi[index].rdev)); 353 + if (IS_ERR(psec->ps)) { 354 + ret = PTR_ERR(psec->ps); 355 + goto put_module; 356 + } 357 + 358 + ret = regulator_is_enabled(psec->ps); 359 + if (ret < 0) 360 + goto regulator_put; 361 + 362 + pcdev->pi[index].admin_state_enabled = ret; 493 363 494 364 psec->pcdev = pcdev; 495 365 list_add(&psec->list, &pcdev->pse_control_head); ··· 510 354 kref_init(&psec->refcnt); 511 355 512 356 return psec; 357 + 358 + regulator_put: 359 + devm_regulator_put(psec->ps); 360 + put_module: 361 + module_put(pcdev->owner); 362 + free_psec: 363 + kfree(psec); 364 + 365 + return ERR_PTR(ret); 513 366 } 514 367 515 368 /** ··· 651 486 } 652 487 EXPORT_SYMBOL_GPL(pse_ethtool_get_status); 653 488 489 + static int pse_ethtool_c33_set_config(struct pse_control *psec, 490 + const struct pse_control_config *config) 491 + { 492 + int err = 0; 493 + 494 + /* Look at admin_state_enabled status to not call regulator_enable 495 + * or regulator_disable twice creating a regulator counter mismatch 496 + */ 497 + switch (config->c33_admin_control) { 498 + case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED: 499 + if (!psec->pcdev->pi[psec->id].admin_state_enabled) 500 + err = regulator_enable(psec->ps); 501 + break; 502 + case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED: 503 + if (psec->pcdev->pi[psec->id].admin_state_enabled) 504 + err = regulator_disable(psec->ps); 505 + break; 506 + default: 507 + err = -EOPNOTSUPP; 508 + } 509 + 510 + return err; 511 + } 512 + 513 + static int pse_ethtool_podl_set_config(struct pse_control *psec, 514 + const struct pse_control_config *config) 515 + { 516 + int err = 0; 517 + 518 + /* Look at admin_state_enabled status to not call regulator_enable 519 + * or regulator_disable twice creating a regulator counter mismatch 520 + */ 521 + switch (config->podl_admin_control) { 522 + case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: 523 + if (!psec->pcdev->pi[psec->id].admin_state_enabled) 524 + err = regulator_enable(psec->ps); 525 + break; 526 + case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: 527 + if (psec->pcdev->pi[psec->id].admin_state_enabled) 528 + err = regulator_disable(psec->ps); 529 + break; 530 + default: 531 + err = -EOPNOTSUPP; 532 + } 533 + 534 + return err; 535 + } 536 + 654 537 /** 655 538 * pse_ethtool_set_config - set PSE control configuration 656 539 * @psec: PSE control pointer ··· 709 496 struct netlink_ext_ack *extack, 710 497 const struct pse_control_config *config) 711 498 { 712 - const struct pse_controller_ops *ops; 713 - int err; 499 + int err = 0; 714 500 715 - ops = psec->pcdev->ops; 716 - 717 - if (!ops->ethtool_set_config) { 718 - NL_SET_ERR_MSG(extack, 719 - "PSE driver does not configuration"); 720 - return -EOPNOTSUPP; 501 + if (pse_has_c33(psec)) { 502 + err = pse_ethtool_c33_set_config(psec, config); 503 + if (err) 504 + return err; 721 505 } 722 506 723 - mutex_lock(&psec->pcdev->lock); 724 - err = ops->ethtool_set_config(psec->pcdev, psec->id, extack, config); 725 - mutex_unlock(&psec->pcdev->lock); 507 + if (pse_has_podl(psec)) 508 + err = pse_ethtool_podl_set_config(psec, config); 726 509 727 510 return err; 728 511 }
+28 -22
drivers/net/pse-pd/pse_regulator.c
··· 24 24 } 25 25 26 26 static int 27 - pse_reg_ethtool_set_config(struct pse_controller_dev *pcdev, unsigned long id, 28 - struct netlink_ext_ack *extack, 29 - const struct pse_control_config *config) 27 + pse_reg_pi_enable(struct pse_controller_dev *pcdev, int id) 30 28 { 31 29 struct pse_reg_priv *priv = to_pse_reg(pcdev); 32 30 int ret; 33 31 34 - if (priv->admin_state == config->podl_admin_control) 35 - return 0; 36 - 37 - switch (config->podl_admin_control) { 38 - case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: 39 - ret = regulator_enable(priv->ps); 40 - break; 41 - case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: 42 - ret = regulator_disable(priv->ps); 43 - break; 44 - default: 45 - dev_err(pcdev->dev, "Unknown admin state %i\n", 46 - config->podl_admin_control); 47 - ret = -ENOTSUPP; 48 - } 49 - 32 + ret = regulator_enable(priv->ps); 50 33 if (ret) 51 34 return ret; 52 35 53 - priv->admin_state = config->podl_admin_control; 54 - 36 + priv->admin_state = ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED; 55 37 return 0; 38 + } 39 + 40 + static int 41 + pse_reg_pi_disable(struct pse_controller_dev *pcdev, int id) 42 + { 43 + struct pse_reg_priv *priv = to_pse_reg(pcdev); 44 + int ret; 45 + 46 + ret = regulator_disable(priv->ps); 47 + if (ret) 48 + return ret; 49 + 50 + priv->admin_state = ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED; 51 + return 0; 52 + } 53 + 54 + static int 55 + pse_reg_pi_is_enabled(struct pse_controller_dev *pcdev, int id) 56 + { 57 + struct pse_reg_priv *priv = to_pse_reg(pcdev); 58 + 59 + return regulator_is_enabled(priv->ps); 56 60 } 57 61 58 62 static int ··· 84 80 85 81 static const struct pse_controller_ops pse_reg_ops = { 86 82 .ethtool_get_status = pse_reg_ethtool_get_status, 87 - .ethtool_set_config = pse_reg_ethtool_set_config, 83 + .pi_enable = pse_reg_pi_enable, 84 + .pi_is_enabled = pse_reg_pi_is_enabled, 85 + .pi_disable = pse_reg_pi_disable, 88 86 }; 89 87 90 88 static int
+11 -4
include/linux/pse-pd/pse.h
··· 48 48 * struct pse_controller_ops - PSE controller driver callbacks 49 49 * 50 50 * @ethtool_get_status: get PSE control status for ethtool interface 51 - * @ethtool_set_config: set PSE control configuration over ethtool interface 52 51 * @setup_pi_matrix: setup PI matrix of the PSE controller 52 + * @pi_is_enabled: Return 1 if the PSE PI is enabled, 0 if not. 53 + * May also return negative errno. 54 + * @pi_enable: Configure the PSE PI as enabled. 55 + * @pi_disable: Configure the PSE PI as disabled. 53 56 */ 54 57 struct pse_controller_ops { 55 58 int (*ethtool_get_status)(struct pse_controller_dev *pcdev, 56 59 unsigned long id, struct netlink_ext_ack *extack, 57 60 struct pse_control_status *status); 58 - int (*ethtool_set_config)(struct pse_controller_dev *pcdev, 59 - unsigned long id, struct netlink_ext_ack *extack, 60 - const struct pse_control_config *config); 61 61 int (*setup_pi_matrix)(struct pse_controller_dev *pcdev); 62 + int (*pi_is_enabled)(struct pse_controller_dev *pcdev, int id); 63 + int (*pi_enable)(struct pse_controller_dev *pcdev, int id); 64 + int (*pi_disable)(struct pse_controller_dev *pcdev, int id); 62 65 }; 63 66 64 67 struct module; ··· 93 90 * 94 91 * @pairset: table of the PSE PI pinout alternative for the two pairset 95 92 * @np: device node pointer of the PSE PI node 93 + * @rdev: regulator represented by the PSE PI 94 + * @admin_state_enabled: PI enabled state 96 95 */ 97 96 struct pse_pi { 98 97 struct pse_pi_pairset pairset[2]; 99 98 struct device_node *np; 99 + struct regulator_dev *rdev; 100 + bool admin_state_enabled; 100 101 }; 101 102 102 103 /**