| .. | .. |
|---|
| 30 | 30 | * SOFTWARE. |
|---|
| 31 | 31 | */ |
|---|
| 32 | 32 | |
|---|
| 33 | | -#include <linux/module.h> |
|---|
| 34 | | -#include <linux/mlx5/driver.h> |
|---|
| 35 | 33 | #include <linux/mlx5/port.h> |
|---|
| 36 | | -#include <linux/mlx5/cmd.h> |
|---|
| 37 | 34 | #include "mlx5_core.h" |
|---|
| 38 | 35 | |
|---|
| 39 | 36 | int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, |
|---|
| .. | .. |
|---|
| 157 | 154 | sizeof(out), MLX5_REG_MLCR, 0, 1); |
|---|
| 158 | 155 | } |
|---|
| 159 | 156 | |
|---|
| 160 | | -int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, |
|---|
| 161 | | - u32 *proto_cap, int proto_mask) |
|---|
| 162 | | -{ |
|---|
| 163 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 164 | | - int err; |
|---|
| 165 | | - |
|---|
| 166 | | - err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); |
|---|
| 167 | | - if (err) |
|---|
| 168 | | - return err; |
|---|
| 169 | | - |
|---|
| 170 | | - if (proto_mask == MLX5_PTYS_EN) |
|---|
| 171 | | - *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); |
|---|
| 172 | | - else |
|---|
| 173 | | - *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability); |
|---|
| 174 | | - |
|---|
| 175 | | - return 0; |
|---|
| 176 | | -} |
|---|
| 177 | | -EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap); |
|---|
| 178 | | - |
|---|
| 179 | | -int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev, |
|---|
| 180 | | - u32 *proto_admin, int proto_mask) |
|---|
| 181 | | -{ |
|---|
| 182 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 183 | | - int err; |
|---|
| 184 | | - |
|---|
| 185 | | - err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); |
|---|
| 186 | | - if (err) |
|---|
| 187 | | - return err; |
|---|
| 188 | | - |
|---|
| 189 | | - if (proto_mask == MLX5_PTYS_EN) |
|---|
| 190 | | - *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); |
|---|
| 191 | | - else |
|---|
| 192 | | - *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); |
|---|
| 193 | | - |
|---|
| 194 | | - return 0; |
|---|
| 195 | | -} |
|---|
| 196 | | -EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin); |
|---|
| 197 | | - |
|---|
| 198 | | -int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev, |
|---|
| 199 | | - u8 *link_width_oper, u8 local_port) |
|---|
| 200 | | -{ |
|---|
| 201 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 202 | | - int err; |
|---|
| 203 | | - |
|---|
| 204 | | - err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_IB, local_port); |
|---|
| 205 | | - if (err) |
|---|
| 206 | | - return err; |
|---|
| 207 | | - |
|---|
| 208 | | - *link_width_oper = MLX5_GET(ptys_reg, out, ib_link_width_oper); |
|---|
| 209 | | - |
|---|
| 210 | | - return 0; |
|---|
| 211 | | -} |
|---|
| 212 | | -EXPORT_SYMBOL_GPL(mlx5_query_port_link_width_oper); |
|---|
| 213 | | - |
|---|
| 214 | | -int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev, |
|---|
| 215 | | - u32 *proto_oper, u8 local_port) |
|---|
| 216 | | -{ |
|---|
| 217 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 218 | | - int err; |
|---|
| 219 | | - |
|---|
| 220 | | - err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, |
|---|
| 221 | | - local_port); |
|---|
| 222 | | - if (err) |
|---|
| 223 | | - return err; |
|---|
| 224 | | - |
|---|
| 225 | | - *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); |
|---|
| 226 | | - |
|---|
| 227 | | - return 0; |
|---|
| 228 | | -} |
|---|
| 229 | | -EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper); |
|---|
| 230 | | - |
|---|
| 231 | | -int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev, |
|---|
| 232 | | - u8 *proto_oper, u8 local_port) |
|---|
| 157 | +int mlx5_query_ib_port_oper(struct mlx5_core_dev *dev, u16 *link_width_oper, |
|---|
| 158 | + u16 *proto_oper, u8 local_port) |
|---|
| 233 | 159 | { |
|---|
| 234 | 160 | u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 235 | 161 | int err; |
|---|
| .. | .. |
|---|
| 239 | 165 | if (err) |
|---|
| 240 | 166 | return err; |
|---|
| 241 | 167 | |
|---|
| 168 | + *link_width_oper = MLX5_GET(ptys_reg, out, ib_link_width_oper); |
|---|
| 242 | 169 | *proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper); |
|---|
| 243 | 170 | |
|---|
| 244 | 171 | return 0; |
|---|
| 245 | 172 | } |
|---|
| 246 | | -EXPORT_SYMBOL(mlx5_query_port_ib_proto_oper); |
|---|
| 247 | | - |
|---|
| 248 | | -int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable, |
|---|
| 249 | | - u32 proto_admin, int proto_mask) |
|---|
| 250 | | -{ |
|---|
| 251 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 252 | | - u32 in[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 253 | | - u8 an_disable_admin; |
|---|
| 254 | | - u8 an_disable_cap; |
|---|
| 255 | | - u8 an_status; |
|---|
| 256 | | - |
|---|
| 257 | | - mlx5_query_port_autoneg(dev, proto_mask, &an_status, |
|---|
| 258 | | - &an_disable_cap, &an_disable_admin); |
|---|
| 259 | | - if (!an_disable_cap && an_disable) |
|---|
| 260 | | - return -EPERM; |
|---|
| 261 | | - |
|---|
| 262 | | - memset(in, 0, sizeof(in)); |
|---|
| 263 | | - |
|---|
| 264 | | - MLX5_SET(ptys_reg, in, local_port, 1); |
|---|
| 265 | | - MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); |
|---|
| 266 | | - MLX5_SET(ptys_reg, in, proto_mask, proto_mask); |
|---|
| 267 | | - if (proto_mask == MLX5_PTYS_EN) |
|---|
| 268 | | - MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); |
|---|
| 269 | | - else |
|---|
| 270 | | - MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); |
|---|
| 271 | | - |
|---|
| 272 | | - return mlx5_core_access_reg(dev, in, sizeof(in), out, |
|---|
| 273 | | - sizeof(out), MLX5_REG_PTYS, 0, 1); |
|---|
| 274 | | -} |
|---|
| 275 | | -EXPORT_SYMBOL_GPL(mlx5_set_port_ptys); |
|---|
| 173 | +EXPORT_SYMBOL(mlx5_query_ib_port_oper); |
|---|
| 276 | 174 | |
|---|
| 277 | 175 | /* This function should be used after setting a port register only */ |
|---|
| 278 | 176 | void mlx5_toggle_port_link(struct mlx5_core_dev *dev) |
|---|
| .. | .. |
|---|
| 380 | 278 | return 0; |
|---|
| 381 | 279 | } |
|---|
| 382 | 280 | |
|---|
| 281 | +static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, |
|---|
| 282 | + u8 *module_id) |
|---|
| 283 | +{ |
|---|
| 284 | + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; |
|---|
| 285 | + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; |
|---|
| 286 | + int err, status; |
|---|
| 287 | + u8 *ptr; |
|---|
| 288 | + |
|---|
| 289 | + MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW); |
|---|
| 290 | + MLX5_SET(mcia_reg, in, module, module_num); |
|---|
| 291 | + MLX5_SET(mcia_reg, in, device_address, 0); |
|---|
| 292 | + MLX5_SET(mcia_reg, in, page_number, 0); |
|---|
| 293 | + MLX5_SET(mcia_reg, in, size, 1); |
|---|
| 294 | + MLX5_SET(mcia_reg, in, l, 0); |
|---|
| 295 | + |
|---|
| 296 | + err = mlx5_core_access_reg(dev, in, sizeof(in), out, |
|---|
| 297 | + sizeof(out), MLX5_REG_MCIA, 0, 0); |
|---|
| 298 | + if (err) |
|---|
| 299 | + return err; |
|---|
| 300 | + |
|---|
| 301 | + status = MLX5_GET(mcia_reg, out, status); |
|---|
| 302 | + if (status) { |
|---|
| 303 | + mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", |
|---|
| 304 | + status); |
|---|
| 305 | + return -EIO; |
|---|
| 306 | + } |
|---|
| 307 | + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); |
|---|
| 308 | + |
|---|
| 309 | + *module_id = ptr[0]; |
|---|
| 310 | + |
|---|
| 311 | + return 0; |
|---|
| 312 | +} |
|---|
| 313 | + |
|---|
| 314 | +static int mlx5_qsfp_eeprom_page(u16 offset) |
|---|
| 315 | +{ |
|---|
| 316 | + if (offset < MLX5_EEPROM_PAGE_LENGTH) |
|---|
| 317 | + /* Addresses between 0-255 - page 00 */ |
|---|
| 318 | + return 0; |
|---|
| 319 | + |
|---|
| 320 | + /* Addresses between 256 - 639 belongs to pages 01, 02 and 03 |
|---|
| 321 | + * For example, offset = 400 belongs to page 02: |
|---|
| 322 | + * 1 + ((400 - 256)/128) = 2 |
|---|
| 323 | + */ |
|---|
| 324 | + return 1 + ((offset - MLX5_EEPROM_PAGE_LENGTH) / |
|---|
| 325 | + MLX5_EEPROM_HIGH_PAGE_LENGTH); |
|---|
| 326 | +} |
|---|
| 327 | + |
|---|
| 328 | +static int mlx5_qsfp_eeprom_high_page_offset(int page_num) |
|---|
| 329 | +{ |
|---|
| 330 | + if (!page_num) /* Page 0 always start from low page */ |
|---|
| 331 | + return 0; |
|---|
| 332 | + |
|---|
| 333 | + /* High page */ |
|---|
| 334 | + return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH; |
|---|
| 335 | +} |
|---|
| 336 | + |
|---|
| 337 | +static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset) |
|---|
| 338 | +{ |
|---|
| 339 | + *i2c_addr = MLX5_I2C_ADDR_LOW; |
|---|
| 340 | + *page_num = mlx5_qsfp_eeprom_page(*offset); |
|---|
| 341 | + *offset -= mlx5_qsfp_eeprom_high_page_offset(*page_num); |
|---|
| 342 | +} |
|---|
| 343 | + |
|---|
| 344 | +static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset) |
|---|
| 345 | +{ |
|---|
| 346 | + *i2c_addr = MLX5_I2C_ADDR_LOW; |
|---|
| 347 | + *page_num = 0; |
|---|
| 348 | + |
|---|
| 349 | + if (*offset < MLX5_EEPROM_PAGE_LENGTH) |
|---|
| 350 | + return; |
|---|
| 351 | + |
|---|
| 352 | + *i2c_addr = MLX5_I2C_ADDR_HIGH; |
|---|
| 353 | + *offset -= MLX5_EEPROM_PAGE_LENGTH; |
|---|
| 354 | +} |
|---|
| 355 | + |
|---|
| 383 | 356 | int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, |
|---|
| 384 | 357 | u16 offset, u16 size, u8 *data) |
|---|
| 385 | 358 | { |
|---|
| 359 | + int module_num, status, err, page_num = 0; |
|---|
| 360 | + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; |
|---|
| 386 | 361 | u32 out[MLX5_ST_SZ_DW(mcia_reg)]; |
|---|
| 387 | | - u32 in[MLX5_ST_SZ_DW(mcia_reg)]; |
|---|
| 388 | | - int module_num; |
|---|
| 389 | | - u16 i2c_addr; |
|---|
| 390 | | - int status; |
|---|
| 391 | | - int err; |
|---|
| 392 | | - void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); |
|---|
| 362 | + u16 i2c_addr = 0; |
|---|
| 363 | + u8 module_id; |
|---|
| 364 | + void *ptr; |
|---|
| 393 | 365 | |
|---|
| 394 | 366 | err = mlx5_query_module_num(dev, &module_num); |
|---|
| 395 | 367 | if (err) |
|---|
| 396 | 368 | return err; |
|---|
| 397 | 369 | |
|---|
| 398 | | - memset(in, 0, sizeof(in)); |
|---|
| 399 | | - size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); |
|---|
| 370 | + err = mlx5_query_module_id(dev, module_num, &module_id); |
|---|
| 371 | + if (err) |
|---|
| 372 | + return err; |
|---|
| 400 | 373 | |
|---|
| 401 | | - if (offset < MLX5_EEPROM_PAGE_LENGTH && |
|---|
| 402 | | - offset + size > MLX5_EEPROM_PAGE_LENGTH) |
|---|
| 374 | + switch (module_id) { |
|---|
| 375 | + case MLX5_MODULE_ID_SFP: |
|---|
| 376 | + mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset); |
|---|
| 377 | + break; |
|---|
| 378 | + case MLX5_MODULE_ID_QSFP: |
|---|
| 379 | + case MLX5_MODULE_ID_QSFP_PLUS: |
|---|
| 380 | + case MLX5_MODULE_ID_QSFP28: |
|---|
| 381 | + mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset); |
|---|
| 382 | + break; |
|---|
| 383 | + default: |
|---|
| 384 | + mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id); |
|---|
| 385 | + return -EINVAL; |
|---|
| 386 | + } |
|---|
| 387 | + |
|---|
| 388 | + if (offset + size > MLX5_EEPROM_PAGE_LENGTH) |
|---|
| 403 | 389 | /* Cross pages read, read until offset 256 in low page */ |
|---|
| 404 | 390 | size -= offset + size - MLX5_EEPROM_PAGE_LENGTH; |
|---|
| 405 | 391 | |
|---|
| 406 | | - i2c_addr = MLX5_I2C_ADDR_LOW; |
|---|
| 392 | + size = min_t(int, size, MLX5_EEPROM_MAX_BYTES); |
|---|
| 407 | 393 | |
|---|
| 408 | 394 | MLX5_SET(mcia_reg, in, l, 0); |
|---|
| 409 | 395 | MLX5_SET(mcia_reg, in, module, module_num); |
|---|
| 410 | 396 | MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr); |
|---|
| 411 | | - MLX5_SET(mcia_reg, in, page_number, 0); |
|---|
| 397 | + MLX5_SET(mcia_reg, in, page_number, page_num); |
|---|
| 412 | 398 | MLX5_SET(mcia_reg, in, device_address, offset); |
|---|
| 413 | 399 | MLX5_SET(mcia_reg, in, size, size); |
|---|
| 414 | 400 | |
|---|
| .. | .. |
|---|
| 424 | 410 | return -EIO; |
|---|
| 425 | 411 | } |
|---|
| 426 | 412 | |
|---|
| 413 | + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); |
|---|
| 427 | 414 | memcpy(data, ptr, size); |
|---|
| 428 | 415 | |
|---|
| 429 | 416 | return size; |
|---|
| .. | .. |
|---|
| 601 | 588 | return 0; |
|---|
| 602 | 589 | } |
|---|
| 603 | 590 | EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); |
|---|
| 604 | | - |
|---|
| 605 | | -void mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask, |
|---|
| 606 | | - u8 *an_status, |
|---|
| 607 | | - u8 *an_disable_cap, u8 *an_disable_admin) |
|---|
| 608 | | -{ |
|---|
| 609 | | - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; |
|---|
| 610 | | - |
|---|
| 611 | | - *an_status = 0; |
|---|
| 612 | | - *an_disable_cap = 0; |
|---|
| 613 | | - *an_disable_admin = 0; |
|---|
| 614 | | - |
|---|
| 615 | | - if (mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1)) |
|---|
| 616 | | - return; |
|---|
| 617 | | - |
|---|
| 618 | | - *an_status = MLX5_GET(ptys_reg, out, an_status); |
|---|
| 619 | | - *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); |
|---|
| 620 | | - *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); |
|---|
| 621 | | -} |
|---|
| 622 | | -EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg); |
|---|
| 623 | 591 | |
|---|
| 624 | 592 | int mlx5_max_tc(struct mlx5_core_dev *mdev) |
|---|
| 625 | 593 | { |
|---|
| .. | .. |
|---|
| 841 | 809 | |
|---|
| 842 | 810 | int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode) |
|---|
| 843 | 811 | { |
|---|
| 844 | | - u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {0}; |
|---|
| 845 | | - u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)] = {0}; |
|---|
| 812 | + u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)] = {}; |
|---|
| 846 | 813 | |
|---|
| 847 | 814 | MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL); |
|---|
| 848 | 815 | MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1); |
|---|
| 849 | 816 | MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode); |
|---|
| 850 | | - return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); |
|---|
| 817 | + return mlx5_cmd_exec_in(mdev, set_wol_rol, in); |
|---|
| 851 | 818 | } |
|---|
| 852 | 819 | EXPORT_SYMBOL_GPL(mlx5_set_port_wol); |
|---|
| 853 | 820 | |
|---|
| 854 | 821 | int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode) |
|---|
| 855 | 822 | { |
|---|
| 856 | | - u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {0}; |
|---|
| 857 | | - u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {0}; |
|---|
| 823 | + u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)] = {}; |
|---|
| 824 | + u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)] = {}; |
|---|
| 858 | 825 | int err; |
|---|
| 859 | 826 | |
|---|
| 860 | 827 | MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL); |
|---|
| 861 | | - err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); |
|---|
| 828 | + err = mlx5_cmd_exec_inout(mdev, query_wol_rol, in, out); |
|---|
| 862 | 829 | if (!err) |
|---|
| 863 | 830 | *wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode); |
|---|
| 864 | 831 | |
|---|
| .. | .. |
|---|
| 866 | 833 | } |
|---|
| 867 | 834 | EXPORT_SYMBOL_GPL(mlx5_query_port_wol); |
|---|
| 868 | 835 | |
|---|
| 869 | | -static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, |
|---|
| 870 | | - int outlen) |
|---|
| 836 | +int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen) |
|---|
| 871 | 837 | { |
|---|
| 872 | 838 | u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; |
|---|
| 873 | 839 | |
|---|
| .. | .. |
|---|
| 876 | 842 | outlen, MLX5_REG_PCMR, 0, 0); |
|---|
| 877 | 843 | } |
|---|
| 878 | 844 | |
|---|
| 879 | | -static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) |
|---|
| 845 | +int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) |
|---|
| 880 | 846 | { |
|---|
| 881 | 847 | u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; |
|---|
| 882 | 848 | |
|---|
| .. | .. |
|---|
| 887 | 853 | int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable) |
|---|
| 888 | 854 | { |
|---|
| 889 | 855 | u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; |
|---|
| 856 | + int err; |
|---|
| 890 | 857 | |
|---|
| 858 | + err = mlx5_query_ports_check(mdev, in, sizeof(in)); |
|---|
| 859 | + if (err) |
|---|
| 860 | + return err; |
|---|
| 891 | 861 | MLX5_SET(pcmr_reg, in, local_port, 1); |
|---|
| 892 | 862 | MLX5_SET(pcmr_reg, in, fcs_chk, enable); |
|---|
| 893 | 863 | return mlx5_set_ports_check(mdev, in, sizeof(in)); |
|---|
| .. | .. |
|---|
| 909 | 879 | |
|---|
| 910 | 880 | *supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap)); |
|---|
| 911 | 881 | *enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk)); |
|---|
| 912 | | -} |
|---|
| 913 | | - |
|---|
| 914 | | -static const char *mlx5_pme_status[MLX5_MODULE_STATUS_NUM] = { |
|---|
| 915 | | - "Cable plugged", /* MLX5_MODULE_STATUS_PLUGGED = 0x1 */ |
|---|
| 916 | | - "Cable unplugged", /* MLX5_MODULE_STATUS_UNPLUGGED = 0x2 */ |
|---|
| 917 | | - "Cable error", /* MLX5_MODULE_STATUS_ERROR = 0x3 */ |
|---|
| 918 | | -}; |
|---|
| 919 | | - |
|---|
| 920 | | -static const char *mlx5_pme_error[MLX5_MODULE_EVENT_ERROR_NUM] = { |
|---|
| 921 | | - "Power budget exceeded", |
|---|
| 922 | | - "Long Range for non MLNX cable", |
|---|
| 923 | | - "Bus stuck(I2C or data shorted)", |
|---|
| 924 | | - "No EEPROM/retry timeout", |
|---|
| 925 | | - "Enforce part number list", |
|---|
| 926 | | - "Unknown identifier", |
|---|
| 927 | | - "High Temperature", |
|---|
| 928 | | - "Bad or shorted cable/module", |
|---|
| 929 | | - "Unknown status", |
|---|
| 930 | | -}; |
|---|
| 931 | | - |
|---|
| 932 | | -void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe) |
|---|
| 933 | | -{ |
|---|
| 934 | | - enum port_module_event_status_type module_status; |
|---|
| 935 | | - enum port_module_event_error_type error_type; |
|---|
| 936 | | - struct mlx5_eqe_port_module *module_event_eqe; |
|---|
| 937 | | - struct mlx5_priv *priv = &dev->priv; |
|---|
| 938 | | - u8 module_num; |
|---|
| 939 | | - |
|---|
| 940 | | - module_event_eqe = &eqe->data.port_module; |
|---|
| 941 | | - module_num = module_event_eqe->module; |
|---|
| 942 | | - module_status = module_event_eqe->module_status & |
|---|
| 943 | | - PORT_MODULE_EVENT_MODULE_STATUS_MASK; |
|---|
| 944 | | - error_type = module_event_eqe->error_type & |
|---|
| 945 | | - PORT_MODULE_EVENT_ERROR_TYPE_MASK; |
|---|
| 946 | | - |
|---|
| 947 | | - if (module_status < MLX5_MODULE_STATUS_ERROR) { |
|---|
| 948 | | - priv->pme_stats.status_counters[module_status - 1]++; |
|---|
| 949 | | - } else if (module_status == MLX5_MODULE_STATUS_ERROR) { |
|---|
| 950 | | - if (error_type >= MLX5_MODULE_EVENT_ERROR_UNKNOWN) |
|---|
| 951 | | - /* Unknown error type */ |
|---|
| 952 | | - error_type = MLX5_MODULE_EVENT_ERROR_UNKNOWN; |
|---|
| 953 | | - priv->pme_stats.error_counters[error_type]++; |
|---|
| 954 | | - } |
|---|
| 955 | | - |
|---|
| 956 | | - if (!printk_ratelimit()) |
|---|
| 957 | | - return; |
|---|
| 958 | | - |
|---|
| 959 | | - if (module_status < MLX5_MODULE_STATUS_ERROR) |
|---|
| 960 | | - mlx5_core_info(dev, |
|---|
| 961 | | - "Port module event: module %u, %s\n", |
|---|
| 962 | | - module_num, mlx5_pme_status[module_status - 1]); |
|---|
| 963 | | - |
|---|
| 964 | | - else if (module_status == MLX5_MODULE_STATUS_ERROR) |
|---|
| 965 | | - mlx5_core_info(dev, |
|---|
| 966 | | - "Port module event[error]: module %u, %s, %s\n", |
|---|
| 967 | | - module_num, mlx5_pme_status[module_status - 1], |
|---|
| 968 | | - mlx5_pme_error[error_type]); |
|---|
| 969 | 882 | } |
|---|
| 970 | 883 | |
|---|
| 971 | 884 | int mlx5_query_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size) |
|---|