diff options
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 55 |
3 files changed, 55 insertions, 4 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 394f99852e6d..a4817a841fae 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -110,6 +110,7 @@ struct controller { | |||
110 | struct timer_list poll_timer; | 110 | struct timer_list poll_timer; |
111 | int cmd_busy; | 111 | int cmd_busy; |
112 | unsigned int no_cmd_complete:1; | 112 | unsigned int no_cmd_complete:1; |
113 | unsigned int link_active_reporting:1; | ||
113 | }; | 114 | }; |
114 | 115 | ||
115 | #define INT_BUTTON_IGNORE 0 | 116 | #define INT_BUTTON_IGNORE 0 |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index cce6e5f659e8..d6c5eb297753 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -226,9 +226,6 @@ static int board_added(struct slot *p_slot) | |||
226 | if (PWR_LED(ctrl)) | 226 | if (PWR_LED(ctrl)) |
227 | p_slot->hpc_ops->green_led_blink(p_slot); | 227 | p_slot->hpc_ops->green_led_blink(p_slot); |
228 | 228 | ||
229 | /* Wait for ~1 second */ | ||
230 | msleep(1000); | ||
231 | |||
232 | /* Check link training status */ | 229 | /* Check link training status */ |
233 | retval = p_slot->hpc_ops->check_lnk_status(ctrl); | 230 | retval = p_slot->hpc_ops->check_lnk_status(ctrl); |
234 | if (retval) { | 231 | if (retval) { |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 4b921226f888..58c72d2cc217 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -125,6 +125,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
125 | /* Field definitions in Link Capabilities Register */ | 125 | /* Field definitions in Link Capabilities Register */ |
126 | #define MAX_LNK_SPEED 0x000F | 126 | #define MAX_LNK_SPEED 0x000F |
127 | #define MAX_LNK_WIDTH 0x03F0 | 127 | #define MAX_LNK_WIDTH 0x03F0 |
128 | #define LINK_ACTIVE_REPORTING 0x00100000 | ||
128 | 129 | ||
129 | /* Link Width Encoding */ | 130 | /* Link Width Encoding */ |
130 | #define LNK_X1 0x01 | 131 | #define LNK_X1 0x01 |
@@ -141,6 +142,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
141 | #define LNK_TRN_ERR 0x0400 | 142 | #define LNK_TRN_ERR 0x0400 |
142 | #define LNK_TRN 0x0800 | 143 | #define LNK_TRN 0x0800 |
143 | #define SLOT_CLK_CONF 0x1000 | 144 | #define SLOT_CLK_CONF 0x1000 |
145 | #define LINK_ACTIVE 0x2000 | ||
144 | 146 | ||
145 | /* Field definitions in Slot Capabilities Register */ | 147 | /* Field definitions in Slot Capabilities Register */ |
146 | #define ATTN_BUTTN_PRSN 0x00000001 | 148 | #define ATTN_BUTTN_PRSN 0x00000001 |
@@ -368,11 +370,52 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
368 | return retval; | 370 | return retval; |
369 | } | 371 | } |
370 | 372 | ||
373 | static inline int check_link_active(struct controller *ctrl) | ||
374 | { | ||
375 | u16 link_status; | ||
376 | |||
377 | if (pciehp_readw(ctrl, LNKSTATUS, &link_status)) | ||
378 | return 0; | ||
379 | return !!(link_status & LINK_ACTIVE); | ||
380 | } | ||
381 | |||
382 | static void pcie_wait_link_active(struct controller *ctrl) | ||
383 | { | ||
384 | int timeout = 1000; | ||
385 | |||
386 | if (check_link_active(ctrl)) | ||
387 | return; | ||
388 | while (timeout > 0) { | ||
389 | msleep(10); | ||
390 | timeout -= 10; | ||
391 | if (check_link_active(ctrl)) | ||
392 | return; | ||
393 | } | ||
394 | ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n"); | ||
395 | } | ||
396 | |||
371 | static int hpc_check_lnk_status(struct controller *ctrl) | 397 | static int hpc_check_lnk_status(struct controller *ctrl) |
372 | { | 398 | { |
373 | u16 lnk_status; | 399 | u16 lnk_status; |
374 | int retval = 0; | 400 | int retval = 0; |
375 | 401 | ||
402 | /* | ||
403 | * Data Link Layer Link Active Reporting must be capable for | ||
404 | * hot-plug capable downstream port. But old controller might | ||
405 | * not implement it. In this case, we wait for 1000 ms. | ||
406 | */ | ||
407 | if (ctrl->link_active_reporting){ | ||
408 | /* Wait for Data Link Layer Link Active bit to be set */ | ||
409 | pcie_wait_link_active(ctrl); | ||
410 | /* | ||
411 | * We must wait for 100 ms after the Data Link Layer | ||
412 | * Link Active bit reads 1b before initiating a | ||
413 | * configuration access to the hot added device. | ||
414 | */ | ||
415 | msleep(100); | ||
416 | } else | ||
417 | msleep(1000); | ||
418 | |||
376 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); | 419 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); |
377 | if (retval) { | 420 | if (retval) { |
378 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | 421 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", |
@@ -1131,7 +1174,7 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
1131 | struct controller *pcie_init(struct pcie_device *dev) | 1174 | struct controller *pcie_init(struct pcie_device *dev) |
1132 | { | 1175 | { |
1133 | struct controller *ctrl; | 1176 | struct controller *ctrl; |
1134 | u32 slot_cap; | 1177 | u32 slot_cap, link_cap; |
1135 | struct pci_dev *pdev = dev->port; | 1178 | struct pci_dev *pdev = dev->port; |
1136 | 1179 | ||
1137 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | 1180 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); |
@@ -1173,6 +1216,16 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
1173 | !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) | 1216 | !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) |
1174 | ctrl->no_cmd_complete = 1; | 1217 | ctrl->no_cmd_complete = 1; |
1175 | 1218 | ||
1219 | /* Check if Data Link Layer Link Active Reporting is implemented */ | ||
1220 | if (pciehp_readl(ctrl, LNKCAP, &link_cap)) { | ||
1221 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | ||
1222 | goto abort_ctrl; | ||
1223 | } | ||
1224 | if (link_cap & LINK_ACTIVE_REPORTING) { | ||
1225 | ctrl_dbg(ctrl, "Link Active Reporting supported\n"); | ||
1226 | ctrl->link_active_reporting = 1; | ||
1227 | } | ||
1228 | |||
1176 | /* Clear all remaining event bits in Slot Status register */ | 1229 | /* Clear all remaining event bits in Slot Status register */ |
1177 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) | 1230 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) |
1178 | goto abort_ctrl; | 1231 | goto abort_ctrl; |