1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ 3 4 #include <linux/kernel.h> 5 #include <linux/err.h> 6 #include <linux/ethtool.h> 7 #include <linux/sfp.h> 8 #include <linux/mutex.h> 9 10 #include "core.h" 11 #include "core_env.h" 12 #include "item.h" 13 #include "reg.h" 14 15 struct mlxsw_env_module_info { 16 u64 module_overheat_counter; 17 bool is_overheat; 18 int num_ports_mapped; 19 int num_ports_up; 20 enum ethtool_module_power_mode_policy power_mode_policy; 21 enum mlxsw_reg_pmtm_module_type type; 22 }; 23 24 struct mlxsw_env { 25 struct mlxsw_core *core; 26 u8 module_count; 27 struct mutex module_info_lock; /* Protects 'module_info'. */ 28 struct mlxsw_env_module_info module_info[]; 29 }; 30 31 static int __mlxsw_env_validate_module_type(struct mlxsw_core *core, u8 module) 32 { 33 struct mlxsw_env *mlxsw_env = mlxsw_core_env(core); 34 int err; 35 36 switch (mlxsw_env->module_info[module].type) { 37 case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR: 38 err = -EINVAL; 39 break; 40 default: 41 err = 0; 42 } 43 44 return err; 45 } 46 47 static int mlxsw_env_validate_module_type(struct mlxsw_core *core, u8 module) 48 { 49 struct mlxsw_env *mlxsw_env = mlxsw_core_env(core); 50 int err; 51 52 mutex_lock(&mlxsw_env->module_info_lock); 53 err = __mlxsw_env_validate_module_type(core, module); 54 mutex_unlock(&mlxsw_env->module_info_lock); 55 56 return err; 57 } 58 59 static int 60 mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, bool *qsfp, 61 bool *cmis) 62 { 63 char mcia_pl[MLXSW_REG_MCIA_LEN]; 64 char *eeprom_tmp; 65 u8 ident; 66 int err; 67 68 err = mlxsw_env_validate_module_type(core, id); 69 if (err) 70 return err; 71 72 mlxsw_reg_mcia_pack(mcia_pl, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1, 73 MLXSW_REG_MCIA_I2C_ADDR_LOW); 74 err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); 75 if (err) 76 return err; 77 eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl); 78 ident = eeprom_tmp[0]; 79 *cmis = false; 80 switch (ident) { 81 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: 82 *qsfp = false; 83 break; 84 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: 85 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: 86 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: 87 *qsfp = true; 88 break; 89 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD: 90 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_OSFP: 91 *qsfp = true; 92 *cmis = true; 93 break; 94 default: 95 return -EINVAL; 96 } 97 98 return 0; 99 } 100 101 static int 102 mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, 103 u16 offset, u16 size, void *data, 104 bool qsfp, unsigned int *p_read_size) 105 { 106 char mcia_pl[MLXSW_REG_MCIA_LEN]; 107 char *eeprom_tmp; 108 u16 i2c_addr; 109 u8 page = 0; 110 int status; 111 int err; 112 113 /* MCIA register accepts buffer size <= 48. Page of size 128 should be 114 * read by chunks of size 48, 48, 32. Align the size of the last chunk 115 * to avoid reading after the end of the page. 116 */ 117 size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); 118 119 if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && 120 offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) 121 /* Cross pages read, read until offset 256 in low page */ 122 size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; 123 124 i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW; 125 if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) { 126 if (qsfp) { 127 /* When reading upper pages 1, 2 and 3 the offset 128 * starts at 128. Please refer to "QSFP+ Memory Map" 129 * figure in SFF-8436 specification and to "CMIS Module 130 * Memory Map" figure in CMIS specification for 131 * graphical depiction. 132 */ 133 page = MLXSW_REG_MCIA_PAGE_GET(offset); 134 offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page; 135 if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) 136 size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; 137 } else { 138 /* When reading upper pages 1, 2 and 3 the offset 139 * starts at 0 and I2C high address is used. Please refer 140 * refer to "Memory Organization" figure in SFF-8472 141 * specification for graphical depiction. 142 */ 143 i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH; 144 offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH; 145 } 146 } 147 148 mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr); 149 150 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); 151 if (err) 152 return err; 153 154 status = mlxsw_reg_mcia_status_get(mcia_pl); 155 if (status) 156 return -EIO; 157 158 eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl); 159 memcpy(data, eeprom_tmp, size); 160 *p_read_size = size; 161 162 return 0; 163 } 164 165 int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, 166 int off, int *temp) 167 { 168 unsigned int module_temp, module_crit, module_emerg; 169 union { 170 u8 buf[MLXSW_REG_MCIA_TH_ITEM_SIZE]; 171 u16 temp; 172 } temp_thresh; 173 char mcia_pl[MLXSW_REG_MCIA_LEN] = {0}; 174 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 175 char *eeprom_tmp; 176 bool qsfp, cmis; 177 int page; 178 int err; 179 180 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, 181 false, false); 182 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl); 183 if (err) 184 return err; 185 mlxsw_reg_mtmp_unpack(mtmp_pl, &module_temp, NULL, &module_crit, 186 &module_emerg, NULL); 187 if (!module_temp) { 188 *temp = 0; 189 return 0; 190 } 191 192 /* Validate if threshold reading is available through MTMP register, 193 * otherwise fallback to read through MCIA. 194 */ 195 if (module_emerg) { 196 *temp = off == SFP_TEMP_HIGH_WARN ? module_crit : module_emerg; 197 return 0; 198 } 199 200 /* Read Free Side Device Temperature Thresholds from page 03h 201 * (MSB at lower byte address). 202 * Bytes: 203 * 128-129 - Temp High Alarm (SFP_TEMP_HIGH_ALARM); 204 * 130-131 - Temp Low Alarm (SFP_TEMP_LOW_ALARM); 205 * 132-133 - Temp High Warning (SFP_TEMP_HIGH_WARN); 206 * 134-135 - Temp Low Warning (SFP_TEMP_LOW_WARN); 207 */ 208 209 /* Validate module identifier value. */ 210 err = mlxsw_env_validate_cable_ident(core, module, &qsfp, &cmis); 211 if (err) 212 return err; 213 214 if (qsfp) { 215 /* For QSFP/CMIS module-defined thresholds are located in page 216 * 02h, otherwise in page 03h. 217 */ 218 if (cmis) 219 page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM; 220 else 221 page = MLXSW_REG_MCIA_TH_PAGE_NUM; 222 mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, 223 MLXSW_REG_MCIA_TH_PAGE_OFF + off, 224 MLXSW_REG_MCIA_TH_ITEM_SIZE, 225 MLXSW_REG_MCIA_I2C_ADDR_LOW); 226 } else { 227 mlxsw_reg_mcia_pack(mcia_pl, module, 0, 228 MLXSW_REG_MCIA_PAGE0_LO, 229 off, MLXSW_REG_MCIA_TH_ITEM_SIZE, 230 MLXSW_REG_MCIA_I2C_ADDR_HIGH); 231 } 232 233 err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); 234 if (err) 235 return err; 236 237 eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl); 238 memcpy(temp_thresh.buf, eeprom_tmp, MLXSW_REG_MCIA_TH_ITEM_SIZE); 239 *temp = temp_thresh.temp * 1000; 240 241 return 0; 242 } 243 244 int mlxsw_env_get_module_info(struct net_device *netdev, 245 struct mlxsw_core *mlxsw_core, int module, 246 struct ethtool_modinfo *modinfo) 247 { 248 u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; 249 u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; 250 u8 module_rev_id, module_id, diag_mon; 251 unsigned int read_size; 252 int err; 253 254 err = mlxsw_env_validate_module_type(mlxsw_core, module); 255 if (err) { 256 netdev_err(netdev, 257 "EEPROM is not equipped on port module type"); 258 return err; 259 } 260 261 err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset, 262 module_info, false, &read_size); 263 if (err) 264 return err; 265 266 if (read_size < offset) 267 return -EIO; 268 269 module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID]; 270 module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID]; 271 272 switch (module_id) { 273 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: 274 modinfo->type = ETH_MODULE_SFF_8436; 275 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; 276 break; 277 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: 278 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: 279 if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 || 280 module_rev_id >= 281 MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) { 282 modinfo->type = ETH_MODULE_SFF_8636; 283 modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; 284 } else { 285 modinfo->type = ETH_MODULE_SFF_8436; 286 modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; 287 } 288 break; 289 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: 290 /* Verify if transceiver provides diagnostic monitoring page */ 291 err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 292 SFP_DIAGMON, 1, &diag_mon, 293 false, &read_size); 294 if (err) 295 return err; 296 297 if (read_size < 1) 298 return -EIO; 299 300 modinfo->type = ETH_MODULE_SFF_8472; 301 if (diag_mon) 302 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 303 else 304 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2; 305 break; 306 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD: 307 case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_OSFP: 308 /* Use SFF_8636 as base type. ethtool should recognize specific 309 * type through the identifier value. 310 */ 311 modinfo->type = ETH_MODULE_SFF_8636; 312 /* Verify if module EEPROM is a flat memory. In case of flat 313 * memory only page 00h (0-255 bytes) can be read. Otherwise 314 * upper pages 01h and 02h can also be read. Upper pages 10h 315 * and 11h are currently not supported by the driver. 316 */ 317 if (module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_TYPE_ID] & 318 MLXSW_REG_MCIA_EEPROM_CMIS_FLAT_MEMORY) 319 modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; 320 else 321 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 322 break; 323 default: 324 return -EINVAL; 325 } 326 327 return 0; 328 } 329 EXPORT_SYMBOL(mlxsw_env_get_module_info); 330 331 int mlxsw_env_get_module_eeprom(struct net_device *netdev, 332 struct mlxsw_core *mlxsw_core, int module, 333 struct ethtool_eeprom *ee, u8 *data) 334 { 335 int offset = ee->offset; 336 unsigned int read_size; 337 bool qsfp, cmis; 338 int i = 0; 339 int err; 340 341 if (!ee->len) 342 return -EINVAL; 343 344 memset(data, 0, ee->len); 345 /* Validate module identifier value. */ 346 err = mlxsw_env_validate_cable_ident(mlxsw_core, module, &qsfp, &cmis); 347 if (err) 348 return err; 349 350 while (i < ee->len) { 351 err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset, 352 ee->len - i, data + i, 353 qsfp, &read_size); 354 if (err) { 355 netdev_err(netdev, "Eeprom query failed\n"); 356 return err; 357 } 358 359 i += read_size; 360 offset += read_size; 361 } 362 363 return 0; 364 } 365 EXPORT_SYMBOL(mlxsw_env_get_module_eeprom); 366 367 static int mlxsw_env_mcia_status_process(const char *mcia_pl, 368 struct netlink_ext_ack *extack) 369 { 370 u8 status = mlxsw_reg_mcia_status_get(mcia_pl); 371 372 switch (status) { 373 case MLXSW_REG_MCIA_STATUS_GOOD: 374 return 0; 375 case MLXSW_REG_MCIA_STATUS_NO_EEPROM_MODULE: 376 NL_SET_ERR_MSG_MOD(extack, "No response from module's EEPROM"); 377 return -EIO; 378 case MLXSW_REG_MCIA_STATUS_MODULE_NOT_SUPPORTED: 379 NL_SET_ERR_MSG_MOD(extack, "Module type not supported by the device"); 380 return -EOPNOTSUPP; 381 case MLXSW_REG_MCIA_STATUS_MODULE_NOT_CONNECTED: 382 NL_SET_ERR_MSG_MOD(extack, "No module present indication"); 383 return -EIO; 384 case MLXSW_REG_MCIA_STATUS_I2C_ERROR: 385 NL_SET_ERR_MSG_MOD(extack, "Error occurred while trying to access module's EEPROM using I2C"); 386 return -EIO; 387 case MLXSW_REG_MCIA_STATUS_MODULE_DISABLED: 388 NL_SET_ERR_MSG_MOD(extack, "Module is disabled"); 389 return -EIO; 390 default: 391 NL_SET_ERR_MSG_MOD(extack, "Unknown error"); 392 return -EIO; 393 } 394 } 395 396 int 397 mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core, u8 module, 398 const struct ethtool_module_eeprom *page, 399 struct netlink_ext_ack *extack) 400 { 401 u32 bytes_read = 0; 402 u16 device_addr; 403 int err; 404 405 err = mlxsw_env_validate_module_type(mlxsw_core, module); 406 if (err) { 407 NL_SET_ERR_MSG_MOD(extack, "EEPROM is not equipped on port module type"); 408 return err; 409 } 410 411 /* Offset cannot be larger than 2 * ETH_MODULE_EEPROM_PAGE_LEN */ 412 device_addr = page->offset; 413 414 while (bytes_read < page->length) { 415 char mcia_pl[MLXSW_REG_MCIA_LEN]; 416 char *eeprom_tmp; 417 u8 size; 418 419 size = min_t(u8, page->length - bytes_read, 420 MLXSW_REG_MCIA_EEPROM_SIZE); 421 422 mlxsw_reg_mcia_pack(mcia_pl, module, 0, page->page, 423 device_addr + bytes_read, size, 424 page->i2c_address); 425 mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank); 426 427 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); 428 if (err) { 429 NL_SET_ERR_MSG_MOD(extack, "Failed to access module's EEPROM"); 430 return err; 431 } 432 433 err = mlxsw_env_mcia_status_process(mcia_pl, extack); 434 if (err) 435 return err; 436 437 eeprom_tmp = mlxsw_reg_mcia_eeprom_data(mcia_pl); 438 memcpy(page->data + bytes_read, eeprom_tmp, size); 439 bytes_read += size; 440 } 441 442 return bytes_read; 443 } 444 EXPORT_SYMBOL(mlxsw_env_get_module_eeprom_by_page); 445 446 static int mlxsw_env_module_reset(struct mlxsw_core *mlxsw_core, u8 module) 447 { 448 char pmaos_pl[MLXSW_REG_PMAOS_LEN]; 449 450 mlxsw_reg_pmaos_pack(pmaos_pl, module); 451 mlxsw_reg_pmaos_rst_set(pmaos_pl, true); 452 453 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); 454 } 455 456 int mlxsw_env_reset_module(struct net_device *netdev, 457 struct mlxsw_core *mlxsw_core, u8 module, u32 *flags) 458 { 459 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 460 u32 req = *flags; 461 int err; 462 463 if (!(req & ETH_RESET_PHY) && 464 !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) 465 return 0; 466 467 mutex_lock(&mlxsw_env->module_info_lock); 468 469 err = __mlxsw_env_validate_module_type(mlxsw_core, module); 470 if (err) { 471 netdev_err(netdev, "Reset module is not supported on port module type\n"); 472 goto out; 473 } 474 475 if (mlxsw_env->module_info[module].num_ports_up) { 476 netdev_err(netdev, "Cannot reset module when ports using it are administratively up\n"); 477 err = -EINVAL; 478 goto out; 479 } 480 481 if (mlxsw_env->module_info[module].num_ports_mapped > 1 && 482 !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT))) { 483 netdev_err(netdev, "Cannot reset module without \"phy-shared\" flag when shared by multiple ports\n"); 484 err = -EINVAL; 485 goto out; 486 } 487 488 err = mlxsw_env_module_reset(mlxsw_core, module); 489 if (err) { 490 netdev_err(netdev, "Failed to reset module\n"); 491 goto out; 492 } 493 494 *flags &= ~(ETH_RESET_PHY | (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT)); 495 496 out: 497 mutex_unlock(&mlxsw_env->module_info_lock); 498 return err; 499 } 500 EXPORT_SYMBOL(mlxsw_env_reset_module); 501 502 int 503 mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, 504 struct ethtool_module_power_mode_params *params, 505 struct netlink_ext_ack *extack) 506 { 507 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 508 char mcion_pl[MLXSW_REG_MCION_LEN]; 509 u32 status_bits; 510 int err; 511 512 mutex_lock(&mlxsw_env->module_info_lock); 513 514 err = __mlxsw_env_validate_module_type(mlxsw_core, module); 515 if (err) { 516 NL_SET_ERR_MSG_MOD(extack, "Power mode is not supported on port module type"); 517 goto out; 518 } 519 520 params->policy = mlxsw_env->module_info[module].power_mode_policy; 521 522 mlxsw_reg_mcion_pack(mcion_pl, module); 523 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl); 524 if (err) { 525 NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode"); 526 goto out; 527 } 528 529 status_bits = mlxsw_reg_mcion_module_status_bits_get(mcion_pl); 530 if (!(status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK)) 531 goto out; 532 533 if (status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK) 534 params->mode = ETHTOOL_MODULE_POWER_MODE_LOW; 535 else 536 params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH; 537 538 out: 539 mutex_unlock(&mlxsw_env->module_info_lock); 540 return err; 541 } 542 EXPORT_SYMBOL(mlxsw_env_get_module_power_mode); 543 544 static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core, 545 u8 module, bool enable) 546 { 547 enum mlxsw_reg_pmaos_admin_status admin_status; 548 char pmaos_pl[MLXSW_REG_PMAOS_LEN]; 549 550 mlxsw_reg_pmaos_pack(pmaos_pl, module); 551 admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED : 552 MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED; 553 mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status); 554 mlxsw_reg_pmaos_ase_set(pmaos_pl, true); 555 556 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); 557 } 558 559 static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core, 560 u8 module, bool low_power) 561 { 562 u16 eeprom_override_mask, eeprom_override; 563 char pmmp_pl[MLXSW_REG_PMMP_LEN]; 564 565 mlxsw_reg_pmmp_pack(pmmp_pl, module); 566 mlxsw_reg_pmmp_sticky_set(pmmp_pl, true); 567 /* Mask all the bits except low power mode. */ 568 eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK; 569 mlxsw_reg_pmmp_eeprom_override_mask_set(pmmp_pl, eeprom_override_mask); 570 eeprom_override = low_power ? MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK : 571 0; 572 mlxsw_reg_pmmp_eeprom_override_set(pmmp_pl, eeprom_override); 573 574 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmmp), pmmp_pl); 575 } 576 577 static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, 578 u8 module, bool low_power, 579 struct netlink_ext_ack *extack) 580 { 581 int err; 582 583 err = mlxsw_env_module_enable_set(mlxsw_core, module, false); 584 if (err) { 585 NL_SET_ERR_MSG_MOD(extack, "Failed to disable module"); 586 return err; 587 } 588 589 err = mlxsw_env_module_low_power_set(mlxsw_core, module, low_power); 590 if (err) { 591 NL_SET_ERR_MSG_MOD(extack, "Failed to set module's power mode"); 592 goto err_module_low_power_set; 593 } 594 595 err = mlxsw_env_module_enable_set(mlxsw_core, module, true); 596 if (err) { 597 NL_SET_ERR_MSG_MOD(extack, "Failed to enable module"); 598 goto err_module_enable_set; 599 } 600 601 return 0; 602 603 err_module_enable_set: 604 mlxsw_env_module_low_power_set(mlxsw_core, module, !low_power); 605 err_module_low_power_set: 606 mlxsw_env_module_enable_set(mlxsw_core, module, true); 607 return err; 608 } 609 610 int 611 mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module, 612 enum ethtool_module_power_mode_policy policy, 613 struct netlink_ext_ack *extack) 614 { 615 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 616 bool low_power; 617 int err = 0; 618 619 if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH && 620 policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) { 621 NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy"); 622 return -EOPNOTSUPP; 623 } 624 625 mutex_lock(&mlxsw_env->module_info_lock); 626 627 err = __mlxsw_env_validate_module_type(mlxsw_core, module); 628 if (err) { 629 NL_SET_ERR_MSG_MOD(extack, 630 "Power mode set is not supported on port module type"); 631 goto out; 632 } 633 634 if (mlxsw_env->module_info[module].power_mode_policy == policy) 635 goto out; 636 637 /* If any ports are up, we are already in high power mode. */ 638 if (mlxsw_env->module_info[module].num_ports_up) 639 goto out_set_policy; 640 641 low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO; 642 err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, low_power, 643 extack); 644 if (err) 645 goto out; 646 647 out_set_policy: 648 mlxsw_env->module_info[module].power_mode_policy = policy; 649 out: 650 mutex_unlock(&mlxsw_env->module_info_lock); 651 return err; 652 } 653 EXPORT_SYMBOL(mlxsw_env_set_module_power_mode); 654 655 static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, 656 u8 module, 657 bool *p_has_temp_sensor) 658 { 659 char mtbr_pl[MLXSW_REG_MTBR_LEN]; 660 u16 temp; 661 int err; 662 663 mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 664 1); 665 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl); 666 if (err) 667 return err; 668 669 mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); 670 671 switch (temp) { 672 case MLXSW_REG_MTBR_BAD_SENS_INFO: 673 case MLXSW_REG_MTBR_NO_CONN: 674 case MLXSW_REG_MTBR_NO_TEMP_SENS: 675 case MLXSW_REG_MTBR_INDEX_NA: 676 *p_has_temp_sensor = false; 677 break; 678 default: 679 *p_has_temp_sensor = temp ? true : false; 680 } 681 return 0; 682 } 683 684 static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, 685 u16 sensor_index, bool enable) 686 { 687 char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; 688 enum mlxsw_reg_mtmp_tee tee; 689 int err, threshold_hi; 690 691 mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, sensor_index); 692 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); 693 if (err) 694 return err; 695 696 if (enable) { 697 err = mlxsw_env_module_temp_thresholds_get(mlxsw_core, 698 sensor_index - 699 MLXSW_REG_MTMP_MODULE_INDEX_MIN, 700 SFP_TEMP_HIGH_WARN, 701 &threshold_hi); 702 /* In case it is not possible to query the module's threshold, 703 * use the default value. 704 */ 705 if (err) 706 threshold_hi = MLXSW_REG_MTMP_THRESH_HI; 707 else 708 /* mlxsw_env_module_temp_thresholds_get() multiplies 709 * Celsius degrees by 1000 whereas MTMP expects 710 * temperature in 0.125 Celsius degrees units. 711 * Convert threshold_hi to correct units. 712 */ 713 threshold_hi = threshold_hi / 1000 * 8; 714 715 mlxsw_reg_mtmp_temperature_threshold_hi_set(mtmp_pl, threshold_hi); 716 mlxsw_reg_mtmp_temperature_threshold_lo_set(mtmp_pl, threshold_hi - 717 MLXSW_REG_MTMP_HYSTERESIS_TEMP); 718 } 719 tee = enable ? MLXSW_REG_MTMP_TEE_GENERATE_EVENT : MLXSW_REG_MTMP_TEE_NO_EVENT; 720 mlxsw_reg_mtmp_tee_set(mtmp_pl, tee); 721 return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); 722 } 723 724 static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core) 725 { 726 int i, err, sensor_index; 727 bool has_temp_sensor; 728 729 for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) { 730 err = mlxsw_env_module_has_temp_sensor(mlxsw_core, i, 731 &has_temp_sensor); 732 if (err) 733 return err; 734 735 if (!has_temp_sensor) 736 continue; 737 738 sensor_index = i + MLXSW_REG_MTMP_MODULE_INDEX_MIN; 739 err = mlxsw_env_temp_event_set(mlxsw_core, sensor_index, true); 740 if (err) 741 return err; 742 } 743 744 return 0; 745 } 746 747 struct mlxsw_env_module_temp_warn_event { 748 struct mlxsw_env *mlxsw_env; 749 char mtwe_pl[MLXSW_REG_MTWE_LEN]; 750 struct work_struct work; 751 }; 752 753 static void mlxsw_env_mtwe_event_work(struct work_struct *work) 754 { 755 struct mlxsw_env_module_temp_warn_event *event; 756 struct mlxsw_env *mlxsw_env; 757 int i, sensor_warning; 758 bool is_overheat; 759 760 event = container_of(work, struct mlxsw_env_module_temp_warn_event, 761 work); 762 mlxsw_env = event->mlxsw_env; 763 764 for (i = 0; i < mlxsw_env->module_count; i++) { 765 /* 64-127 of sensor_index are mapped to the port modules 766 * sequentially (module 0 is mapped to sensor_index 64, 767 * module 1 to sensor_index 65 and so on) 768 */ 769 sensor_warning = 770 mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl, 771 i + MLXSW_REG_MTMP_MODULE_INDEX_MIN); 772 mutex_lock(&mlxsw_env->module_info_lock); 773 is_overheat = 774 mlxsw_env->module_info[i].is_overheat; 775 776 if ((is_overheat && sensor_warning) || 777 (!is_overheat && !sensor_warning)) { 778 /* Current state is "warning" and MTWE still reports 779 * warning OR current state in "no warning" and MTWE 780 * does not report warning. 781 */ 782 mutex_unlock(&mlxsw_env->module_info_lock); 783 continue; 784 } else if (is_overheat && !sensor_warning) { 785 /* MTWE reports "no warning", turn is_overheat off. 786 */ 787 mlxsw_env->module_info[i].is_overheat = false; 788 mutex_unlock(&mlxsw_env->module_info_lock); 789 } else { 790 /* Current state is "no warning" and MTWE reports 791 * "warning", increase the counter and turn is_overheat 792 * on. 793 */ 794 mlxsw_env->module_info[i].is_overheat = true; 795 mlxsw_env->module_info[i].module_overheat_counter++; 796 mutex_unlock(&mlxsw_env->module_info_lock); 797 } 798 } 799 800 kfree(event); 801 } 802 803 static void 804 mlxsw_env_mtwe_listener_func(const struct mlxsw_reg_info *reg, char *mtwe_pl, 805 void *priv) 806 { 807 struct mlxsw_env_module_temp_warn_event *event; 808 struct mlxsw_env *mlxsw_env = priv; 809 810 event = kmalloc(sizeof(*event), GFP_ATOMIC); 811 if (!event) 812 return; 813 814 event->mlxsw_env = mlxsw_env; 815 memcpy(event->mtwe_pl, mtwe_pl, MLXSW_REG_MTWE_LEN); 816 INIT_WORK(&event->work, mlxsw_env_mtwe_event_work); 817 mlxsw_core_schedule_work(&event->work); 818 } 819 820 static const struct mlxsw_listener mlxsw_env_temp_warn_listener = 821 MLXSW_CORE_EVENTL(mlxsw_env_mtwe_listener_func, MTWE); 822 823 static int mlxsw_env_temp_warn_event_register(struct mlxsw_core *mlxsw_core) 824 { 825 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 826 827 return mlxsw_core_trap_register(mlxsw_core, 828 &mlxsw_env_temp_warn_listener, 829 mlxsw_env); 830 } 831 832 static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env) 833 { 834 mlxsw_core_trap_unregister(mlxsw_env->core, 835 &mlxsw_env_temp_warn_listener, mlxsw_env); 836 } 837 838 struct mlxsw_env_module_plug_unplug_event { 839 struct mlxsw_env *mlxsw_env; 840 u8 module; 841 struct work_struct work; 842 }; 843 844 static void mlxsw_env_pmpe_event_work(struct work_struct *work) 845 { 846 struct mlxsw_env_module_plug_unplug_event *event; 847 struct mlxsw_env *mlxsw_env; 848 bool has_temp_sensor; 849 u16 sensor_index; 850 int err; 851 852 event = container_of(work, struct mlxsw_env_module_plug_unplug_event, 853 work); 854 mlxsw_env = event->mlxsw_env; 855 856 mutex_lock(&mlxsw_env->module_info_lock); 857 mlxsw_env->module_info[event->module].is_overheat = false; 858 mutex_unlock(&mlxsw_env->module_info_lock); 859 860 err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, event->module, 861 &has_temp_sensor); 862 /* Do not disable events on modules without sensors or faulty sensors 863 * because FW returns errors. 864 */ 865 if (err) 866 goto out; 867 868 if (!has_temp_sensor) 869 goto out; 870 871 sensor_index = event->module + MLXSW_REG_MTMP_MODULE_INDEX_MIN; 872 mlxsw_env_temp_event_set(mlxsw_env->core, sensor_index, true); 873 874 out: 875 kfree(event); 876 } 877 878 static void 879 mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl, 880 void *priv) 881 { 882 struct mlxsw_env_module_plug_unplug_event *event; 883 enum mlxsw_reg_pmpe_module_status module_status; 884 u8 module = mlxsw_reg_pmpe_module_get(pmpe_pl); 885 struct mlxsw_env *mlxsw_env = priv; 886 887 if (WARN_ON_ONCE(module >= mlxsw_env->module_count)) 888 return; 889 890 module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl); 891 if (module_status != MLXSW_REG_PMPE_MODULE_STATUS_PLUGGED_ENABLED) 892 return; 893 894 event = kmalloc(sizeof(*event), GFP_ATOMIC); 895 if (!event) 896 return; 897 898 event->mlxsw_env = mlxsw_env; 899 event->module = module; 900 INIT_WORK(&event->work, mlxsw_env_pmpe_event_work); 901 mlxsw_core_schedule_work(&event->work); 902 } 903 904 static const struct mlxsw_listener mlxsw_env_module_plug_listener = 905 MLXSW_CORE_EVENTL(mlxsw_env_pmpe_listener_func, PMPE); 906 907 static int 908 mlxsw_env_module_plug_event_register(struct mlxsw_core *mlxsw_core) 909 { 910 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 911 912 return mlxsw_core_trap_register(mlxsw_core, 913 &mlxsw_env_module_plug_listener, 914 mlxsw_env); 915 } 916 917 static void 918 mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env) 919 { 920 mlxsw_core_trap_unregister(mlxsw_env->core, 921 &mlxsw_env_module_plug_listener, 922 mlxsw_env); 923 } 924 925 static int 926 mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core) 927 { 928 int i, err; 929 930 for (i = 0; i < mlxsw_core_env(mlxsw_core)->module_count; i++) { 931 char pmaos_pl[MLXSW_REG_PMAOS_LEN]; 932 933 mlxsw_reg_pmaos_pack(pmaos_pl, i); 934 mlxsw_reg_pmaos_e_set(pmaos_pl, 935 MLXSW_REG_PMAOS_E_GENERATE_EVENT); 936 mlxsw_reg_pmaos_ee_set(pmaos_pl, true); 937 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl); 938 if (err) 939 return err; 940 } 941 return 0; 942 } 943 944 int 945 mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module, 946 u64 *p_counter) 947 { 948 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 949 950 mutex_lock(&mlxsw_env->module_info_lock); 951 *p_counter = mlxsw_env->module_info[module].module_overheat_counter; 952 mutex_unlock(&mlxsw_env->module_info_lock); 953 954 return 0; 955 } 956 EXPORT_SYMBOL(mlxsw_env_module_overheat_counter_get); 957 958 void mlxsw_env_module_port_map(struct mlxsw_core *mlxsw_core, u8 module) 959 { 960 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 961 962 mutex_lock(&mlxsw_env->module_info_lock); 963 mlxsw_env->module_info[module].num_ports_mapped++; 964 mutex_unlock(&mlxsw_env->module_info_lock); 965 } 966 EXPORT_SYMBOL(mlxsw_env_module_port_map); 967 968 void mlxsw_env_module_port_unmap(struct mlxsw_core *mlxsw_core, u8 module) 969 { 970 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 971 972 mutex_lock(&mlxsw_env->module_info_lock); 973 mlxsw_env->module_info[module].num_ports_mapped--; 974 mutex_unlock(&mlxsw_env->module_info_lock); 975 } 976 EXPORT_SYMBOL(mlxsw_env_module_port_unmap); 977 978 int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module) 979 { 980 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 981 int err = 0; 982 983 mutex_lock(&mlxsw_env->module_info_lock); 984 985 if (mlxsw_env->module_info[module].power_mode_policy != 986 ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) 987 goto out_inc; 988 989 if (mlxsw_env->module_info[module].num_ports_up != 0) 990 goto out_inc; 991 992 /* Transition to high power mode following first port using the module 993 * being put administratively up. 994 */ 995 err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, false, 996 NULL); 997 if (err) 998 goto out_unlock; 999 1000 out_inc: 1001 mlxsw_env->module_info[module].num_ports_up++; 1002 out_unlock: 1003 mutex_unlock(&mlxsw_env->module_info_lock); 1004 return err; 1005 } 1006 EXPORT_SYMBOL(mlxsw_env_module_port_up); 1007 1008 void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module) 1009 { 1010 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 1011 1012 mutex_lock(&mlxsw_env->module_info_lock); 1013 1014 mlxsw_env->module_info[module].num_ports_up--; 1015 1016 if (mlxsw_env->module_info[module].power_mode_policy != 1017 ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) 1018 goto out_unlock; 1019 1020 if (mlxsw_env->module_info[module].num_ports_up != 0) 1021 goto out_unlock; 1022 1023 /* Transition to low power mode following last port using the module 1024 * being put administratively down. 1025 */ 1026 __mlxsw_env_set_module_power_mode(mlxsw_core, module, true, NULL); 1027 1028 out_unlock: 1029 mutex_unlock(&mlxsw_env->module_info_lock); 1030 } 1031 EXPORT_SYMBOL(mlxsw_env_module_port_down); 1032 1033 static int 1034 mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core) 1035 { 1036 struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core); 1037 int i; 1038 1039 for (i = 0; i < mlxsw_env->module_count; i++) { 1040 char pmtm_pl[MLXSW_REG_PMTM_LEN]; 1041 int err; 1042 1043 mlxsw_reg_pmtm_pack(pmtm_pl, 0, i); 1044 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(pmtm), pmtm_pl); 1045 if (err) 1046 return err; 1047 1048 mlxsw_env->module_info[i].type = 1049 mlxsw_reg_pmtm_module_type_get(pmtm_pl); 1050 } 1051 1052 return 0; 1053 } 1054 1055 int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) 1056 { 1057 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 1058 struct mlxsw_env *env; 1059 u8 module_count; 1060 int i, err; 1061 1062 mlxsw_reg_mgpir_pack(mgpir_pl); 1063 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); 1064 if (err) 1065 return err; 1066 1067 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &module_count); 1068 1069 env = kzalloc(struct_size(env, module_info, module_count), GFP_KERNEL); 1070 if (!env) 1071 return -ENOMEM; 1072 1073 /* Firmware defaults to high power mode policy where modules are 1074 * transitioned to high power mode following plug-in. 1075 */ 1076 for (i = 0; i < module_count; i++) 1077 env->module_info[i].power_mode_policy = 1078 ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH; 1079 1080 mutex_init(&env->module_info_lock); 1081 env->core = mlxsw_core; 1082 env->module_count = module_count; 1083 *p_env = env; 1084 1085 err = mlxsw_env_temp_warn_event_register(mlxsw_core); 1086 if (err) 1087 goto err_temp_warn_event_register; 1088 1089 err = mlxsw_env_module_plug_event_register(mlxsw_core); 1090 if (err) 1091 goto err_module_plug_event_register; 1092 1093 err = mlxsw_env_module_oper_state_event_enable(mlxsw_core); 1094 if (err) 1095 goto err_oper_state_event_enable; 1096 1097 err = mlxsw_env_module_temp_event_enable(mlxsw_core); 1098 if (err) 1099 goto err_temp_event_enable; 1100 1101 err = mlxsw_env_module_type_set(mlxsw_core); 1102 if (err) 1103 goto err_type_set; 1104 1105 return 0; 1106 1107 err_type_set: 1108 err_temp_event_enable: 1109 err_oper_state_event_enable: 1110 mlxsw_env_module_plug_event_unregister(env); 1111 err_module_plug_event_register: 1112 mlxsw_env_temp_warn_event_unregister(env); 1113 err_temp_warn_event_register: 1114 mutex_destroy(&env->module_info_lock); 1115 kfree(env); 1116 return err; 1117 } 1118 1119 void mlxsw_env_fini(struct mlxsw_env *env) 1120 { 1121 mlxsw_env_module_plug_event_unregister(env); 1122 /* Make sure there is no more event work scheduled. */ 1123 mlxsw_core_flush_owq(); 1124 mlxsw_env_temp_warn_event_unregister(env); 1125 mutex_destroy(&env->module_info_lock); 1126 kfree(env); 1127 } 1128