📄 pciehp_hpc.c
字号:
return 0;}static int hpc_query_power_fault(struct slot * slot){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; u8 pwr_fault; int retval = 0; u8 status; DBG_ENTER_ROUTINE if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); return -1; } retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); if (retval) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return retval; } pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); status = (pwr_fault != 1) ? 1 : 0; DBG_LEAVE_ROUTINE /* Note: Logic 0 => fault */ return status;}static int hpc_set_attention_status(struct slot *slot, u8 value){ struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd = 0; u16 slot_ctrl; int rc = 0; dbg("%s: \n", __FUNCTION__); 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; } dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); 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); 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("%s: \n", __FUNCTION__); 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; } dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); 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); 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("%s: \n", __FUNCTION__); 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; } dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); 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); 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("%s: \n", __FUNCTION__); 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; } dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); 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); 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; int retval = 0; DBG_ENTER_ROUTINE dbg("%s: \n", __FUNCTION__); 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; } 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; } dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; if (!pciehp_poll_mode) slot_cmd = slot_cmd | 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 dbg("%s: \n", __FUNCTION__); 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; } dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; if (!pciehp_poll_mode) slot_cmd = slot_cmd | 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: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__); 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; } dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); 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; } dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } if (intr_loc & CMD_COMPLETED) { /* * Command Complete Interrupt Pending */ dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__); 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__); dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); 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; } dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); 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__);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -