History

PCI/NPEM: Add Native PCIe Enclosure Management support

Native PCIe Enclosure Management (NPEM, PCIe r6.1 sec 6.28) allows managing LEDs in storage enclosures. NPEM is indication oriented and it does not give direct access to LEDs. Although each indication *could* represent an individual LED, multiple indications could also be represented as a single, multi-color LED or a single LED blinking in a specific interval. The specification leaves that open. Each enabled indication (capability register bit on) is represented as a ledclass_dev which can be controlled through sysfs. For every ledclass device only 2 brightness states are allowed: LED_ON (1) or LED_OFF (0). This corresponds to the NPEM control register (Indication bit on/off). Ledclass devices appear in sysfs as child devices (subdirectory) of PCI device which has an NPEM Extended Capability and indication is enabled in NPEM capability register. For example, these are LEDs created for pcieport "10000:02:05.0" on my setup: leds/ ├── 10000:02:05.0:enclosure:fail ├── 10000:02:05.0:enclosure:locate ├── 10000:02:05.0:enclosure:ok └── 10000:02:05.0:enclosure:rebuild They can be also found in "/sys/class/leds" directory. The parent PCIe device domain/bus/device/function address is used to guarantee uniqueness across leds subsystem. To enable/disable a "fail" indication, the "brightness" file can be edited: echo 1 > ./leds/10000:02:05.0:enclosure:fail/brightness echo 0 > ./leds/10000:02:05.0:enclosure:fail/brightness PCIe r6.1, sec 7.9.19.2 defines the possible indications. Multiple indications for same parent PCIe device can conflict and hardware may update them when processing new request. To avoid issues, driver refresh all indications by reading back control register. This driver expects to be the exclusive NPEM extended capability manager. It waits up to 1 second after imposing new request, it doesn't verify if controller is busy before write, and it assumes the mutex lock gives protection from concurrent updates. If _DSM LED management is available, we assume the platform may be using NPEM for its own purposes (see PCI Firmware Spec r3.3 sec 4.7), so the driver does not use NPEM. A future patch will add _DSM support; an info message notes whether NPEM or _DSM is being used. NPEM is a PCIe extended capability so it should be registered in pcie_init_capabilities() but it is not possible due to LED dependency. The parent pci_device must be added earlier for led_classdev_register() to be successful. NPEM does not require configuration on kernel side, so it is safe to register LED devices later.

Mariusz Tkaczyk committed 2 years ago

Commit 4e893541 parent 78efa539 files · +546 −0Browse files

Unified · Split

9 files
  1. Documentation/ABI/testing/sysfs-bus-pci +63 −0
  2. drivers/pci/Kconfig +9 −0
  3. drivers/pci/Makefile +1 −0
  4. drivers/pci/npem.c +423 −0
  5. drivers/pci/pci.h +8 −0
  6. drivers/pci/probe.c +2 −0
  7. drivers/pci/remove.c +2 −0
  8. include/linux/pci.h +3 −0
  9. include/uapi/linux/pci_regs.h +35 −0
