aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2008-10-22 01:31:44 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-22 19:42:45 -0400
commitf18e9625e02bb3e5ba9e81104f14e9d904ab28c4 (patch)
tree688eb9985ec1f85e2c1869a7252004789fb09a14 /drivers/pci
parentb84346ef74cf76793070762b933387729c5df1ed (diff)
PCI hotplug: pciehp: poll data link layer link active
This patch adds polling mechanism for Data Link Layer Link Active bit after turning power on, instead of waiting for 1000 msec. This reduces reduce the unnecessary long wait. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c3
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c55
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
373static 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
382static 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
371static int hpc_check_lnk_status(struct controller *ctrl) 397static 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)
1131struct controller *pcie_init(struct pcie_device *dev) 1174struct 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;