1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCIe Enclosure management driver created for LED interfaces based on 4 * indications. It says *what indications* blink but does not specify *how* 5 * they blink - it is hardware defined. 6 * 7 * The driver name refers to Native PCIe Enclosure Management. It is 8 * first indication oriented standard with specification. 9 * 10 * Native PCIe Enclosure Management (NPEM) 11 * PCIe Base Specification r6.1 sec 6.28, 7.9.19 12 * 13 * _DSM Definitions for PCIe SSD Status LED 14 * PCI Firmware Specification, r3.3 sec 4.7 15 * 16 * Two backends are supported to manipulate indications: Direct NPEM register 17 * access (npem_ops) and indirect access through the ACPI _DSM (dsm_ops). 18 * _DSM is used if supported, else NPEM. 19 * 20 * Copyright (c) 2021-2022 Dell Inc. 21 * Copyright (c) 2023-2024 Intel Corporation 22 * Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com> 23 */ 24 25 #include <linux/acpi.h> 26 #include <linux/bitops.h> 27 #include <linux/errno.h> 28 #include <linux/iopoll.h> 29 #include <linux/leds.h> 30 #include <linux/mutex.h> 31 #include <linux/pci.h> 32 #include <linux/pci_regs.h> 33 #include <linux/types.h> 34 #include <linux/uleds.h> 35 36 #include "pci.h" 37 38 struct indication { 39 u32 bit; 40 const char *name; 41 }; 42 43 static const struct indication npem_indications[] = { 44 {PCI_NPEM_IND_OK, "enclosure:ok"}, 45 {PCI_NPEM_IND_LOCATE, "enclosure:locate"}, 46 {PCI_NPEM_IND_FAIL, "enclosure:fail"}, 47 {PCI_NPEM_IND_REBUILD, "enclosure:rebuild"}, 48 {PCI_NPEM_IND_PFA, "enclosure:pfa"}, 49 {PCI_NPEM_IND_HOTSPARE, "enclosure:hotspare"}, 50 {PCI_NPEM_IND_ICA, "enclosure:ica"}, 51 {PCI_NPEM_IND_IFA, "enclosure:ifa"}, 52 {PCI_NPEM_IND_IDT, "enclosure:idt"}, 53 {PCI_NPEM_IND_DISABLED, "enclosure:disabled"}, 54 {PCI_NPEM_IND_SPEC_0, "enclosure:specific_0"}, 55 {PCI_NPEM_IND_SPEC_1, "enclosure:specific_1"}, 56 {PCI_NPEM_IND_SPEC_2, "enclosure:specific_2"}, 57 {PCI_NPEM_IND_SPEC_3, "enclosure:specific_3"}, 58 {PCI_NPEM_IND_SPEC_4, "enclosure:specific_4"}, 59 {PCI_NPEM_IND_SPEC_5, "enclosure:specific_5"}, 60 {PCI_NPEM_IND_SPEC_6, "enclosure:specific_6"}, 61 {PCI_NPEM_IND_SPEC_7, "enclosure:specific_7"}, 62 {0, NULL} 63 }; 64 65 /* _DSM PCIe SSD LED States correspond to NPEM register values */ 66 static const struct indication dsm_indications[] = { 67 {PCI_NPEM_IND_OK, "enclosure:ok"}, 68 {PCI_NPEM_IND_LOCATE, "enclosure:locate"}, 69 {PCI_NPEM_IND_FAIL, "enclosure:fail"}, 70 {PCI_NPEM_IND_REBUILD, "enclosure:rebuild"}, 71 {PCI_NPEM_IND_PFA, "enclosure:pfa"}, 72 {PCI_NPEM_IND_HOTSPARE, "enclosure:hotspare"}, 73 {PCI_NPEM_IND_ICA, "enclosure:ica"}, 74 {PCI_NPEM_IND_IFA, "enclosure:ifa"}, 75 {PCI_NPEM_IND_IDT, "enclosure:idt"}, 76 {PCI_NPEM_IND_DISABLED, "enclosure:disabled"}, 77 {0, NULL} 78 }; 79 80 #define for_each_indication(ind, inds) \ 81 for (ind = inds; ind->bit; ind++) 82 83 /* 84 * The driver has internal list of supported indications. Ideally, the driver 85 * should not touch bits that are not defined and for which LED devices are 86 * not exposed but in reality, it needs to turn them off. 87 * 88 * Otherwise, there will be no possibility to turn off indications turned on by 89 * other utilities or turned on by default and it leads to bad user experience. 90 * 91 * Additionally, it excludes NPEM commands like RESET or ENABLE. 92 */ 93 static u32 reg_to_indications(u32 caps, const struct indication *inds) 94 { 95 const struct indication *ind; 96 u32 supported_indications = 0; 97 98 for_each_indication(ind, inds) 99 supported_indications |= ind->bit; 100 101 return caps & supported_indications; 102 } 103 104 /** 105 * struct npem_led - LED details 106 * @indication: indication details 107 * @npem: NPEM device 108 * @name: LED name 109 * @led: LED device 110 */ 111 struct npem_led { 112 const struct indication *indication; 113 struct npem *npem; 114 char name[LED_MAX_NAME_SIZE]; 115 struct led_classdev led; 116 }; 117 118 /** 119 * struct npem_ops - backend specific callbacks 120 * @get_active_indications: get active indications 121 * npem: NPEM device 122 * inds: response buffer 123 * @set_active_indications: set new indications 124 * npem: npem device 125 * inds: bit mask to set 126 * @inds: supported indications array, set of indications is backend specific 127 * @name: backend name 128 */ 129 struct npem_ops { 130 int (*get_active_indications)(struct npem *npem, u32 *inds); 131 int (*set_active_indications)(struct npem *npem, u32 inds); 132 const struct indication *inds; 133 const char *name; 134 }; 135 136 /** 137 * struct npem - NPEM device properties 138 * @dev: PCI device this driver is attached to 139 * @ops: backend specific callbacks 140 * @lock: serializes concurrent access to NPEM device by multiple LED devices 141 * @pos: cached offset of NPEM Capability Register in Configuration Space; 142 * only used if NPEM registers are accessed directly and not through _DSM 143 * @supported_indications: cached bit mask of supported indications; 144 * non-indication and reserved bits in the NPEM Capability Register are 145 * cleared in this bit mask 146 * @active_indications: cached bit mask of active indications; 147 * non-indication and reserved bits in the NPEM Control Register are 148 * cleared in this bit mask 149 * @active_inds_initialized: whether @active_indications has been initialized; 150 * On Dell platforms, it is required that IPMI drivers are loaded before 151 * the GET_STATE_DSM method is invoked: They use an IPMI OpRegion to 152 * get/set the active LEDs. By initializing @active_indications lazily 153 * (on first access to an LED), IPMI drivers are given a chance to load. 154 * If they are not loaded in time, users will see various errors on LED 155 * access in dmesg. Once they are loaded, the errors go away and LED 156 * access becomes possible. 157 * @led_cnt: size of @leds array 158 * @leds: array containing LED class devices of all supported LEDs 159 */ 160 struct npem { 161 struct pci_dev *dev; 162 const struct npem_ops *ops; 163 struct mutex lock; 164 u16 pos; 165 u32 supported_indications; 166 u32 active_indications; 167 unsigned int active_inds_initialized:1; 168 int led_cnt; 169 struct npem_led leds[]; 170 }; 171 172 static int npem_read_reg(struct npem *npem, u16 reg, u32 *val) 173 { 174 int ret = pci_read_config_dword(npem->dev, npem->pos + reg, val); 175 176 return pcibios_err_to_errno(ret); 177 } 178 179 static int npem_write_ctrl(struct npem *npem, u32 reg) 180 { 181 int pos = npem->pos + PCI_NPEM_CTRL; 182 int ret = pci_write_config_dword(npem->dev, pos, reg); 183 184 return pcibios_err_to_errno(ret); 185 } 186 187 static int npem_get_active_indications(struct npem *npem, u32 *inds) 188 { 189 u32 ctrl; 190 int ret; 191 192 ret = npem_read_reg(npem, PCI_NPEM_CTRL, &ctrl); 193 if (ret) 194 return ret; 195 196 /* If PCI_NPEM_CTRL_ENABLE is not set then no indication should blink */ 197 if (!(ctrl & PCI_NPEM_CTRL_ENABLE)) { 198 *inds = 0; 199 return 0; 200 } 201 202 *inds = ctrl & npem->supported_indications; 203 204 return 0; 205 } 206 207 static int npem_set_active_indications(struct npem *npem, u32 inds) 208 { 209 int ctrl, ret, ret_val; 210 u32 cc_status; 211 212 lockdep_assert_held(&npem->lock); 213 214 /* This bit is always required */ 215 ctrl = inds | PCI_NPEM_CTRL_ENABLE; 216 217 ret = npem_write_ctrl(npem, ctrl); 218 if (ret) 219 return ret; 220 221 /* 222 * For the case where a NPEM command has not completed immediately, 223 * it is recommended that software not continuously "spin" on polling 224 * the status register, but rather poll under interrupt at a reduced 225 * rate; for example at 10 ms intervals. 226 * 227 * PCIe r6.1 sec 6.28 "Implementation Note: Software Polling of NPEM 228 * Command Completed" 229 */ 230 ret = read_poll_timeout(npem_read_reg, ret_val, 231 ret_val || (cc_status & PCI_NPEM_STATUS_CC), 232 10 * USEC_PER_MSEC, USEC_PER_SEC, false, npem, 233 PCI_NPEM_STATUS, &cc_status); 234 if (ret) 235 return ret; 236 if (ret_val) 237 return ret_val; 238 239 /* 240 * All writes to control register, including writes that do not change 241 * the register value, are NPEM commands and should eventually result 242 * in a command completion indication in the NPEM Status Register. 243 * 244 * PCIe Base Specification r6.1 sec 7.9.19.3 245 * 246 * Register may not be updated, or other conflicting bits may be 247 * cleared. Spec is not strict here. Read NPEM Control register after 248 * write to keep cache in-sync. 249 */ 250 return npem_get_active_indications(npem, &npem->active_indications); 251 } 252 253 static const struct npem_ops npem_ops = { 254 .get_active_indications = npem_get_active_indications, 255 .set_active_indications = npem_set_active_indications, 256 .name = "Native PCIe Enclosure Management", 257 .inds = npem_indications, 258 }; 259 260 #define DSM_GUID GUID_INIT(0x5d524d9d, 0xfff9, 0x4d4b, 0x8c, 0xb7, 0x74, 0x7e,\ 261 0xd5, 0x1e, 0x19, 0x4d) 262 #define GET_SUPPORTED_STATES_DSM 1 263 #define GET_STATE_DSM 2 264 #define SET_STATE_DSM 3 265 266 static const guid_t dsm_guid = DSM_GUID; 267 268 static bool npem_has_dsm(struct pci_dev *pdev) 269 { 270 acpi_handle handle; 271 272 handle = ACPI_HANDLE(&pdev->dev); 273 if (!handle) 274 return false; 275 276 return acpi_check_dsm(handle, &dsm_guid, 0x1, 277 BIT(GET_SUPPORTED_STATES_DSM) | 278 BIT(GET_STATE_DSM) | BIT(SET_STATE_DSM)); 279 } 280 281 struct dsm_output { 282 u16 status; 283 u8 function_specific_err; 284 u8 vendor_specific_err; 285 u32 state; 286 }; 287 288 /** 289 * dsm_evaluate() - send DSM PCIe SSD Status LED command 290 * @pdev: PCI device 291 * @dsm_func: DSM LED Function 292 * @output: buffer to copy DSM Response 293 * @value_to_set: value for SET_STATE_DSM function 294 * 295 * To not bother caller with ACPI context, the returned _DSM Output Buffer is 296 * copied. 297 */ 298 static int dsm_evaluate(struct pci_dev *pdev, u64 dsm_func, 299 struct dsm_output *output, u32 value_to_set) 300 { 301 acpi_handle handle = ACPI_HANDLE(&pdev->dev); 302 union acpi_object *out_obj, arg3[2]; 303 union acpi_object *arg3_p = NULL; 304 305 if (dsm_func == SET_STATE_DSM) { 306 arg3[0].type = ACPI_TYPE_PACKAGE; 307 arg3[0].package.count = 1; 308 arg3[0].package.elements = &arg3[1]; 309 310 arg3[1].type = ACPI_TYPE_BUFFER; 311 arg3[1].buffer.length = 4; 312 arg3[1].buffer.pointer = (u8 *)&value_to_set; 313 314 arg3_p = arg3; 315 } 316 317 out_obj = acpi_evaluate_dsm_typed(handle, &dsm_guid, 0x1, dsm_func, 318 arg3_p, ACPI_TYPE_BUFFER); 319 if (!out_obj) 320 return -EIO; 321 322 if (out_obj->buffer.length < sizeof(struct dsm_output)) { 323 ACPI_FREE(out_obj); 324 return -EIO; 325 } 326 327 memcpy(output, out_obj->buffer.pointer, sizeof(struct dsm_output)); 328 329 ACPI_FREE(out_obj); 330 return 0; 331 } 332 333 static int dsm_get(struct pci_dev *pdev, u64 dsm_func, u32 *buf) 334 { 335 struct dsm_output output; 336 int ret = dsm_evaluate(pdev, dsm_func, &output, 0); 337 338 if (ret) 339 return ret; 340 341 if (output.status != 0) 342 return -EIO; 343 344 *buf = output.state; 345 return 0; 346 } 347 348 static int dsm_get_active_indications(struct npem *npem, u32 *buf) 349 { 350 int ret = dsm_get(npem->dev, GET_STATE_DSM, buf); 351 352 /* Filter out not supported indications in response */ 353 *buf &= npem->supported_indications; 354 return ret; 355 } 356 357 static int dsm_set_active_indications(struct npem *npem, u32 value) 358 { 359 struct dsm_output output; 360 int ret = dsm_evaluate(npem->dev, SET_STATE_DSM, &output, value); 361 362 if (ret) 363 return ret; 364 365 switch (output.status) { 366 case 4: 367 /* 368 * Not all bits are set. If this bit is set, the platform 369 * disregarded some or all of the request state changes. OSPM 370 * should check the resulting PCIe SSD Status LED States to see 371 * what, if anything, has changed. 372 * 373 * PCI Firmware Specification, r3.3 Table 4-19. 374 */ 375 if (output.function_specific_err != 1) 376 return -EIO; 377 fallthrough; 378 case 0: 379 break; 380 default: 381 return -EIO; 382 } 383 384 npem->active_indications = output.state; 385 386 return 0; 387 } 388 389 static const struct npem_ops dsm_ops = { 390 .get_active_indications = dsm_get_active_indications, 391 .set_active_indications = dsm_set_active_indications, 392 .name = "_DSM PCIe SSD Status LED Management", 393 .inds = dsm_indications, 394 }; 395 396 static int npem_initialize_active_indications(struct npem *npem) 397 { 398 int ret; 399 400 lockdep_assert_held(&npem->lock); 401 402 if (npem->active_inds_initialized) 403 return 0; 404 405 ret = npem->ops->get_active_indications(npem, 406 &npem->active_indications); 407 if (ret) 408 return ret; 409 410 npem->active_inds_initialized = true; 411 return 0; 412 } 413 414 /* 415 * The status of each indicator is cached on first brightness_ get/set time 416 * and updated at write time. brightness_get() is only responsible for 417 * reflecting the last written/cached value. 418 */ 419 static enum led_brightness brightness_get(struct led_classdev *led) 420 { 421 struct npem_led *nled = container_of(led, struct npem_led, led); 422 struct npem *npem = nled->npem; 423 int ret, val = 0; 424 425 ret = mutex_lock_interruptible(&npem->lock); 426 if (ret) 427 return ret; 428 429 ret = npem_initialize_active_indications(npem); 430 if (ret) 431 goto out; 432 433 if (npem->active_indications & nled->indication->bit) 434 val = 1; 435 436 out: 437 mutex_unlock(&npem->lock); 438 return val; 439 } 440 441 static int brightness_set(struct led_classdev *led, 442 enum led_brightness brightness) 443 { 444 struct npem_led *nled = container_of(led, struct npem_led, led); 445 struct npem *npem = nled->npem; 446 u32 indications; 447 int ret; 448 449 ret = mutex_lock_interruptible(&npem->lock); 450 if (ret) 451 return ret; 452 453 ret = npem_initialize_active_indications(npem); 454 if (ret) 455 goto out; 456 457 if (brightness == 0) 458 indications = npem->active_indications & ~(nled->indication->bit); 459 else 460 indications = npem->active_indications | nled->indication->bit; 461 462 ret = npem->ops->set_active_indications(npem, indications); 463 464 out: 465 mutex_unlock(&npem->lock); 466 return ret; 467 } 468 469 static void npem_free(struct npem *npem) 470 { 471 struct npem_led *nled; 472 int cnt; 473 474 if (!npem) 475 return; 476 477 for (cnt = 0; cnt < npem->led_cnt; cnt++) { 478 nled = &npem->leds[cnt]; 479 480 if (nled->name[0]) 481 led_classdev_unregister(&nled->led); 482 } 483 484 mutex_destroy(&npem->lock); 485 kfree(npem); 486 } 487 488 static int pci_npem_set_led_classdev(struct npem *npem, struct npem_led *nled) 489 { 490 struct led_classdev *led = &nled->led; 491 struct led_init_data init_data = {}; 492 char *name = nled->name; 493 int ret; 494 495 init_data.devicename = pci_name(npem->dev); 496 init_data.default_label = nled->indication->name; 497 498 ret = led_compose_name(&npem->dev->dev, &init_data, name); 499 if (ret) 500 return ret; 501 502 led->name = name; 503 led->brightness_set_blocking = brightness_set; 504 led->brightness_get = brightness_get; 505 led->max_brightness = 1; 506 led->default_trigger = "none"; 507 led->flags = 0; 508 509 ret = led_classdev_register(&npem->dev->dev, led); 510 if (ret) 511 /* Clear the name to indicate that it is not registered. */ 512 name[0] = 0; 513 return ret; 514 } 515 516 static int pci_npem_init(struct pci_dev *dev, const struct npem_ops *ops, 517 int pos, u32 caps) 518 { 519 u32 supported = reg_to_indications(caps, ops->inds); 520 int supported_cnt = hweight32(supported); 521 const struct indication *indication; 522 struct npem_led *nled; 523 struct npem *npem; 524 int led_idx = 0; 525 int ret; 526 527 npem = kzalloc(struct_size(npem, leds, supported_cnt), GFP_KERNEL); 528 if (!npem) 529 return -ENOMEM; 530 531 npem->supported_indications = supported; 532 npem->led_cnt = supported_cnt; 533 npem->pos = pos; 534 npem->dev = dev; 535 npem->ops = ops; 536 537 mutex_init(&npem->lock); 538 539 for_each_indication(indication, npem_indications) { 540 if (!(npem->supported_indications & indication->bit)) 541 continue; 542 543 nled = &npem->leds[led_idx++]; 544 nled->indication = indication; 545 nled->npem = npem; 546 547 ret = pci_npem_set_led_classdev(npem, nled); 548 if (ret) { 549 npem_free(npem); 550 return ret; 551 } 552 } 553 554 dev->npem = npem; 555 return 0; 556 } 557 558 void pci_npem_remove(struct pci_dev *dev) 559 { 560 npem_free(dev->npem); 561 } 562 563 void pci_npem_create(struct pci_dev *dev) 564 { 565 const struct npem_ops *ops = &npem_ops; 566 int pos = 0, ret; 567 u32 cap; 568 569 if (npem_has_dsm(dev)) { 570 /* 571 * OS should use the DSM for LED control if it is available 572 * PCI Firmware Spec r3.3 sec 4.7. 573 */ 574 ret = dsm_get(dev, GET_SUPPORTED_STATES_DSM, &cap); 575 if (ret) 576 return; 577 578 ops = &dsm_ops; 579 } else { 580 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_NPEM); 581 if (pos == 0) 582 return; 583 584 if (pci_read_config_dword(dev, pos + PCI_NPEM_CAP, &cap) != 0 || 585 (cap & PCI_NPEM_CAP_CAPABLE) == 0) 586 return; 587 } 588 589 pci_info(dev, "Configuring %s\n", ops->name); 590 591 ret = pci_npem_init(dev, ops, pos, cap); 592 if (ret) 593 pci_err(dev, "Failed to register %s, err: %d\n", ops->name, 594 ret); 595 } 596