Documentation/ABI/testing/sysfs-bus-pci+63−0
@@ -500,3 +500,66 @@ Description: · 499 unmodified lines
500 console drivers from the device. Raw users of pci-sysfs500 console drivers from the device. Raw users of pci-sysfs
501 resourceN attributes must be terminated prior to resizing.501 resourceN attributes must be terminated prior to resizing.
502 Success of the resizing operation is not guaranteed.502 Success of the resizing operation is not guaranteed.
503
504What: /sys/bus/pci/devices/.../leds/*:enclosure:*/brightness
505What: /sys/class/leds/*:enclosure:*/brightness
506Date: August 2024
507KernelVersion: 6.12
508Description:
509 LED indications on PCIe storage enclosures which are controlled
510 through the NPEM interface (Native PCIe Enclosure Management,
511 PCIe r6.1 sec 6.28) are accessible as led class devices, both
512 below /sys/class/leds and below NPEM-capable PCI devices.
513
514 Although these led class devices could be manipulated manually,
515 in practice they are typically manipulated automatically by an
516 application such as ledmon(8).
517
518 The name of a led class device is as follows:
519 <bdf>:enclosure:<indication>
520 where:
521
522 - <bdf> is the domain, bus, device and function number
523 (e.g. 10000:02:05.0)
524 - <indication> is a short description of the LED indication
525
526 Valid indications per PCIe r6.1 table 6-27 are:
527
528 - ok (drive is functioning normally)
529 - locate (drive is being identified by an admin)
530 - fail (drive is not functioning properly)
531 - rebuild (drive is part of an array that is rebuilding)
532 - pfa (drive is predicted to fail soon)
533 - hotspare (drive is marked to be used as a replacement)
534 - ica (drive is part of an array that is degraded)
535 - ifa (drive is part of an array that is failed)
536 - idt (drive is not the right type for the connector)
537 - disabled (drive is disabled, removal is safe)
538 - specific0 to specific7 (enclosure-specific indications)
539
540 Broadly, the indications fall into one of these categories:
541
542 - to signify drive state (ok, locate, fail, idt, disabled)
543 - to signify drive role or state in a software RAID array
544 (rebuild, pfa, hotspare, ica, ifa)
545 - to signify any other role or state (specific0 to specific7)
546
547 Mandatory indications per PCIe r6.1 sec 7.9.19.2 comprise:
548 ok, locate, fail, rebuild. All others are optional.
549 A led class device is only visible if the corresponding
550 indication is supported by the device.
551
552 To manipulate the indications, write 0 (LED_OFF) or 1 (LED_ON)
553 to the "brightness" file. Note that manipulating an indication
554 may implicitly manipulate other indications at the vendor's
555 discretion. E.g. when the user lights up the "ok" indication,
556 the vendor may choose to automatically turn off the "fail"
557 indication. The current state of an indication can be
558 retrieved by reading its "brightness" file.
559
560 The PCIe Base Specification allows vendors leeway to choose
561 different colors or blinking patterns for the indications,
562 but they typically follow the IBPI standard. E.g. the "locate"
563 indication is usually presented as one or two LEDs blinking at
564 4 Hz frequency:
565 https://en.wikipedia.org/wiki/International_Blinking_Pattern_Interpretation
drivers/pci/Kconfig+9−0
@@ -143,6 +143,15 @@ config PCI_IOV · 142 unmodified lines
143 143
144 If unsure, say N.144 If unsure, say N.
145 145
146config PCI_NPEM
147 bool "Native PCIe Enclosure Management"
148 depends on LEDS_CLASS=y
149 help
150 Support for Native PCIe Enclosure Management. It allows managing LED
151 indications in storage enclosures. Enclosure must support following
152 indications: OK, Locate, Fail, Rebuild, other indications are
153 optional.
154
146config PCI_PRI155config PCI_PRI
147 bool "PCI PRI support"156 bool "PCI PRI support"
148 select PCI_ATS157 select PCI_ATS
drivers/pci/Makefile+1−0
@@ -35,6 +35,7 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o · 34 unmodified lines
35obj-$(CONFIG_VGA_ARB) += vgaarb.o35obj-$(CONFIG_VGA_ARB) += vgaarb.o
36obj-$(CONFIG_PCI_DOE) += doe.o36obj-$(CONFIG_PCI_DOE) += doe.o
37obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o37obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o
38obj-$(CONFIG_PCI_NPEM) += npem.o
38 39
39# Endpoint library must be initialized before its users40# Endpoint library must be initialized before its users
40obj-$(CONFIG_PCI_ENDPOINT) += endpoint/41obj-$(CONFIG_PCI_ENDPOINT) += endpoint/
drivers/pci/npem.c+423−0
@@ -0,0 +1,423 @@
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 * Copyright (c) 2023-2024 Intel Corporation
14 * Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
15 */
16
17#include <linux/acpi.h>
18#include <linux/bitops.h>
19#include <linux/errno.h>
20#include <linux/iopoll.h>
21#include <linux/leds.h>
22#include <linux/mutex.h>
23#include <linux/pci.h>
24#include <linux/pci_regs.h>
25#include <linux/types.h>
26#include <linux/uleds.h>
27
28#include "pci.h"
29
30struct indication {
31 u32 bit;
32 const char *name;
33};
34
35static const struct indication npem_indications[] = {
36 {PCI_NPEM_IND_OK, "enclosure:ok"},
37 {PCI_NPEM_IND_LOCATE, "enclosure:locate"},
38 {PCI_NPEM_IND_FAIL, "enclosure:fail"},
39 {PCI_NPEM_IND_REBUILD, "enclosure:rebuild"},
40 {PCI_NPEM_IND_PFA, "enclosure:pfa"},
41 {PCI_NPEM_IND_HOTSPARE, "enclosure:hotspare"},
42 {PCI_NPEM_IND_ICA, "enclosure:ica"},
43 {PCI_NPEM_IND_IFA, "enclosure:ifa"},
44 {PCI_NPEM_IND_IDT, "enclosure:idt"},
45 {PCI_NPEM_IND_DISABLED, "enclosure:disabled"},
46 {PCI_NPEM_IND_SPEC_0, "enclosure:specific_0"},
47 {PCI_NPEM_IND_SPEC_1, "enclosure:specific_1"},
48 {PCI_NPEM_IND_SPEC_2, "enclosure:specific_2"},
49 {PCI_NPEM_IND_SPEC_3, "enclosure:specific_3"},
50 {PCI_NPEM_IND_SPEC_4, "enclosure:specific_4"},
51 {PCI_NPEM_IND_SPEC_5, "enclosure:specific_5"},
52 {PCI_NPEM_IND_SPEC_6, "enclosure:specific_6"},
53 {PCI_NPEM_IND_SPEC_7, "enclosure:specific_7"},
54 {0, NULL}
55};
56
57#define for_each_indication(ind, inds) \
58 for (ind = inds; ind->bit; ind++)
59
60/*
61 * The driver has internal list of supported indications. Ideally, the driver
62 * should not touch bits that are not defined and for which LED devices are
63 * not exposed but in reality, it needs to turn them off.
64 *
65 * Otherwise, there will be no possibility to turn off indications turned on by
66 * other utilities or turned on by default and it leads to bad user experience.
67 *
68 * Additionally, it excludes NPEM commands like RESET or ENABLE.
69 */
70static u32 reg_to_indications(u32 caps, const struct indication *inds)
71{
72 const struct indication *ind;
73 u32 supported_indications = 0;
74
75 for_each_indication(ind, inds)
76 supported_indications |= ind->bit;
77
78 return caps & supported_indications;
79}
80
81/**
82 * struct npem_led - LED details
83 * @indication: indication details
84 * @npem: NPEM device
85 * @name: LED name
86 * @led: LED device
87 */
88struct npem_led {
89 const struct indication *indication;
90 struct npem *npem;
91 char name[LED_MAX_NAME_SIZE];
92 struct led_classdev led;
93};
94
95/**
96 * struct npem_ops - backend specific callbacks
97 * @get_active_indications: get active indications
98 * npem: NPEM device
99 * inds: response buffer
100 * @set_active_indications: set new indications
101 * npem: npem device
102 * inds: bit mask to set
103 * @inds: supported indications array, set of indications is backend specific
104 * @name: backend name
105 */
106struct npem_ops {
107 int (*get_active_indications)(struct npem *npem, u32 *inds);
108 int (*set_active_indications)(struct npem *npem, u32 inds);
109 const struct indication *inds;
110 const char *name;
111};
112
113/**
114 * struct npem - NPEM device properties
115 * @dev: PCI device this driver is attached to
116 * @ops: backend specific callbacks
117 * @lock: serializes concurrent access to NPEM device by multiple LED devices
118 * @pos: cached offset of NPEM Capability Register in Configuration Space;
119 * only used if NPEM registers are accessed directly and not through _DSM
120 * @supported_indications: cached bit mask of supported indications;
121 * non-indication and reserved bits in the NPEM Capability Register are
122 * cleared in this bit mask
123 * @active_indications: cached bit mask of active indications;
124 * non-indication and reserved bits in the NPEM Control Register are
125 * cleared in this bit mask
126 * @led_cnt: size of @leds array
127 * @leds: array containing LED class devices of all supported LEDs
128 */
129struct npem {
130 struct pci_dev *dev;
131 const struct npem_ops *ops;
132 struct mutex lock;
133 u16 pos;
134 u32 supported_indications;
135 u32 active_indications;
136 int led_cnt;
137 struct npem_led leds[];
138};
139
140static int npem_read_reg(struct npem *npem, u16 reg, u32 *val)
141{
142 int ret = pci_read_config_dword(npem->dev, npem->pos + reg, val);
143
144 return pcibios_err_to_errno(ret);
145}
146
147static int npem_write_ctrl(struct npem *npem, u32 reg)
148{
149 int pos = npem->pos + PCI_NPEM_CTRL;
150 int ret = pci_write_config_dword(npem->dev, pos, reg);
151
152 return pcibios_err_to_errno(ret);
153}
154
155static int npem_get_active_indications(struct npem *npem, u32 *inds)
156{
157 u32 ctrl;
158 int ret;
159
160 ret = npem_read_reg(npem, PCI_NPEM_CTRL, &ctrl);
161 if (ret)
162 return ret;
163
164 /* If PCI_NPEM_CTRL_ENABLE is not set then no indication should blink */
165 if (!(ctrl & PCI_NPEM_CTRL_ENABLE)) {
166 *inds = 0;
167 return 0;
168 }
169
170 *inds = ctrl & npem->supported_indications;
171
172 return 0;
173}
174
175static int npem_set_active_indications(struct npem *npem, u32 inds)
176{
177 int ctrl, ret, ret_val;
178 u32 cc_status;
179
180 lockdep_assert_held(&npem->lock);
181
182 /* This bit is always required */
183 ctrl = inds | PCI_NPEM_CTRL_ENABLE;
184
185 ret = npem_write_ctrl(npem, ctrl);
186 if (ret)
187 return ret;
188
189 /*
190 * For the case where a NPEM command has not completed immediately,
191 * it is recommended that software not continuously "spin" on polling
192 * the status register, but rather poll under interrupt at a reduced
193 * rate; for example at 10 ms intervals.
194 *
195 * PCIe r6.1 sec 6.28 "Implementation Note: Software Polling of NPEM
196 * Command Completed"
197 */
198 ret = read_poll_timeout(npem_read_reg, ret_val,
199 ret_val || (cc_status & PCI_NPEM_STATUS_CC),
200 10 * USEC_PER_MSEC, USEC_PER_SEC, false, npem,
201 PCI_NPEM_STATUS, &cc_status);
202 if (ret)
203 return ret;
204 if (ret_val)
205 return ret_val;
206
207 /*
208 * All writes to control register, including writes that do not change
209 * the register value, are NPEM commands and should eventually result
210 * in a command completion indication in the NPEM Status Register.
211 *
212 * PCIe Base Specification r6.1 sec 7.9.19.3
213 *
214 * Register may not be updated, or other conflicting bits may be
215 * cleared. Spec is not strict here. Read NPEM Control register after
216 * write to keep cache in-sync.
217 */
218 return npem_get_active_indications(npem, &npem->active_indications);
219}
220
221static const struct npem_ops npem_ops = {
222 .get_active_indications = npem_get_active_indications,
223 .set_active_indications = npem_set_active_indications,
224 .name = "Native PCIe Enclosure Management",
225 .inds = npem_indications,
226};
227
228#define DSM_GUID GUID_INIT(0x5d524d9d, 0xfff9, 0x4d4b, 0x8c, 0xb7, 0x74, 0x7e,\
229 0xd5, 0x1e, 0x19, 0x4d)
230#define GET_SUPPORTED_STATES_DSM 1
231#define GET_STATE_DSM 2
232#define SET_STATE_DSM 3
233
234static const guid_t dsm_guid = DSM_GUID;
235
236static bool npem_has_dsm(struct pci_dev *pdev)
237{
238 acpi_handle handle;
239
240 handle = ACPI_HANDLE(&pdev->dev);
241 if (!handle)
242 return false;
243
244 return acpi_check_dsm(handle, &dsm_guid, 0x1,
245 BIT(GET_SUPPORTED_STATES_DSM) |
246 BIT(GET_STATE_DSM) | BIT(SET_STATE_DSM));
247}
248
249/*
250 * The status of each indicator is cached on first brightness_ get/set time
251 * and updated at write time. brightness_get() is only responsible for
252 * reflecting the last written/cached value.
253 */
254static enum led_brightness brightness_get(struct led_classdev *led)
255{
256 struct npem_led *nled = container_of(led, struct npem_led, led);
257 struct npem *npem = nled->npem;
258 int ret, val = 0;
259
260 ret = mutex_lock_interruptible(&npem->lock);
261 if (ret)
262 return ret;
263
264 if (npem->active_indications & nled->indication->bit)
265 val = 1;
266
267 mutex_unlock(&npem->lock);
268 return val;
269}
270
271static int brightness_set(struct led_classdev *led,
272 enum led_brightness brightness)
273{
274 struct npem_led *nled = container_of(led, struct npem_led, led);
275 struct npem *npem = nled->npem;
276 u32 indications;
277 int ret;
278
279 ret = mutex_lock_interruptible(&npem->lock);
280 if (ret)
281 return ret;
282
283 if (brightness == 0)
284 indications = npem->active_indications & ~(nled->indication->bit);
285 else
286 indications = npem->active_indications | nled->indication->bit;
287
288 ret = npem->ops->set_active_indications(npem, indications);
289
290 mutex_unlock(&npem->lock);
291 return ret;
292}
293
294static void npem_free(struct npem *npem)
295{
296 struct npem_led *nled;
297 int cnt;
298
299 if (!npem)
300 return;
301
302 for (cnt = 0; cnt < npem->led_cnt; cnt++) {
303 nled = &npem->leds[cnt];
304
305 if (nled->name[0])
306 led_classdev_unregister(&nled->led);
307 }
308
309 mutex_destroy(&npem->lock);
310 kfree(npem);
311}
312
313static int pci_npem_set_led_classdev(struct npem *npem, struct npem_led *nled)
314{
315 struct led_classdev *led = &nled->led;
316 struct led_init_data init_data = {};
317 char *name = nled->name;
318 int ret;
319
320 init_data.devicename = pci_name(npem->dev);
321 init_data.default_label = nled->indication->name;
322
323 ret = led_compose_name(&npem->dev->dev, &init_data, name);
324 if (ret)
325 return ret;
326
327 led->name = name;
328 led->brightness_set_blocking = brightness_set;
329 led->brightness_get = brightness_get;
330 led->max_brightness = 1;
331 led->default_trigger = "none";
332 led->flags = 0;
333
334 ret = led_classdev_register(&npem->dev->dev, led);
335 if (ret)
336 /* Clear the name to indicate that it is not registered. */
337 name[0] = 0;
338 return ret;
339}
340
341static int pci_npem_init(struct pci_dev *dev, const struct npem_ops *ops,
342 int pos, u32 caps)
343{
344 u32 supported = reg_to_indications(caps, ops->inds);
345 int supported_cnt = hweight32(supported);
346 const struct indication *indication;
347 struct npem_led *nled;
348 struct npem *npem;
349 int led_idx = 0;
350 int ret;
351
352 npem = kzalloc(struct_size(npem, leds, supported_cnt), GFP_KERNEL);
353 if (!npem)
354 return -ENOMEM;
355
356 npem->supported_indications = supported;
357 npem->led_cnt = supported_cnt;
358 npem->pos = pos;
359 npem->dev = dev;
360 npem->ops = ops;
361
362 ret = npem->ops->get_active_indications(npem,
363 &npem->active_indications);
364 if (ret)
365 return ret;
366
367 mutex_init(&npem->lock);
368
369 for_each_indication(indication, npem_indications) {
370 if (!(npem->supported_indications & indication->bit))
371 continue;
372
373 nled = &npem->leds[led_idx++];
374 nled->indication = indication;
375 nled->npem = npem;
376
377 ret = pci_npem_set_led_classdev(npem, nled);
378 if (ret) {
379 npem_free(npem);
380 return ret;
381 }
382 }
383
384 dev->npem = npem;
385 return 0;
386}
387
388void pci_npem_remove(struct pci_dev *dev)
389{
390 npem_free(dev->npem);
391}
392
393void pci_npem_create(struct pci_dev *dev)
394{
395 const struct npem_ops *ops = &npem_ops;
396 int pos = 0, ret;
397 u32 cap;
398
399 if (npem_has_dsm(dev)) {
400 /*
401 * OS should use the DSM for LED control if it is available
402 * PCI Firmware Spec r3.3 sec 4.7.
403 */
404 pci_info(dev, "Not configuring %s because _DSM is present\n",
405 ops->name);
406 return;
407 } else {
408 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_NPEM);
409 if (pos == 0)
410 return;
411
412 if (pci_read_config_dword(dev, pos + PCI_NPEM_CAP, &cap) != 0 ||
413 (cap & PCI_NPEM_CAP_CAPABLE) == 0)
414 return;
415 }
416
417 pci_info(dev, "Configuring %s\n", ops->name);
418
419 ret = pci_npem_init(dev, ops, pos, cap);
420 if (ret)
421 pci_err(dev, "Failed to register %s, err: %d\n", ops->name,
422 ret);
423}
drivers/pci/pci.h+8−0
@@ -398,6 +398,14 @@ static inline void pci_doe_destroy(struct pci_dev *pdev) { } · 397 unmodified lines
398static inline void pci_doe_disconnected(struct pci_dev *pdev) { }398static inline void pci_doe_disconnected(struct pci_dev *pdev) { }
399#endif399#endif
400 400
401#ifdef CONFIG_PCI_NPEM
402void pci_npem_create(struct pci_dev *dev);
403void pci_npem_remove(struct pci_dev *dev);
404#else
405static inline void pci_npem_create(struct pci_dev *dev) { }
406static inline void pci_npem_remove(struct pci_dev *dev) { }
407#endif
408
401/**409/**
402 * pci_dev_set_io_state - Set the new error state if possible.410 * pci_dev_set_io_state - Set the new error state if possible.
403 *411 *
drivers/pci/probe.c+2−0
@@ -2593,6 +2593,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) · 2592 unmodified lines
2593 dev->match_driver = false;2593 dev->match_driver = false;
2594 ret = device_add(&dev->dev);2594 ret = device_add(&dev->dev);
2595 WARN_ON(ret < 0);2595 WARN_ON(ret < 0);
2596
2597 pci_npem_create(dev);
2596}2598}
2597 2599
2598struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)2600struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
drivers/pci/remove.c+2−0
@@ -34,6 +34,8 @@ static void pci_destroy_dev(struct pci_dev *dev) · 33 unmodified lines
34 if (!dev->dev.kobj.parent)34 if (!dev->dev.kobj.parent)
35 return;35 return;
36 36
37 pci_npem_remove(dev);
38
37 device_del(&dev->dev);39 device_del(&dev->dev);
38 40
39 down_write(&pci_bus_sem);41 down_write(&pci_bus_sem);
include/linux/pci.h+3−0
@@ -516,6 +516,9 @@ struct pci_dev { · 515 unmodified lines
516#endif516#endif
517#ifdef CONFIG_PCI_DOE517#ifdef CONFIG_PCI_DOE
518 struct xarray doe_mbs; /* Data Object Exchange mailboxes */518 struct xarray doe_mbs; /* Data Object Exchange mailboxes */
519#endif
520#ifdef CONFIG_PCI_NPEM
521 struct npem *npem; /* Native PCIe Enclosure Management */
519#endif522#endif
520 u16 acs_cap; /* ACS Capability offset */523 u16 acs_cap; /* ACS Capability offset */
521 phys_addr_t rom; /* Physical address if not from BAR */524 phys_addr_t rom; /* Physical address if not from BAR */
include/uapi/linux/pci_regs.h+35−0
@@ -740,6 +740,7 @@ · 739 unmodified lines
740#define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */740#define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */
741#define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */741#define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */
742#define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */742#define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */
743#define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */
743#define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */744#define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */
744#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */745#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */
745#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE746#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE
@@ -1121,6 +1122,40 @@ · 375 unmodified lines
1121#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F01122#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0
1122#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 41123#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4
1123 1124
1125/* Native PCIe Enclosure Management */
1126#define PCI_NPEM_CAP 0x04 /* NPEM capability register */
1127#define PCI_NPEM_CAP_CAPABLE 0x00000001 /* NPEM Capable */
1128
1129#define PCI_NPEM_CTRL 0x08 /* NPEM control register */
1130#define PCI_NPEM_CTRL_ENABLE 0x00000001 /* NPEM Enable */
1131
1132/*
1133 * Native PCIe Enclosure Management indication bits and Reset command bit
1134 * are corresponding for capability and control registers.
1135 */
1136#define PCI_NPEM_CMD_RESET 0x00000002 /* Reset Command */
1137#define PCI_NPEM_IND_OK 0x00000004 /* OK */
1138#define PCI_NPEM_IND_LOCATE 0x00000008 /* Locate */
1139#define PCI_NPEM_IND_FAIL 0x00000010 /* Fail */
1140#define PCI_NPEM_IND_REBUILD 0x00000020 /* Rebuild */
1141#define PCI_NPEM_IND_PFA 0x00000040 /* Predicted Failure Analysis */
1142#define PCI_NPEM_IND_HOTSPARE 0x00000080 /* Hot Spare */
1143#define PCI_NPEM_IND_ICA 0x00000100 /* In Critical Array */
1144#define PCI_NPEM_IND_IFA 0x00000200 /* In Failed Array */
1145#define PCI_NPEM_IND_IDT 0x00000400 /* Device Type */
1146#define PCI_NPEM_IND_DISABLED 0x00000800 /* Disabled */
1147#define PCI_NPEM_IND_SPEC_0 0x01000000
1148#define PCI_NPEM_IND_SPEC_1 0x02000000
1149#define PCI_NPEM_IND_SPEC_2 0x04000000
1150#define PCI_NPEM_IND_SPEC_3 0x08000000
1151#define PCI_NPEM_IND_SPEC_4 0x10000000
1152#define PCI_NPEM_IND_SPEC_5 0x20000000
1153#define PCI_NPEM_IND_SPEC_6 0x40000000
1154#define PCI_NPEM_IND_SPEC_7 0x80000000
1155
1156#define PCI_NPEM_STATUS 0x0c /* NPEM status register */
1157#define PCI_NPEM_STATUS_CC 0x00000001 /* Command Completed */
1158
1124/* Data Object Exchange */1159/* Data Object Exchange */
1125#define PCI_DOE_CAP 0x04 /* DOE Capabilities Register */1160#define PCI_DOE_CAP 0x04 /* DOE Capabilities Register */
1126#define PCI_DOE_CAP_INT_SUP 0x00000001 /* Interrupt Support */1161#define PCI_DOE_CAP_INT_SUP 0x00000001 /* Interrupt Support */