drivers/infiniband/hw/hfi1/pcie.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/hfi1/pcie.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/hfi1/pcie.c
Extension
.c
Size
38953 bytes
Lines
1383
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret) {
			dd_dev_err(dd, "Unable to set DMA mask: %d\n", ret);
			goto bail;
		}
	}

	pci_set_master(pdev);
	return 0;

bail:
	hfi1_pcie_cleanup(pdev);
	return ret;
}

/*
 * Clean what was done in hfi1_pcie_init()
 */
void hfi1_pcie_cleanup(struct pci_dev *pdev)
{
	pci_disable_device(pdev);
	/*
	 * Release regions should be called after the disable. OK to
	 * call if request regions has not been called or failed.
	 */
	pci_release_regions(pdev);
}

/*
 * Do remaining PCIe setup, once dd is allocated, and save away
 * fields required to re-initialize after a chip reset, or for
 * various other purposes
 */
int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev)
{
	unsigned long len;
	resource_size_t addr;
	int ret = 0;
	u32 rcv_array_count;

	addr = pci_resource_start(pdev, 0);
	len = pci_resource_len(pdev, 0);

	/*
	 * The TXE PIO buffers are at the tail end of the chip space.
	 * Cut them off and map them separately.
	 */

	/* sanity check vs expectations */
	if (len != TXE_PIO_SEND + TXE_PIO_SIZE) {
		dd_dev_err(dd, "chip PIO range does not match\n");
		return -EINVAL;
	}

	dd->kregbase1 = ioremap(addr, RCV_ARRAY);
	if (!dd->kregbase1) {
		dd_dev_err(dd, "UC mapping of kregbase1 failed\n");
		return -ENOMEM;
	}
	dd_dev_info(dd, "UC base1: %p for %x\n", dd->kregbase1, RCV_ARRAY);

	/* verify that reads actually work, save revision for reset check */
	dd->revision = readq(dd->kregbase1 + CCE_REVISION);
	if (dd->revision == ~(u64)0) {
		dd_dev_err(dd, "Cannot read chip CSRs\n");
		goto nomem;
	}

	rcv_array_count = readq(dd->kregbase1 + RCV_ARRAY_CNT);
	dd_dev_info(dd, "RcvArray count: %u\n", rcv_array_count);
	dd->base2_start  = RCV_ARRAY + rcv_array_count * 8;

	dd->kregbase2 = ioremap(
		addr + dd->base2_start,
		TXE_PIO_SEND - dd->base2_start);
	if (!dd->kregbase2) {
		dd_dev_err(dd, "UC mapping of kregbase2 failed\n");
		goto nomem;
	}
	dd_dev_info(dd, "UC base2: %p for %x\n", dd->kregbase2,
		    TXE_PIO_SEND - dd->base2_start);

	dd->piobase = ioremap_wc(addr + TXE_PIO_SEND, TXE_PIO_SIZE);
	if (!dd->piobase) {
		dd_dev_err(dd, "WC mapping of send buffers failed\n");
		goto nomem;
	}
	dd_dev_info(dd, "WC piobase: %p for %x\n", dd->piobase, TXE_PIO_SIZE);

	dd->physaddr = addr;        /* used for io_remap, etc. */

Annotation

Implementation Notes