drivers/pci/hotplug/shpchp_hpc.c

Source file repositories/reference/linux-study-clean/drivers/pci/hotplug/shpchp_hpc.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/hotplug/shpchp_hpc.c
Extension
.c
Size
26651 bytes
Lines
1049
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!ctrl->cap_offset) {
			ctrl_err(ctrl, "Cannot find PCI capability\n");
			goto abort;
		}
		ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset);

		rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
		if (rc) {
			ctrl_err(ctrl, "Cannot read base_offset\n");
			goto abort;
		}

		rc = shpc_indirect_read(ctrl, 3, &tempdword);
		if (rc) {
			ctrl_err(ctrl, "Cannot read slot config\n");
			goto abort;
		}
		num_slots = tempdword & SLOT_NUM;
		ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots);

		for (i = 0; i < 9 + num_slots; i++) {
			rc = shpc_indirect_read(ctrl, i, &tempdword);
			if (rc) {
				ctrl_err(ctrl, "Cannot read creg (index = %d)\n",
					 i);
				goto abort;
			}
			ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword);
		}

		ctrl->mmio_base =
			pci_resource_start(pdev, 0) + shpc_base_offset;
		ctrl->mmio_size = 0x24 + 0x4 * num_slots;
	}

	ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
		  pdev->vendor, pdev->device, pdev->subsystem_vendor,
		  pdev->subsystem_device);

	rc = pci_enable_device(pdev);
	if (rc) {
		ctrl_err(ctrl, "pci_enable_device failed\n");
		goto abort;
	}

	if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
		ctrl_err(ctrl, "Cannot reserve MMIO region\n");
		rc = -1;
		goto abort;
	}

	ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
	if (!ctrl->creg) {
		ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n",
			 ctrl->mmio_size, ctrl->mmio_base);
		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
		rc = -1;
		goto abort;
	}
	ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg);

	mutex_init(&ctrl->crit_sect);
	mutex_init(&ctrl->cmd_lock);

	/* Setup wait queue */
	init_waitqueue_head(&ctrl->queue);

	/* Return PCI Controller Info */
	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
	ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
	ctrl->num_slots = slot_config & SLOT_NUM;
	ctrl->first_slot = (slot_config & PSN) >> 16;
	ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1;

	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
	ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
	tempdword |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
		      COMMAND_INTR_MASK | ARBITER_SERR_MASK);
	tempdword &= ~SERR_INTR_RSVDZ_MASK;
	shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
	ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);

	/* Mask the MRL sensor SERR Mask of individual slot in
	 * Slot SERR-INT Mask & clear all the existing event if any
	 */
	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
		ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n",

Annotation

Implementation Notes