1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2016, Google, Inc. All rights reserved
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7
8 #include <arch/mmu.h>
9 #include <assert.h>
10 #include <debug.h>
11 #include <dev/interrupt.h>
12 #include <dev/pcie_bridge.h>
13 #include <dev/pcie_bus_driver.h>
14 #include <dev/pcie_device.h>
15 #include <err.h>
16 #include <fbl/algorithm.h>
17 #include <fbl/auto_lock.h>
18 #include <fbl/limits.h>
19 #include <inttypes.h>
20 #include <kernel/spinlock.h>
21 #include <lk/init.h>
22 #include <platform.h>
23 #include <string.h>
24 #include <trace.h>
25 #include <vm/arch_vm_aspace.h>
26 #include <vm/vm.h>
27 #include <zircon/compiler.h>
28 #include <zircon/time.h>
29 #include <zircon/types.h>
30
31 #include <fbl/alloc_checker.h>
32
33 using fbl::AutoLock;
34
35 #define LOCAL_TRACE 0
36
37 namespace { // anon namespace. Externals do not need to know about PcieDeviceImpl
38 class PcieDeviceImpl : public PcieDevice {
39 public:
40 static fbl::RefPtr<PcieDevice> Create(PcieUpstreamNode& upstream, uint dev_id, uint func_id);
41
42 // Disallow copying, assigning and moving.
43 DISALLOW_COPY_ASSIGN_AND_MOVE(PcieDeviceImpl);
44
45 // Implement ref counting, do not let derived classes override.
46 PCIE_IMPLEMENT_REFCOUNTED;
47
48 protected:
PcieDeviceImpl(PcieBusDriver & bus_drv,uint bus_id,uint dev_id,uint func_id)49 PcieDeviceImpl(PcieBusDriver& bus_drv, uint bus_id, uint dev_id, uint func_id)
50 : PcieDevice(bus_drv, bus_id, dev_id, func_id, false) { }
51 };
52
Create(PcieUpstreamNode & upstream,uint dev_id,uint func_id)53 fbl::RefPtr<PcieDevice> PcieDeviceImpl::Create(PcieUpstreamNode& upstream,
54 uint dev_id, uint func_id) {
55 fbl::AllocChecker ac;
56 auto raw_dev = new (&ac) PcieDeviceImpl(upstream.driver(),
57 upstream.managed_bus_id(),
58 dev_id,
59 func_id);
60 if (!ac.check()) {
61 TRACEF("Out of memory attemping to create PCIe device %02x:%02x.%01x.\n",
62 upstream.managed_bus_id(), dev_id, func_id);
63 return nullptr;
64 }
65
66 auto dev = fbl::AdoptRef(static_cast<PcieDevice*>(raw_dev));
67 zx_status_t res = raw_dev->Init(upstream);
68 if (res != ZX_OK) {
69 TRACEF("Failed to initialize PCIe device %02x:%02x.%01x. (res %d)\n",
70 upstream.managed_bus_id(), dev_id, func_id, res);
71 return nullptr;
72 }
73
74 return dev;
75 }
76 } // namespace
77
PcieDevice(PcieBusDriver & bus_drv,uint bus_id,uint dev_id,uint func_id,bool is_bridge)78 PcieDevice::PcieDevice(PcieBusDriver& bus_drv,
79 uint bus_id, uint dev_id, uint func_id, bool is_bridge)
80 : bus_drv_(bus_drv),
81 is_bridge_(is_bridge),
82 bus_id_(bus_id),
83 dev_id_(dev_id),
84 func_id_(func_id),
85 bar_count_(is_bridge ? PCIE_BAR_REGS_PER_BRIDGE : PCIE_BAR_REGS_PER_DEVICE) {
86 }
87
~PcieDevice()88 PcieDevice::~PcieDevice() {
89 /* We should already be unlinked from the bus's device tree. */
90 DEBUG_ASSERT(!upstream_);
91 DEBUG_ASSERT(!plugged_in_);
92
93 /* TODO(johngro) : ASSERT that this device no longer participating in any of
94 * the bus driver's shared IRQ dispatching. */
95
96 /* Make certain that all bus access (MMIO, PIO, Bus mastering) has been
97 * disabled. Also, explicitly disable legacy IRQs */
98 if (cfg_)
99 cfg_->Write(PciConfig::kCommand, PCIE_CFG_COMMAND_INT_DISABLE);
100 }
101
Create(PcieUpstreamNode & upstream,uint dev_id,uint func_id)102 fbl::RefPtr<PcieDevice> PcieDevice::Create(PcieUpstreamNode& upstream, uint dev_id, uint func_id) {
103 return PcieDeviceImpl::Create(upstream, dev_id, func_id);
104 }
105
Init(PcieUpstreamNode & upstream)106 zx_status_t PcieDevice::Init(PcieUpstreamNode& upstream) {
107 AutoLock dev_lock(&dev_lock_);
108
109 zx_status_t res = InitLocked(upstream);
110 if (res == ZX_OK) {
111 // Things went well, flag the device as plugged in and link ourselves up to
112 // the graph.
113 plugged_in_ = true;
114 bus_drv_.LinkDeviceToUpstream(*this, upstream);
115 }
116
117 return res;
118 }
119
InitLocked(PcieUpstreamNode & upstream)120 zx_status_t PcieDevice::InitLocked(PcieUpstreamNode& upstream) {
121 zx_status_t res;
122 DEBUG_ASSERT(dev_lock_.IsHeld());
123 DEBUG_ASSERT(cfg_ == nullptr);
124
125 cfg_ = bus_drv_.GetConfig(bus_id_, dev_id_, func_id_, &cfg_phys_);
126 if (cfg_ == nullptr) {
127 TRACEF("Failed to fetch config for device %02x:%02x.%01x.\n", bus_id_, dev_id_, func_id_);
128 return ZX_ERR_BAD_STATE;
129 }
130
131 // Cache basic device info
132 vendor_id_ = cfg_->Read(PciConfig::kVendorId);
133 device_id_ = cfg_->Read(PciConfig::kDeviceId);
134 class_id_ = cfg_->Read(PciConfig::kBaseClass);
135 subclass_ = cfg_->Read(PciConfig::kSubClass);
136 prog_if_ = cfg_->Read(PciConfig::kProgramInterface);
137 rev_id_ = cfg_->Read(PciConfig::kRevisionId);
138
139 // Determine the details of each of the BARs, but do not actually allocate
140 // space on the bus for them yet.
141 res = ProbeBarsLocked();
142 if (res != ZX_OK)
143 return res;
144
145 // Parse and sanity check the capabilities and extended capabilities lists
146 // if they exist
147 res = ProbeCapabilitiesLocked();
148 if (res != ZX_OK)
149 return res;
150
151 // Now that we know what our capabilities are, initialize our internal IRQ
152 // bookkeeping
153 res = InitLegacyIrqStateLocked(upstream);
154 if (res != ZX_OK)
155 return res;
156
157 return ZX_OK;
158 }
159
GetUpstream()160 fbl::RefPtr<PcieUpstreamNode> PcieDevice::GetUpstream() {
161 return bus_drv_.GetUpstream(*this);
162 }
163
Unplug()164 void PcieDevice::Unplug() {
165 /* Begin by completely nerfing this device, and preventing an new API
166 * operations on it. We need to be inside the dev lock to do this. Note:
167 * it is assumed that we will not disappear during any of this function,
168 * because our caller is holding a reference to us. */
169 AutoLock dev_lock(&dev_lock_);
170
171 if (plugged_in_) {
172 /* Remove all access this device has to the PCI bus */
173 cfg_->Write(PciConfig::kCommand, PCIE_CFG_COMMAND_INT_DISABLE);
174
175 /* TODO(johngro) : Make sure that our interrupt mode has been set to
176 * completely disabled. Do not return allocated BARs to the central
177 * pool yet. These regions of the physical bus need to remain
178 * "allocated" until all drivers/users in the system release their last
179 * reference to the device. This way, if the device gets plugged in
180 * again immediately, the new version of the device will not end up
181 * getting mapped underneath any stale driver instances. */
182
183 plugged_in_ = false;
184 } else {
185 /* TODO(johngro) : Assert that the device has been completely disabled. */
186 }
187
188 /* Unlink ourselves from our upstream parent (if we still have one). */
189 bus_drv_.UnlinkDeviceFromUpstream(*this);
190 }
191
DoFunctionLevelReset()192 zx_status_t PcieDevice::DoFunctionLevelReset() {
193 zx_status_t ret;
194
195 // TODO(johngro) : Function level reset is an operation which can take quite
196 // a long time (more than a second). We should not hold the device lock for
197 // the entire duration of the operation. This should be re-done so that the
198 // device can be placed into a "resetting" state (and other API calls can
199 // fail with ZX_ERR_BAD_STATE, or some-such) and the lock can be released while the
200 // reset timeouts run. This way, a spontaneous unplug event can occur and
201 // not block the whole world because the device unplugged was in the process
202 // of a FLR.
203 AutoLock dev_lock(&dev_lock_);
204
205 // Make certain to check to see if the device is still plugged in.
206 if (!plugged_in_)
207 return ZX_ERR_UNAVAILABLE;
208
209 // Disallow reset if we currently have an active IRQ mode.
210 //
211 // Note: the only possible reason for get_irq_mode to fail would be for the
212 // device to be unplugged. Since we have already checked for that, we
213 // assert that the call should succeed.
214 pcie_irq_mode_info_t irq_mode_info;
215 ret = GetIrqModeLocked(&irq_mode_info);
216 DEBUG_ASSERT(ZX_OK == ret);
217
218 if (irq_mode_info.mode != PCIE_IRQ_MODE_DISABLED)
219 return ZX_ERR_BAD_STATE;
220
221 DEBUG_ASSERT(!irq_mode_info.registered_handlers);
222 DEBUG_ASSERT(!irq_mode_info.max_handlers);
223
224 // If cannot reset via the PCIe capability, or the PCI advanced capability,
225 // then this device simply does not support function level reset.
226 if (!(pcie_ && pcie_->has_flr()) && !(pci_af_ && pci_af_->has_flr()))
227 return ZX_ERR_NOT_SUPPORTED;
228
229 // Pick the functions we need for testing whether or not transactions are
230 // pending for this device, and for initiating the FLR
231 bool (*check_trans_pending)(void* ctx);
232 void (*initiate_flr)(void* ctx);
233
234 if (pcie_ && pcie_->has_flr()) {
235 check_trans_pending = [](void* ctx) -> bool {
236 auto thiz = reinterpret_cast<PcieDevice*>(ctx);
237 return thiz->cfg_->Read(thiz->pcie_->device.status()) &
238 PCS_DEV_STS_TRANSACTIONS_PENDING;
239 };
240 initiate_flr = [](void* ctx) {
241 auto thiz = reinterpret_cast<PcieDevice*>(ctx);
242 auto val = static_cast<uint16_t>(thiz->cfg_->Read(thiz->pcie_->device.ctrl()) |
243 PCS_DEV_CTRL_INITIATE_FLR);
244 thiz->cfg_->Write(thiz->pcie_->device.ctrl(), val);
245 };
246 } else {
247 check_trans_pending = [](void* ctx) -> bool {
248 auto thiz = reinterpret_cast<PcieDevice*>(ctx);
249 return thiz->cfg_->Read(thiz->pci_af_->af_status()) & PCS_ADVCAPS_STATUS_TRANS_PENDING;
250 };
251 initiate_flr = [](void* ctx) {
252 auto thiz = reinterpret_cast<PcieDevice*>(ctx);
253 thiz->cfg_->Write(thiz->pci_af_->af_ctrl(), PCS_ADVCAPS_CTRL_INITIATE_FLR);
254 };
255 }
256
257 // Following the procedure outlined in the Implementation notes
258 uint32_t bar_backup[PCIE_MAX_BAR_REGS];
259 uint16_t cmd_backup;
260
261 // 1) Make sure driver code is not creating new transactions (not much I
262 // can do about this, just have to hope).
263 // 2) Clear out the command register so that no new transactions may be
264 // initiated. Also back up the BARs in the process.
265 {
266 DEBUG_ASSERT(irq_.legacy.shared_handler != nullptr);
267 AutoSpinLock cmd_reg_lock(&cmd_reg_lock_);
268
269 cmd_backup = cfg_->Read(PciConfig::kCommand);
270 cfg_->Write(PciConfig::kCommand, PCIE_CFG_COMMAND_INT_DISABLE);
271 for (uint i = 0; i < bar_count_; ++i)
272 bar_backup[i] = cfg_->Read(PciConfig::kBAR(i));
273 }
274
275 // 3) Poll the transaction pending bit until it clears. This may take
276 // "several seconds"
277 zx_time_t start = current_time();
278 ret = ZX_ERR_TIMED_OUT;
279 do {
280 if (!check_trans_pending(this)) {
281 ret = ZX_OK;
282 break;
283 }
284 thread_sleep_relative(ZX_MSEC(1));
285 } while (zx_time_sub_time(current_time(), start) < ZX_SEC(5));
286
287 if (ret != ZX_OK) {
288 TRACEF("Timeout waiting for pending transactions to clear the bus "
289 "for %02x:%02x.%01x\n",
290 bus_id_, dev_id_, func_id_);
291
292 // Restore the command register
293 AutoSpinLock cmd_reg_lock(&cmd_reg_lock_);
294 cfg_->Write(PciConfig::kCommand, cmd_backup);
295
296 return ret;
297 } else {
298 // 4) Software initiates the FLR
299 initiate_flr(this);
300
301 // 5) Software waits 100mSec
302 thread_sleep_relative(ZX_MSEC(100));
303 }
304
305 // NOTE: Even though the spec says that the reset operation is supposed
306 // to always take less than 100mSec, no one really follows this rule.
307 // Generally speaking, when a device resets, config read cycles will
308 // return all 0xFFs until the device finally resets and comes back.
309 // Poll the Vendor ID field until the device finally completes it's
310 // reset.
311 start = current_time();
312 ret = ZX_ERR_TIMED_OUT;
313 do {
314 if (cfg_->Read(PciConfig::kVendorId) != PCIE_INVALID_VENDOR_ID) {
315 ret = ZX_OK;
316 break;
317 }
318 thread_sleep_relative(ZX_MSEC(1));
319 } while (zx_time_sub_time(current_time(), start) < ZX_SEC(5));
320
321 if (ret == ZX_OK) {
322 // 6) Software reconfigures the function and enables it for normal operation
323 AutoSpinLock cmd_reg_lock(&cmd_reg_lock_);
324
325 for (uint i = 0; i < bar_count_; ++i)
326 cfg_->Write(PciConfig::kBAR(i), bar_backup[i]);
327 cfg_->Write(PciConfig::kCommand, cmd_backup);
328 } else {
329 // TODO(johngro) : What do we do if this fails? If we trigger a
330 // device reset, and the device fails to re-appear after 5 seconds,
331 // it is probably gone for good. We probably need to force unload
332 // any device drivers which had previously owned the device.
333 TRACEF("Timeout waiting for %02x:%02x.%01x to complete function "
334 "level reset. This is Very Bad.\n",
335 bus_id_, dev_id_, func_id_);
336 }
337
338 return ret;
339 }
340
ModifyCmd(uint16_t clr_bits,uint16_t set_bits)341 zx_status_t PcieDevice::ModifyCmd(uint16_t clr_bits, uint16_t set_bits) {
342 AutoLock dev_lock(&dev_lock_);
343
344 /* In order to keep internal bookkeeping coherent, and interactions between
345 * MSI/MSI-X and Legacy IRQ mode safe, API users may not directly manipulate
346 * the legacy IRQ enable/disable bit. Just ignore them if they try to
347 * manipulate the bit via the modify cmd API. */
348 clr_bits = static_cast<uint16_t>(clr_bits & ~PCIE_CFG_COMMAND_INT_DISABLE);
349 set_bits = static_cast<uint16_t>(set_bits & ~PCIE_CFG_COMMAND_INT_DISABLE);
350
351 if (plugged_in_) {
352 ModifyCmdLocked(clr_bits, set_bits);
353 return ZX_OK;
354 }
355
356 return ZX_ERR_UNAVAILABLE;
357 }
358
ModifyCmdLocked(uint16_t clr_bits,uint16_t set_bits)359 void PcieDevice::ModifyCmdLocked(uint16_t clr_bits, uint16_t set_bits) {
360 DEBUG_ASSERT(dev_lock_.IsHeld());
361
362 {
363 AutoSpinLock cmd_reg_lock(&cmd_reg_lock_);
364 cfg_->Write(PciConfig::kCommand,
365 static_cast<uint16_t>((cfg_->Read(PciConfig::kCommand) & ~clr_bits)
366 | set_bits));
367 }
368 }
369
ProbeBarsLocked()370 zx_status_t PcieDevice::ProbeBarsLocked() {
371 DEBUG_ASSERT(cfg_);
372 DEBUG_ASSERT(dev_lock_.IsHeld());
373
374 static_assert(PCIE_MAX_BAR_REGS >= PCIE_BAR_REGS_PER_DEVICE, "");
375 static_assert(PCIE_MAX_BAR_REGS >= PCIE_BAR_REGS_PER_BRIDGE, "");
376
377 __UNUSED uint8_t header_type = cfg_->Read(PciConfig::kHeaderType) & PCI_HEADER_TYPE_MASK;
378
379 DEBUG_ASSERT((header_type == PCI_HEADER_TYPE_STANDARD) ||
380 (header_type == PCI_HEADER_TYPE_PCI_BRIDGE));
381 DEBUG_ASSERT(bar_count_ <= fbl::count_of(bars_));
382
383 for (uint i = 0; i < bar_count_; ++i) {
384 /* If this is a re-scan of the bus, We should not be re-enumerating BARs. */
385 DEBUG_ASSERT(bars_[i].size == 0);
386 DEBUG_ASSERT(bars_[i].allocation == nullptr);
387
388 zx_status_t probe_res = ProbeBarLocked(i);
389 if (probe_res != ZX_OK)
390 return probe_res;
391
392 if (bars_[i].size > 0) {
393 /* If this was a 64 bit bar, it took two registers to store. Make
394 * sure to skip the next register */
395 if (bars_[i].is_64bit) {
396 i++;
397
398 if (i >= bar_count_) {
399 TRACEF("Device %02x:%02x:%01x claims to have 64-bit BAR in position %u/%u!\n",
400 bus_id_, dev_id_, func_id_, i, bar_count_);
401 return ZX_ERR_BAD_STATE;
402 }
403 }
404 }
405 }
406
407 return ZX_OK;
408 }
409
ProbeBarLocked(uint bar_id)410 zx_status_t PcieDevice::ProbeBarLocked(uint bar_id) {
411 DEBUG_ASSERT(cfg_);
412 DEBUG_ASSERT(bar_id < bar_count_);
413 DEBUG_ASSERT(bar_id < fbl::count_of(bars_));
414
415 /* Determine the type of BAR this is. Make sure that it is one of the types we understand */
416 pcie_bar_info_t& bar_info = bars_[bar_id];
417 uint32_t bar_val = cfg_->Read(PciConfig::kBAR(bar_id));
418 bar_info.is_mmio = (bar_val & PCI_BAR_IO_TYPE_MASK) == PCI_BAR_IO_TYPE_MMIO;
419 bar_info.is_64bit = bar_info.is_mmio &&
420 ((bar_val & PCI_BAR_MMIO_TYPE_MASK) == PCI_BAR_MMIO_TYPE_64BIT);
421 bar_info.is_prefetchable = bar_info.is_mmio && (bar_val & PCI_BAR_MMIO_PREFETCH_MASK);
422 bar_info.first_bar_reg = bar_id;
423
424 if (bar_info.is_64bit) {
425 if ((bar_id + 1) >= bar_count_) {
426 TRACEF("Illegal 64-bit MMIO BAR position (%u/%u) while fetching BAR info "
427 "for device config @%p\n",
428 bar_id, bar_count_, cfg_);
429 return ZX_ERR_BAD_STATE;
430 }
431 } else {
432 if (bar_info.is_mmio && ((bar_val & PCI_BAR_MMIO_TYPE_MASK) != PCI_BAR_MMIO_TYPE_32BIT)) {
433 TRACEF("Unrecognized MMIO BAR type (BAR[%u] == 0x%08x) while fetching BAR info "
434 "for device config @%p\n",
435 bar_id, bar_val, cfg_);
436 return ZX_ERR_BAD_STATE;
437 }
438 }
439
440 /* Disable either MMIO or PIO (depending on the BAR type) access while we
441 * perform the probe. We don't want the addresses written during probing to
442 * conflict with anything else on the bus. Note: No drivers should have
443 * access to this device's registers during the probe process as the device
444 * should not have been published yet. That said, there could be other
445 * (special case) parts of the system accessing a devices registers at this
446 * point in time, like an early init debug console or serial port. Don't
447 * make any attempt to print or log until the probe operation has been
448 * completed. Hopefully these special systems are quiescent at this point
449 * in time, otherwise they might see some minor glitching while access is
450 * disabled.
451 */
452 uint16_t backup = cfg_->Read(PciConfig::kCommand);
453 if (bar_info.is_mmio)
454 cfg_->Write(PciConfig::kCommand, static_cast<uint16_t>(backup & ~PCI_COMMAND_MEM_EN));
455 else
456 cfg_->Write(PciConfig::kCommand, static_cast<uint16_t>(backup & ~PCI_COMMAND_IO_EN));
457
458 /* Figure out the size of this BAR region by writing 1's to the
459 * address bits, then reading back to see which bits the device
460 * considers un-configurable. */
461 uint32_t addr_mask = bar_info.is_mmio ? PCI_BAR_MMIO_ADDR_MASK : PCI_BAR_PIO_ADDR_MASK;
462 uint32_t addr_lo = bar_val & addr_mask;
463 uint64_t size_mask;
464
465 cfg_->Write(PciConfig::kBAR(bar_id), bar_val | addr_mask);
466 size_mask = ~(cfg_->Read(PciConfig::kBAR(bar_id)) & addr_mask);
467 cfg_->Write(PciConfig::kBAR(bar_id), bar_val);
468
469 if (bar_info.is_mmio) {
470 if (bar_info.is_64bit) {
471
472 /* 64bit MMIO? Probe the upper bits as well */
473 bar_id++;
474 bar_val = cfg_->Read(PciConfig::kBAR(bar_id));
475 cfg_->Write(PciConfig::kBAR(bar_id), 0xFFFFFFFF);
476 size_mask |= ((uint64_t)~cfg_->Read(PciConfig::kBAR(bar_id))) << 32;
477 cfg_->Write(PciConfig::kBAR(bar_id), bar_val);
478 bar_info.size = size_mask + 1;
479 bar_info.bus_addr = (static_cast<uint64_t>(bar_val) << 32) | addr_lo;
480 } else {
481 bar_info.size = (uint32_t)(size_mask + 1);
482 bar_info.bus_addr = addr_lo;
483 }
484 } else {
485 /* PIO BAR */
486 bar_info.size = ((uint32_t)(size_mask + 1)) & PCIE_PIO_ADDR_SPACE_MASK;
487 bar_info.bus_addr = addr_lo;
488 }
489
490 /* Restore the command register to its previous value */
491 cfg_->Write(PciConfig::kCommand, backup);
492
493 /* Success */
494 return ZX_OK;
495 }
496
497
AllocateBars()498 zx_status_t PcieDevice::AllocateBars() {
499 AutoLock dev_lock(&dev_lock_);
500 return AllocateBarsLocked();
501 }
502
AllocateBarsLocked()503 zx_status_t PcieDevice::AllocateBarsLocked() {
504 DEBUG_ASSERT(dev_lock_.IsHeld());
505 DEBUG_ASSERT(plugged_in_);
506
507 // Have we become unplugged?
508 if (!plugged_in_)
509 return ZX_ERR_UNAVAILABLE;
510
511 /* Allocate BARs for the device */
512 DEBUG_ASSERT(bar_count_ <= fbl::count_of(bars_));
513 for (size_t i = 0; i < bar_count_; ++i) {
514 if (bars_[i].size) {
515 zx_status_t ret = AllocateBarLocked(bars_[i]);
516 if (ret != ZX_OK)
517 return ret;
518 }
519 }
520
521 return ZX_OK;
522 }
523
AllocateBarLocked(pcie_bar_info_t & info)524 zx_status_t PcieDevice::AllocateBarLocked(pcie_bar_info_t& info) {
525 DEBUG_ASSERT(dev_lock_.IsHeld());
526 DEBUG_ASSERT(plugged_in_);
527
528 // Do not attempt to remap if we are rescanning the bus and this BAR is
529 // already allocated, or if it does not exist (size is zero)
530 if ((info.size == 0) || (info.allocation != nullptr))
531 return ZX_OK;
532
533 // Hold a reference to our upstream node while we do this. If we cannot
534 // obtain a reference, then our upstream node has become unplugged and we
535 // should just fail out now.
536 auto upstream = GetUpstream();
537 if (upstream == nullptr)
538 return ZX_ERR_UNAVAILABLE;
539
540 /* Does this BAR already have an assigned address? If so, try to preserve
541 * it, if possible. */
542 if (info.bus_addr != 0) {
543 RegionAllocator* alloc = nullptr;
544 if (upstream->type() == PcieUpstreamNode::Type::BRIDGE && info.is_prefetchable) {
545 alloc = &upstream->pf_mmio_regions();
546 } else if (info.is_mmio) {
547 /* We currently do not support preserving an MMIO region which spans
548 * the 4GB mark. If we encounter such a thing, clear out the
549 * allocation and attempt to re-allocate. */
550 uint64_t inclusive_end = info.bus_addr + info.size - 1;
551 if (inclusive_end <= fbl::numeric_limits<uint32_t>::max()) {
552 alloc = &upstream->mmio_lo_regions();
553 } else
554 if (info.bus_addr > fbl::numeric_limits<uint32_t>::max()) {
555 alloc = &upstream->mmio_hi_regions();
556 }
557 } else {
558 alloc = &upstream->pio_regions();
559 }
560
561 zx_status_t res = ZX_ERR_NOT_FOUND;
562 if (alloc != nullptr) {
563 res = alloc->GetRegion({ .base = info.bus_addr, .size = info.size }, info.allocation);
564 }
565
566 if (res == ZX_OK)
567 return ZX_OK;
568
569 TRACEF("Failed to preserve device %02x:%02x.%01x's %s window "
570 "[%#" PRIx64 ", %#" PRIx64 "] Attempting to re-allocate.\n",
571 bus_id_, dev_id_, func_id_,
572 info.is_mmio ? (info.is_prefetchable ? "PFMMIO" : "MMIO") : "PIO",
573 info.bus_addr, info.bus_addr + info.size - 1);
574 info.bus_addr = 0;
575 }
576
577 /* We failed to preserve the allocation and need to attempt to
578 * dynamically allocate a new region. Close the device MMIO/PIO
579 * windows, disable interrupts and shut of bus mastering (which will
580 * also disable MSI interrupts) before we attempt dynamic allocation.
581 */
582 AssignCmdLocked(PCIE_CFG_COMMAND_INT_DISABLE);
583
584 /* Choose which region allocator we will attempt to allocate from, then
585 * check to see if we have the space. */
586 RegionAllocator* alloc = !info.is_mmio
587 ? &upstream->pio_regions()
588 : (info.is_64bit ? &upstream->mmio_hi_regions()
589 : &upstream->mmio_lo_regions());
590 uint32_t addr_mask = info.is_mmio
591 ? PCI_BAR_MMIO_ADDR_MASK
592 : PCI_BAR_PIO_ADDR_MASK;
593
594 /* If check to see if we have the space to allocate within the chosen
595 * range. In the case of a 64 bit MMIO BAR, if we run out of space in
596 * the high-memory MMIO range, try the low memory range as well.
597 */
598 while (true) {
599 /* MMIO windows and I/O windows on systems where I/O space is actually
600 * memory mapped must be aligned to a page boundary, at least. */
601 bool is_io_space = PCIE_HAS_IO_ADDR_SPACE && !info.is_mmio;
602 uint64_t align_size = ((info.size >= PAGE_SIZE) || is_io_space)
603 ? info.size
604 : PAGE_SIZE;
605 zx_status_t res = alloc->GetRegion(align_size, align_size, info.allocation);
606
607 if (res != ZX_OK) {
608 if ((res == ZX_ERR_NOT_FOUND) && (alloc == &upstream->mmio_hi_regions())) {
609 LTRACEF("Insufficient space to map 64-bit MMIO BAR in high region while "
610 "configuring BARs for device at %02x:%02x.%01x (cfg vaddr = %p). "
611 "Falling back on low memory region.\n",
612 bus_id_, dev_id_, func_id_, cfg_);
613 alloc = &upstream->mmio_lo_regions();
614 continue;
615 }
616
617 TRACEF("Failed to dynamically allocate %s BAR region (size %#" PRIx64 ") "
618 "while configuring BARs for device at %02x:%02x.%01x (res = %d)\n",
619 info.is_mmio ? (info.is_prefetchable ? "PFMMIO" : "MMIO") : "PIO", info.size,
620 bus_id_, dev_id_, func_id_, res);
621
622 // Looks like we are out of luck. Propagate the error up the stack
623 // so that our upstream node knows to disable us.
624 return res;
625 }
626
627 break;
628 }
629
630 /* Allocation succeeded. Record our allocated and aligned physical address
631 * in our BAR(s) */
632 DEBUG_ASSERT(info.allocation != nullptr);
633 uint bar_reg = info.first_bar_reg;
634 info.bus_addr = info.allocation->base;
635
636 cfg_->Write(PciConfig::kBAR(bar_reg), static_cast<uint32_t>((info.bus_addr & 0xFFFFFFFF) |
637 (cfg_->Read(PciConfig::kBAR(bar_reg)) & ~addr_mask)));
638 if (info.is_64bit)
639 cfg_->Write(PciConfig::kBAR(bar_reg + 1), static_cast<uint32_t>(info.bus_addr >> 32));
640
641 return ZX_OK;
642 }
643
Disable()644 void PcieDevice::Disable() {
645 DEBUG_ASSERT(!dev_lock_.IsHeld());
646 AutoLock dev_lock(&dev_lock_);
647 DisableLocked();
648 }
649
DisableLocked()650 void PcieDevice::DisableLocked() {
651 // Disable a device because we cannot allocate space for all of its BARs (or
652 // forwarding windows, in the case of a bridge). Flag the device as
653 // disabled from here on out.
654 DEBUG_ASSERT(dev_lock_.IsHeld());
655 TRACEF("WARNING - Disabling device %02x:%02x.%01x due to unsatisfiable configuration\n",
656 bus_id_, dev_id_, func_id_);
657
658 // Flag the device as disabled. Close the device's MMIO/PIO windows, shut
659 // off device initiated accesses to the bus, disable legacy interrupts.
660 // Basically, prevent the device from doing anything from here on out.
661 disabled_ = true;
662 AssignCmdLocked(PCIE_CFG_COMMAND_INT_DISABLE);
663
664 // Release all BAR allocations back into the pool they came from.
665 for (auto& bar : bars_)
666 bar.allocation = nullptr;
667 }
668
Dump() const669 void PcieDevice::Dump() const {
670 printf("PCI: device at %02x:%02x:%02x vid:did %04x:%04x\n",
671 bus_id(), dev_id(), func_id(),
672 vendor_id(), device_id());
673 }
674