📄 pciehp_hpc.c
字号:
if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return -1; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return rc; } switch (value) { case 0 : /* turn off */ slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0; break; case 1: /* turn on */ slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040; break; case 2: /* turn blink */ slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080; break; default: return -1; } if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return rc;}static void hpc_set_green_led_on(struct slot *slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return ; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return;}static void hpc_set_green_led_off(struct slot *slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return ; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return;}static void hpc_set_green_led_blink(struct slot *slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return ; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return;}int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ int *first_device_num, /* PCI dev num of the first slot in this PCIE */ int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ u8 *ctrlcap){ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 slot_cap; int rc = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } *first_device_num = 0; *num_ctlr_slots = 1; rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); if (rc) { err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); return -1; } *physical_slot_num = slot_cap >> 19; dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num); *ctrlcap = slot_cap & 0x0000007f; DBG_LEAVE_ROUTINE return 0;}static void hpc_release_ctlr(struct controller *ctrl){ struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return ; } if (pciehp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; if (!pcie_mch_quirk) pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) php_ctlr->pci_dev = NULL; spin_lock(&list_lock); p = php_ctlr_list_head; p_prev = NULL; while (p) { if (p == php_ctlr) { if (p_prev) p_prev->pnext = p->pnext; else php_ctlr_list_head = p->pnext; break; } else { p_prev = p; p = p->pnext; } } spin_unlock(&list_lock); kfree(php_ctlr); DBG_LEAVE_ROUTINE }static int hpc_power_on_slot(struct slot * slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl, slot_status; int retval = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return -1; } /* Clear sticky power-fault bit from previous power failures */ hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); slot_status &= PWR_FAULT_DETECTED; if (slot_status) hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (retval) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; /* Enable detection that we turned off at slot power-off time */ if (!pciehp_poll_mode) slot_cmd = slot_cmd | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | PRSN_DETECT_ENABLE | HP_INTR_ENABLE; retval = pcie_write_cmd(slot, slot_cmd); if (retval) { err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); return -1; } dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return retval;}static int hpc_power_off_slot(struct slot * slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int retval = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); slot->hp_slot = 0; if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return -1; } retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (retval) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; /* * If we get MRL or presence detect interrupts now, the isr * will notice the sticky power-fault bit too and issue power * indicator change commands. This will lead to an endless loop * of command completions, since the power-fault bit remains on * till the slot is powered on again. */ if (!pciehp_poll_mode) slot_cmd = (slot_cmd & ~PWR_FAULT_DETECT_ENABLE & ~MRL_DETECT_ENABLE & ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; retval = pcie_write_cmd(slot, slot_cmd); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); return -1; } dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return retval;}static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs){ struct controller *ctrl = NULL; struct php_ctlr_state_s *php_ctlr; u8 schedule_flag = 0; u16 slot_status, intr_detect, intr_loc; u16 temp_word; int hp_slot = 0; /* only 1 slot per PCI Express port */ int rc = 0; if (!dev_id) return IRQ_NONE; if (!pciehp_poll_mode) { ctrl = dev_id; php_ctlr = ctrl->hpc_ctlr_handle; } else { php_ctlr = dev_id; ctrl = (struct controller *)php_ctlr->callback_instance_id; } if (!ctrl) { dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id); return IRQ_NONE; } if (!php_ctlr) { dbg("%s: php_ctlr == NULL\n", __FUNCTION__); return IRQ_NONE; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED ); intr_loc = slot_status & intr_detect; /* Check to see if it was our interrupt */ if ( !intr_loc ) return IRQ_NONE; dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); /* Mask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1f; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } } if (intr_loc & CMD_COMPLETED) { /* * Command Complete Interrupt Pending */ wake_up_interruptible(&ctrl->queue); } if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED)) schedule_flag += php_ctlr->switch_change_callback( hp_slot, php_ctlr->callback_instance_id); if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED)) schedule_flag += php_ctlr->attention_button_callback( hp_slot, php_ctlr->callback_instance_id); if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED)) schedule_flag += php_ctlr->presence_change_callback( hp_slot , php_ctlr->callback_instance_id); if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED)) schedule_flag += php_ctlr->power_fault_callback( hp_slot, php_ctlr->callback_instance_id); /* Clear all events after serving them */ temp_word = 0x1F; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } /* Unmask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } /* Clear command complete interrupt caused by this write */ temp_word = 0x1F; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } return IRQ_HANDLED;}static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed; u32 lnk_cap; int retval = 0; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } if (slot->hp_slot >= php_ctlr->num_slots) { err("%s: Invalid HPC slot number!\n", __FUNCTION__); return -1; } retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); if (retval) { err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); return retval; } switch (lnk_cap & 0x000F) { case 1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -