/** * pcie_write_cmd - Issue controller command * @ctrl: controller to which the command is issued * @cmd: command value written to slot control register * @mask: bitmask of slot control register to be modified */ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) { struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; u16 slot_ctrl; mutex_lock(&ctrl->ctrl_lock); pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (slot_status & PCI_EXP_SLTSTA_CC) { pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); if (!ctrl->no_cmd_complete) { /* * After 1 sec and CMD_COMPLETED still not set, just * proceed forward to issue the next command according * to spec. Just print out the error message. */ ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n"); } else if (!NO_CMD_CMPL(ctrl)) { /* * This controller seems to notify of command completed * event even though it supports none of power * controller, attention led, power led and EMI. */ ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to wait for command completed event\n"); ctrl->no_cmd_complete = 0; } else { ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe the controller is broken\n"); } } pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); slot_ctrl &= ~mask; slot_ctrl |= (cmd & mask); ctrl->cmd_busy = 1; smp_mb(); pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); /* * Wait for command completion. */ if (!ctrl->no_cmd_complete) { int poll = 0; /* * if hotplug interrupt is not enabled or command * completed interrupt is not enabled, we need to poll * command completed event. */ if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) || !(slot_ctrl & PCI_EXP_SLTCTL_CCIE)) poll = 1; pcie_wait_cmd(ctrl, poll); } mutex_unlock(&ctrl->ctrl_lock); }
/** * board_added - Called after a board has been added to the system. * @p_slot: &slot where board is added * * Turns power on for the board. * Configures board. */ static int board_added(struct slot *p_slot) { int retval = 0; struct controller *ctrl = p_slot->ctrl; struct pci_bus *parent = ctrl->pci_dev->subordinate; ctrl_dbg(ctrl, "%s: slot device, slot offset, hp slot = %d, %d, %d\n", __func__, p_slot->device, ctrl->slot_device_offset, p_slot->hp_slot); if (POWER_CTRL(ctrl)) { /* Power on slot */ retval = p_slot->hpc_ops->power_on_slot(p_slot); if (retval) return retval; } if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_blink(p_slot); /* Check link training status */ retval = p_slot->hpc_ops->check_lnk_status(ctrl); if (retval) { ctrl_err(ctrl, "Failed to check link status\n"); set_slot_off(ctrl, p_slot); return retval; } /* Check for a power fault */ if (p_slot->hpc_ops->query_power_fault(p_slot)) { ctrl_dbg(ctrl, "Power fault detected\n"); retval = POWER_FAILURE; goto err_exit; } retval = pciehp_configure_device(p_slot); if (retval) { ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n", pci_domain_nr(parent), p_slot->bus, p_slot->device); goto err_exit; } /* * Some PCI Express root ports require fixup after hot-plug operation. */ if (pcie_mch_quirk) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_on(p_slot); return 0; err_exit: set_slot_off(ctrl, p_slot); return retval; }
static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { int retval = 0; struct controller *ctrl = slot->ctrl; u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); u8 m66_cap = !!(slot_reg & MHZ66_CAP); u8 pi, pcix_cap; retval = hpc_get_prog_int(slot, &pi); if (retval) return retval; switch (pi) { case 1: pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; break; case 2: pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; break; default: return -ENODEV; } ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", __func__, slot_reg, pcix_cap, m66_cap); switch (pcix_cap) { case 0x0: *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; break; case 0x1: *value = PCI_SPEED_66MHz_PCIX; break; case 0x3: *value = PCI_SPEED_133MHz_PCIX; break; case 0x4: *value = PCI_SPEED_133MHz_PCIX_266; break; case 0x5: *value = PCI_SPEED_133MHz_PCIX_533; break; case 0x2: default: *value = PCI_SPEED_UNKNOWN; retval = -ENODEV; break; } ctrl_dbg(ctrl, "Adapter speed = %d\n", *value); return retval; }
u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; u32 event_type; /* Power fault */ ctrl_dbg(ctrl, "Power fault interrupt received\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { /* * Power fault Cleared */ ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", slot_name(p_slot)); p_slot->status = 0x00; event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot); } queue_interrupt_event(p_slot, event_type); return 1; }
int pciehp_get_cur_link_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, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", __func__); return retval; } switch (lnk_status & PCI_EXP_LNKSTA_CLS) { case 1: lnk_speed = PCIE_2_5GB; break; case 2: lnk_speed = PCIE_5_0GB; break; default: lnk_speed = PCIE_LNK_SPEED_UNKNOWN; break; } *value = lnk_speed; ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed); return retval; }
int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *value) { struct controller *ctrl = slot->ctrl; enum pcie_link_speed lnk_speed; u32 lnk_cap; int retval = 0; retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); if (retval) { ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); return retval; } switch (lnk_cap & 0x000F) { case 1: lnk_speed = PCIE_2_5GB; break; case 2: lnk_speed = PCIE_5_0GB; break; default: lnk_speed = PCIE_LNK_SPEED_UNKNOWN; break; } *value = lnk_speed; ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed); return retval; }
int pciehp_set_attention_status(struct slot *slot, u8 value) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; int rc; cmd_mask = PCI_EXP_SLTCTL_AIC; switch (value) { case 0 : /* turn off */ slot_cmd = 0x00C0; break; case 1: /* turn on */ slot_cmd = 0x0040; break; case 2: /* turn blink */ slot_cmd = 0x0080; break; default: return -1; } rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); return rc; }
u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; u32 event_type; /* Presence Change */ ctrl_dbg(ctrl, "Presence/Notify input change\n"); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* * Save the presence state */ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); if (p_slot->presence_save) { /* * Card Present */ ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot)); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ ctrl_info(ctrl, "Card not present on Slot(%s)\n", slot_name(p_slot)); event_type = INT_PRESENCE_OFF; } queue_interrupt_event(p_slot, event_type); return 1; }
u8 pciehp_handle_presence_change(struct slot *p_slot) { u32 event_type; u8 presence_save; struct controller *ctrl = p_slot->ctrl; /* Presence Change */ ctrl_dbg(ctrl, "Presence/Notify input change\n"); /* Switch is open, assume a presence change * Save the presence state */ pciehp_get_adapter_status(p_slot, &presence_save); if (presence_save) { /* * Card Present */ ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot)); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ ctrl_info(ctrl, "Card not present on Slot(%s)\n", slot_name(p_slot)); event_type = INT_PRESENCE_OFF; } queue_interrupt_event(p_slot, event_type); return 1; }
int pciehp_get_power_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; u16 slot_ctrl; u8 pwr_state; int retval = 0; retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); return retval; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; switch (pwr_state) { case 0: *status = 1; break; case 1: *status = 0; break; default: *status = 0xFF; break; } return retval; }
void pciehp_set_attention_status(struct slot *slot, u8 value) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; if (!ATTN_LED(ctrl)) return; switch (value) { case 0: /* turn off */ slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF; break; case 1: /* turn on */ slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON; break; case 2: /* turn blink */ slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK; break; default: return; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC); }
void pciehp_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_ctrl; pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) { case PCI_EXP_SLTCTL_ATTN_IND_ON: *status = 1; /* On */ break; case PCI_EXP_SLTCTL_ATTN_IND_BLINK: *status = 2; /* Blink */ break; case PCI_EXP_SLTCTL_ATTN_IND_OFF: *status = 0; /* Off */ break; default: *status = 0xFF; break; } }
int pciehp_power_off_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; int retval; /* Disable the link at first */ pciehp_link_disable(ctrl); /* wait the link is down */ if (ctrl->link_active_reporting) pcie_wait_link_not_active(ctrl); else msleep(1000); slot_cmd = POWER_OFF; cmd_mask = PCI_EXP_SLTCTL_PCC; retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write command failed!\n"); return retval; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); return 0; }
static int __pciehp_link_set(struct controller *ctrl, bool enable) { u16 lnk_ctrl; int retval = 0; retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl); if (retval) { ctrl_err(ctrl, "Cannot read LNKCTRL register\n"); return retval; } if (enable) lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; else lnk_ctrl |= PCI_EXP_LNKCTL_LD; retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl); if (retval) { ctrl_err(ctrl, "Cannot write LNKCTRL register\n"); return retval; } ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); return retval; }
int pciehp_check_link_status(struct controller *ctrl) { u16 lnk_status; int retval = 0; /* * Data Link Layer Link Active Reporting must be capable for * hot-plug capable downstream port. But old controller might * not implement it. In this case, we wait for 1000 ms. */ if (ctrl->link_active_reporting) pcie_wait_link_active(ctrl); else msleep(1000); retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); return retval; } ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); if ((lnk_status & PCI_EXP_LNKSTA_LT) || !(lnk_status & PCI_EXP_LNKSTA_NLW)) { ctrl_err(ctrl, "Link Training Error occurs \n"); retval = -1; return retval; } return retval; }
int pciehp_power_on_slot(struct slot *slot) { struct controller *ctrl = slot->ctrl; struct pci_dev *pdev = ctrl_dev(ctrl); u16 slot_status; int retval; /* Clear sticky power-fault bit from previous power failures */ pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); if (slot_status & PCI_EXP_SLTSTA_PFD) pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PFD); ctrl->power_fault_detected = 0; pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PWR_ON); retval = pciehp_link_enable(ctrl); if (retval) ctrl_err(ctrl, "%s: Can not enable the link!\n", __func__); return retval; }
/** * remove_board - Turns off slot and LEDs * @p_slot: slot where board is being removed */ static int remove_board(struct slot *p_slot) { int retval = 0; struct controller *ctrl = p_slot->ctrl; retval = pciehp_unconfigure_device(p_slot); if (retval) return retval; ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, p_slot->hp_slot); if (POWER_CTRL(ctrl)) { /* power off slot */ retval = p_slot->hpc_ops->power_off_slot(p_slot); if (retval) { ctrl_err(ctrl, "Issue of Slot Disable command failed\n"); return retval; } } /* * After turning power off, we must wait for at least 1 second * before taking any action that relies on power having been * removed from the slot/adapter. */ msleep(1000); if (PWR_LED(ctrl)) /* turn off Green LED */ p_slot->hpc_ops->green_led_off(p_slot); return 0; }
int shpchp_unconfigure_device(struct slot *p_slot) { int rc = 0; int j; u8 bctl = 0; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; struct controller *ctrl = p_slot->ctrl; ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); for (j = 0; j < 8 ; j++) { struct pci_dev *temp = pci_get_slot(parent, (p_slot->device << 3) | j); if (!temp) continue; if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", pci_name(temp)); pci_dev_put(temp); rc = -EINVAL; break; } } pci_remove_bus_device(temp); pci_dev_put(temp); } return rc; }
u8 pciehp_handle_switch_change(struct slot *p_slot) { u8 getstatus; u32 event_type; struct controller *ctrl = p_slot->ctrl; /* Switch Change */ ctrl_dbg(ctrl, "Switch interrupt received\n"); pciehp_get_latch_status(p_slot, &getstatus); if (getstatus) { /* * Switch opened */ ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); event_type = INT_SWITCH_CLOSE; } queue_interrupt_event(p_slot, event_type); return 1; }
u8 pciehp_handle_power_fault(struct slot *p_slot) { u32 event_type; struct controller *ctrl = p_slot->ctrl; /* power fault */ ctrl_dbg(ctrl, "Power fault interrupt received\n"); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { /* * power fault Cleared */ ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", slot_name(p_slot)); event_type = INT_POWER_FAULT_CLEAR; } else { /* * power fault */ ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); event_type = INT_POWER_FAULT; ctrl_info(ctrl, "Power fault bit %x set\n", 0); } queue_interrupt_event(p_slot, event_type); return 1; }
static int hpc_power_on_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; u16 slot_status; int retval = 0; ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot); /* Clear sticky power-fault bit from previous power failures */ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", __func__); return retval; } slot_status &= PCI_EXP_SLTSTA_PFD; if (slot_status) { retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); if (retval) { ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS register\n", __func__); return retval; } } slot_cmd = POWER_ON; cmd_mask = PCI_EXP_SLTCTL_PCC; if (!pciehp_poll_mode) { /* Enable power fault detection turned off at power off time */ slot_cmd |= PCI_EXP_SLTCTL_PFDE; cmd_mask |= PCI_EXP_SLTCTL_PFDE; } retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); return retval; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); ctrl->power_fault_detected = 0; return retval; }
void pciehp_power_off_slot(struct slot *slot) { struct controller *ctrl = slot->ctrl; pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PWR_OFF); }
void pciehp_green_led_blink(struct slot *slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; slot_cmd = 0x0200; cmd_mask = PCI_EXP_SLTCTL_PIC; pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); }
void pciehp_green_led_blink(struct slot *slot) { struct controller *ctrl = slot->ctrl; if (!PWR_LED(ctrl)) return; pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PWR_IND_BLINK); }
void pciehp_green_led_off(struct slot *slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; slot_cmd = 0x0300; cmd_mask = PCI_EXP_SLTCTL_PIC; pcie_write_cmd(ctrl, slot_cmd, cmd_mask); ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); }
static int hpc_power_off_slot(struct slot * slot) { struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; int retval = 0; int changed; ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot); /* * Set Bad DLLP Mask bit in Correctable Error Mask * Register. This is the workaround against Bad DLLP error * that sometimes happens during turning power off the slot * which conforms to PCI Express 1.0a spec. */ changed = pcie_mask_bad_dllp(ctrl); slot_cmd = POWER_OFF; cmd_mask = PCI_EXP_SLTCTL_PCC; if (!pciehp_poll_mode) { /* Disable power fault detection */ slot_cmd &= ~PCI_EXP_SLTCTL_PFDE; cmd_mask |= PCI_EXP_SLTCTL_PFDE; } retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { ctrl_err(ctrl, "Write command failed!\n"); retval = -1; goto out; } ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); out: if (changed) pcie_unmask_bad_dllp(ctrl); return retval; }
static void pcie_wait_cmd(struct controller *ctrl, int poll) { unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; unsigned long timeout = msecs_to_jiffies(msecs); int rc; if (poll) rc = pcie_poll_cmd(ctrl); else rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); if (!rc) ctrl_dbg(ctrl, "Command not completed in 1000 msec\n"); }
/* The following routines constitute the bulk of the hotplug controller logic */ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed) { int rc = 0; ctrl_dbg(ctrl, "Change speed to %d\n", speed); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { ctrl_err(ctrl, "%s: Issue of set bus speed mode command " "failed\n", __func__); return WRONG_BUS_FREQUENCY; } return rc; }
int pciehp_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, PCI_EXP_LNKSTA, &lnk_status); if (retval) { ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", __func__); return retval; } switch ((lnk_status & PCI_EXP_LNKSTA_NLW) >> 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; ctrl_dbg(ctrl, "Current link width = %d\n", lnk_wdth); return retval; }
static void pcie_wait_link_active(struct controller *ctrl) { int timeout = 1000; if (check_link_active(ctrl)) return; while (timeout > 0) { msleep(10); timeout -= 10; if (check_link_active(ctrl)) return; } ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n"); }