⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciehp_hpc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		lnk_wdth = PCIE_LNK_X4;		break;	case 8:		lnk_wdth = PCIE_LNK_X8;		break;	case 12:		lnk_wdth = PCIE_LNK_X12;		break;	case 16:		lnk_wdth = PCIE_LNK_X16;		break;	case 32:		lnk_wdth = PCIE_LNK_X32;		break;	default:		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;		break;	}	*value = lnk_wdth;	dbg("Max link width = %d\n", lnk_wdth);	return retval;}static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value){	struct controller *ctrl = slot->ctrl;	enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;	int retval = 0;	u16 lnk_status;	retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);	if (retval) {		err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);		return retval;	}	switch (lnk_status & 0x0F) {	case 1:		lnk_speed = PCIE_2PT5GB;		break;	default:		lnk_speed = PCIE_LNK_SPEED_UNKNOWN;		break;	}	*value = lnk_speed;	dbg("Current link speed = %d\n", lnk_speed);	return retval;}static int hpc_get_cur_lnk_width(struct slot *slot,				 enum pcie_link_width *value){	struct controller *ctrl = slot->ctrl;	enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;	int retval = 0;	u16 lnk_status;	retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);	if (retval) {		err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);		return retval;	}	switch ((lnk_status & 0x03F0) >> 4){	case 0:		lnk_wdth = PCIE_LNK_WIDTH_RESRV;		break;	case 1:		lnk_wdth = PCIE_LNK_X1;		break;	case 2:		lnk_wdth = PCIE_LNK_X2;		break;	case 4:		lnk_wdth = PCIE_LNK_X4;		break;	case 8:		lnk_wdth = PCIE_LNK_X8;		break;	case 12:		lnk_wdth = PCIE_LNK_X12;		break;	case 16:		lnk_wdth = PCIE_LNK_X16;		break;	case 32:		lnk_wdth = PCIE_LNK_X32;		break;	default:		lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;		break;	}	*value = lnk_wdth;	dbg("Current link width = %d\n", lnk_wdth);	return retval;}static struct hpc_ops pciehp_hpc_ops = {	.power_on_slot			= hpc_power_on_slot,	.power_off_slot			= hpc_power_off_slot,	.set_attention_status		= hpc_set_attention_status,	.get_power_status		= hpc_get_power_status,	.get_attention_status		= hpc_get_attention_status,	.get_latch_status		= hpc_get_latch_status,	.get_adapter_status		= hpc_get_adapter_status,	.get_emi_status			= hpc_get_emi_status,	.toggle_emi			= hpc_toggle_emi,	.get_max_bus_speed		= hpc_get_max_lnk_speed,	.get_cur_bus_speed		= hpc_get_cur_lnk_speed,	.get_max_lnk_width		= hpc_get_max_lnk_width,	.get_cur_lnk_width		= hpc_get_cur_lnk_width,	.query_power_fault		= hpc_query_power_fault,	.green_led_on			= hpc_set_green_led_on,	.green_led_off			= hpc_set_green_led_off,	.green_led_blink		= hpc_set_green_led_blink,	.release_ctlr			= hpc_release_ctlr,	.check_lnk_status		= hpc_check_lnk_status,};#ifdef CONFIG_ACPIint pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev){	acpi_status status;	acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));	struct pci_dev *pdev = dev;	struct pci_bus *parent;	struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };	/*	 * Per PCI firmware specification, we should run the ACPI _OSC	 * method to get control of hotplug hardware before using it.	 * If an _OSC is missing, we look for an OSHP to do the same thing.	 * To handle different BIOS behavior, we look for _OSC and OSHP	 * within the scope of the hotplug controller and its parents, upto	 * the host bridge under which this controller exists.	 */	while (!handle) {		/*		 * This hotplug controller was not listed in the ACPI name		 * space at all. Try to get acpi handle of parent pci bus.		 */		if (!pdev || !pdev->bus->parent)			break;		parent = pdev->bus->parent;		dbg("Could not find %s in acpi namespace, trying parent\n",				pci_name(pdev));		if (!parent->self)			/* Parent must be a host bridge */			handle = acpi_get_pci_rootbridge_handle(					pci_domain_nr(parent),					parent->number);		else			handle = DEVICE_ACPI_HANDLE(					&(parent->self->dev));		pdev = parent->self;	}	while (handle) {		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);		dbg("Trying to get hotplug control for %s \n",			(char *)string.pointer);		status = pci_osc_control_set(handle,				OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |				OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);		if (status == AE_NOT_FOUND)			status = acpi_run_oshp(handle);		if (ACPI_SUCCESS(status)) {			dbg("Gained control for hotplug HW for pci %s (%s)\n",				pci_name(dev), (char *)string.pointer);			kfree(string.pointer);			return 0;		}		if (acpi_root_bridge(handle))			break;		chandle = handle;		status = acpi_get_parent(chandle, &handle);		if (ACPI_FAILURE(status))			break;	}	err("Cannot get control of hotplug hardware for pci %s\n",			pci_name(dev));	kfree(string.pointer);	return -1;}#endifint pcie_init(struct controller * ctrl, struct pcie_device *dev){	int rc;	u16 temp_word;	u16 cap_reg;	u16 intr_enable = 0;	u32 slot_cap;	int cap_base;	u16 slot_status, slot_ctrl;	struct pci_dev *pdev;	pdev = dev->port;	ctrl->pci_dev = pdev;	/* save pci_dev in context */	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",			__FUNCTION__, pdev->vendor, pdev->device);	if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);		goto abort_free_ctlr;	}	ctrl->cap_base = cap_base;	dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base);	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);	if (rc) {		err("%s: Cannot read CAPREG register\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: CAPREG offset %x cap_reg %x\n",	    __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);	if (((cap_reg & SLOT_IMPL) == 0) ||	    (((cap_reg & DEV_PORT_TYPE) != 0x0040)		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {		dbg("%s : This is not a root port or the port is not "		    "connected to a slot\n", __FUNCTION__);		goto abort_free_ctlr;	}	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);	if (rc) {		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOTCAP offset %x slot_cap %x\n",	    __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);	if (!(slot_cap & HP_CAP)) {		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);		goto abort_free_ctlr;	}	/* For debugging purpose */	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);	if (rc) {		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",	    __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);	if (rc) {		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);	for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)		if (pci_resource_len(pdev, rc) > 0)			dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,			    (unsigned long long)pci_resource_start(pdev, rc),			    (unsigned long long)pci_resource_len(pdev, rc));	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",	     pdev->vendor, pdev->device,	     pdev->subsystem_vendor, pdev->subsystem_device);	mutex_init(&ctrl->crit_sect);	mutex_init(&ctrl->ctrl_lock);	spin_lock_init(&ctrl->lock);	/* setup wait queue */	init_waitqueue_head(&ctrl->queue);	/* return PCI Controller Info */	ctrl->slot_device_offset = 0;	ctrl->num_slots = 1;	ctrl->first_slot = slot_cap >> 19;	ctrl->ctrlcap = slot_cap & 0x0000007f;	/* Mask Hot-plug Interrupt Enable */	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);	if (rc) {		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);		goto abort_free_ctlr;	}	dbg("%s: SLOTCTRL %x value read %x\n",	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |		0x00;	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);	if (rc) {		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);		goto abort_free_ctlr;	}	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);	if (rc) {		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);		goto abort_free_ctlr;	}	temp_word = 0x1F; /* Clear all events */	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);	if (rc) {		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);		goto abort_free_ctlr;	}	if (pciehp_poll_mode) {		/* Install interrupt polling timer. Start with 10 sec delay */		init_timer(&ctrl->poll_timer);		start_int_poll_timer(ctrl, 10);	} else {		/* Installs the interrupt handler */		rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,				 MY_NAME, (void *)ctrl);		dbg("%s: request_irq %d for hpc%d (returns %d)\n",		    __FUNCTION__, ctrl->pci_dev->irq,		    atomic_read(&pciehp_num_controllers), rc);		if (rc) {			err("Can't get irq %d for the hotplug controller\n",			    ctrl->pci_dev->irq);			goto abort_free_ctlr;		}	}	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);	/*	 * If this is the first controller to be initialized,	 * initialize the pciehp work queue	 */	if (atomic_add_return(1, &pciehp_num_controllers) == 1) {		pciehp_wq = create_singlethread_workqueue("pciehpd");		if (!pciehp_wq) {			rc = -ENOMEM;			goto abort_free_irq;		}	}	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);	if (rc) {		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);		goto abort_free_irq;	}	intr_enable = intr_enable | PRSN_DETECT_ENABLE;	if (ATTN_BUTTN(slot_cap))		intr_enable = intr_enable | ATTN_BUTTN_ENABLE;	if (POWER_CTRL(slot_cap))		intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;	if (MRL_SENS(slot_cap))		intr_enable = intr_enable | MRL_DETECT_ENABLE;	temp_word = (temp_word & ~intr_enable) | intr_enable;	if (pciehp_poll_mode) {		temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;	} else {		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;	}	/*	 * Unmask Hot-plug Interrupt Enable for the interrupt	 * notification mechanism case.	 */	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);	if (rc) {		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);		goto abort_free_irq;	}	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);	if (rc) {		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);		goto abort_disable_intr;	}	temp_word =  0x1F; /* Clear all events */	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);	if (rc) {		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);		goto abort_disable_intr;	}	if (pciehp_force) {		dbg("Bypassing BIOS check for pciehp use on %s\n",				pci_name(ctrl->pci_dev));	} else {		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);		if (rc)			goto abort_disable_intr;	}	ctrl->hpc_ops = &pciehp_hpc_ops;	return 0;	/* We end up here for the many possible ways to fail this API. */abort_disable_intr:	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);	if (!rc) {		temp_word &= ~(intr_enable | HP_INTR_ENABLE);		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);	}	if (rc)		err("%s : disabling interrupts failed\n", __FUNCTION__);abort_free_irq:	if (pciehp_poll_mode)		del_timer_sync(&ctrl->poll_timer);	else		free_irq(ctrl->pci_dev->irq, ctrl);abort_free_ctlr:	return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -