diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2008-04-17 00:09:24 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-17 00:09:24 -0400 |
commit | a51a2513a8cb201f02d83c37e106909938d2f761 (patch) | |
tree | 74e4dad1421eb922f7e108c968d2c7a1666b779e | |
parent | 58411d1c012dca53ec9107bd98acb63f648e2435 (diff) |
IB/ipath: Add code to support multiple link speeds and widths
This patch adds code to get/set portinfo to support multiple link speeds
and widths.
Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_mad.c | 89 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_verbs.c | 11 |
3 files changed, 69 insertions, 33 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index caee731b670f..960d5b7e7865 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -801,6 +801,8 @@ void ipath_hol_event(unsigned long); | |||
801 | /* | 801 | /* |
802 | * values for ipath_flags | 802 | * values for ipath_flags |
803 | */ | 803 | */ |
804 | /* chip can report link latency (IB 1.2) */ | ||
805 | #define IPATH_HAS_LINK_LATENCY 0x1 | ||
804 | /* The chip is up and initted */ | 806 | /* The chip is up and initted */ |
805 | #define IPATH_INITTED 0x2 | 807 | #define IPATH_INITTED 0x2 |
806 | /* set if any user code has set kr_rcvhdrsize */ | 808 | /* set if any user code has set kr_rcvhdrsize */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index aca876bae1c4..7516a2608988 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c | |||
@@ -146,6 +146,15 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp, | |||
146 | return reply(smp); | 146 | return reply(smp); |
147 | } | 147 | } |
148 | 148 | ||
149 | static void set_link_width_enabled(struct ipath_devdata *dd, u32 w) | ||
150 | { | ||
151 | (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w); | ||
152 | } | ||
153 | |||
154 | static void set_link_speed_enabled(struct ipath_devdata *dd, u32 s) | ||
155 | { | ||
156 | (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s); | ||
157 | } | ||
149 | 158 | ||
150 | static int get_overrunthreshold(struct ipath_devdata *dd) | 159 | static int get_overrunthreshold(struct ipath_devdata *dd) |
151 | { | 160 | { |
@@ -226,6 +235,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
226 | struct ib_device *ibdev, u8 port) | 235 | struct ib_device *ibdev, u8 port) |
227 | { | 236 | { |
228 | struct ipath_ibdev *dev; | 237 | struct ipath_ibdev *dev; |
238 | struct ipath_devdata *dd; | ||
229 | struct ib_port_info *pip = (struct ib_port_info *)smp->data; | 239 | struct ib_port_info *pip = (struct ib_port_info *)smp->data; |
230 | u16 lid; | 240 | u16 lid; |
231 | u8 ibcstat; | 241 | u8 ibcstat; |
@@ -239,6 +249,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
239 | } | 249 | } |
240 | 250 | ||
241 | dev = to_idev(ibdev); | 251 | dev = to_idev(ibdev); |
252 | dd = dev->dd; | ||
242 | 253 | ||
243 | /* Clear all fields. Only set the non-zero fields. */ | 254 | /* Clear all fields. Only set the non-zero fields. */ |
244 | memset(smp->data, 0, sizeof(smp->data)); | 255 | memset(smp->data, 0, sizeof(smp->data)); |
@@ -248,25 +259,28 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
248 | dev->mkeyprot == 0) | 259 | dev->mkeyprot == 0) |
249 | pip->mkey = dev->mkey; | 260 | pip->mkey = dev->mkey; |
250 | pip->gid_prefix = dev->gid_prefix; | 261 | pip->gid_prefix = dev->gid_prefix; |
251 | lid = dev->dd->ipath_lid; | 262 | lid = dd->ipath_lid; |
252 | pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE; | 263 | pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE; |
253 | pip->sm_lid = cpu_to_be16(dev->sm_lid); | 264 | pip->sm_lid = cpu_to_be16(dev->sm_lid); |
254 | pip->cap_mask = cpu_to_be32(dev->port_cap_flags); | 265 | pip->cap_mask = cpu_to_be32(dev->port_cap_flags); |
255 | /* pip->diag_code; */ | 266 | /* pip->diag_code; */ |
256 | pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period); | 267 | pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period); |
257 | pip->local_port_num = port; | 268 | pip->local_port_num = port; |
258 | pip->link_width_enabled = dev->link_width_enabled; | 269 | pip->link_width_enabled = dd->ipath_link_width_enabled; |
259 | pip->link_width_supported = 3; /* 1x or 4x */ | 270 | pip->link_width_supported = dd->ipath_link_width_supported; |
260 | pip->link_width_active = 2; /* 4x */ | 271 | pip->link_width_active = dd->ipath_link_width_active; |
261 | pip->linkspeed_portstate = 0x10; /* 2.5Gbps */ | 272 | pip->linkspeed_portstate = dd->ipath_link_speed_supported << 4; |
262 | ibcstat = dev->dd->ipath_lastibcstat; | 273 | ibcstat = dd->ipath_lastibcstat; |
263 | pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1; | 274 | /* map LinkState to IB portinfo values. */ |
275 | pip->linkspeed_portstate |= ipath_ib_linkstate(dd, ibcstat) + 1; | ||
276 | |||
264 | pip->portphysstate_linkdown = | 277 | pip->portphysstate_linkdown = |
265 | (ipath_cvt_physportstate[ibcstat & 0xf] << 4) | | 278 | (ipath_cvt_physportstate[ibcstat & dd->ibcs_lts_mask] << 4) | |
266 | (get_linkdowndefaultstate(dev->dd) ? 1 : 2); | 279 | (get_linkdowndefaultstate(dd) ? 1 : 2); |
267 | pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dev->dd->ipath_lmc; | 280 | pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dd->ipath_lmc; |
268 | pip->linkspeedactive_enabled = 0x11; /* 2.5Gbps, 2.5Gbps */ | 281 | pip->linkspeedactive_enabled = (dd->ipath_link_speed_active << 4) | |
269 | switch (dev->dd->ipath_ibmtu) { | 282 | dd->ipath_link_speed_enabled; |
283 | switch (dd->ipath_ibmtu) { | ||
270 | case 4096: | 284 | case 4096: |
271 | mtu = IB_MTU_4096; | 285 | mtu = IB_MTU_4096; |
272 | break; | 286 | break; |
@@ -300,7 +314,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
300 | pip->mkey_violations = cpu_to_be16(dev->mkey_violations); | 314 | pip->mkey_violations = cpu_to_be16(dev->mkey_violations); |
301 | /* P_KeyViolations are counted by hardware. */ | 315 | /* P_KeyViolations are counted by hardware. */ |
302 | pip->pkey_violations = | 316 | pip->pkey_violations = |
303 | cpu_to_be16((ipath_get_cr_errpkey(dev->dd) - | 317 | cpu_to_be16((ipath_get_cr_errpkey(dd) - |
304 | dev->z_pkey_violations) & 0xFFFF); | 318 | dev->z_pkey_violations) & 0xFFFF); |
305 | pip->qkey_violations = cpu_to_be16(dev->qkey_violations); | 319 | pip->qkey_violations = cpu_to_be16(dev->qkey_violations); |
306 | /* Only the hardware GUID is supported for now */ | 320 | /* Only the hardware GUID is supported for now */ |
@@ -309,10 +323,17 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
309 | /* 32.768 usec. response time (guessing) */ | 323 | /* 32.768 usec. response time (guessing) */ |
310 | pip->resv_resptimevalue = 3; | 324 | pip->resv_resptimevalue = 3; |
311 | pip->localphyerrors_overrunerrors = | 325 | pip->localphyerrors_overrunerrors = |
312 | (get_phyerrthreshold(dev->dd) << 4) | | 326 | (get_phyerrthreshold(dd) << 4) | |
313 | get_overrunthreshold(dev->dd); | 327 | get_overrunthreshold(dd); |
314 | /* pip->max_credit_hint; */ | 328 | /* pip->max_credit_hint; */ |
315 | /* pip->link_roundtrip_latency[3]; */ | 329 | if (dev->port_cap_flags & IB_PORT_LINK_LATENCY_SUP) { |
330 | u32 v; | ||
331 | |||
332 | v = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LINKLATENCY); | ||
333 | pip->link_roundtrip_latency[0] = v >> 16; | ||
334 | pip->link_roundtrip_latency[1] = v >> 8; | ||
335 | pip->link_roundtrip_latency[2] = v; | ||
336 | } | ||
316 | 337 | ||
317 | ret = reply(smp); | 338 | ret = reply(smp); |
318 | 339 | ||
@@ -440,19 +461,25 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, | |||
440 | ib_dispatch_event(&event); | 461 | ib_dispatch_event(&event); |
441 | } | 462 | } |
442 | 463 | ||
443 | /* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */ | 464 | /* Allow 1x or 4x to be set (see 14.2.6.6). */ |
444 | lwe = pip->link_width_enabled; | 465 | lwe = pip->link_width_enabled; |
445 | if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE)) | 466 | if (lwe) { |
446 | goto err; | 467 | if (lwe == 0xFF) |
447 | if (lwe == 0xFF) | 468 | lwe = dd->ipath_link_width_supported; |
448 | dev->link_width_enabled = 3; /* 1x or 4x */ | 469 | else if (lwe >= 16 || (lwe & ~dd->ipath_link_width_supported)) |
449 | else if (lwe) | 470 | goto err; |
450 | dev->link_width_enabled = lwe; | 471 | set_link_width_enabled(dd, lwe); |
472 | } | ||
451 | 473 | ||
452 | /* Only 2.5 Gbs supported. */ | 474 | /* Allow 2.5 or 5.0 Gbs. */ |
453 | lse = pip->linkspeedactive_enabled & 0xF; | 475 | lse = pip->linkspeedactive_enabled & 0xF; |
454 | if (lse >= 2 && lse <= 0xE) | 476 | if (lse) { |
455 | goto err; | 477 | if (lse == 15) |
478 | lse = dd->ipath_link_speed_supported; | ||
479 | else if (lse >= 8 || (lse & ~dd->ipath_link_speed_supported)) | ||
480 | goto err; | ||
481 | set_link_speed_enabled(dd, lse); | ||
482 | } | ||
456 | 483 | ||
457 | /* Set link down default state. */ | 484 | /* Set link down default state. */ |
458 | switch (pip->portphysstate_linkdown & 0xF) { | 485 | switch (pip->portphysstate_linkdown & 0xF) { |
@@ -946,10 +973,14 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp, | |||
946 | * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample | 973 | * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample |
947 | * intervals are counted in ticks. Since we use Linux timers, that | 974 | * intervals are counted in ticks. Since we use Linux timers, that |
948 | * count in jiffies, we can't sample for less than 1000 ticks if HZ | 975 | * count in jiffies, we can't sample for less than 1000 ticks if HZ |
949 | * == 1000 (4000 ticks if HZ is 250). | 976 | * == 1000 (4000 ticks if HZ is 250). link_speed_active returns 2 for |
977 | * DDR, 1 for SDR, set the tick to 1 for DDR, 0 for SDR on chips that | ||
978 | * have hardware support for delaying packets. | ||
950 | */ | 979 | */ |
951 | /* XXX This is WRONG. */ | 980 | if (crp->cr_psstat) |
952 | p->tick = 250; /* 1 usec. */ | 981 | p->tick = dev->dd->ipath_link_speed_active - 1; |
982 | else | ||
983 | p->tick = 250; /* 1 usec. */ | ||
953 | p->counter_width = 4; /* 32 bit counters */ | 984 | p->counter_width = 4; /* 32 bit counters */ |
954 | p->counter_mask0_9 = COUNTER_MASK0_9; | 985 | p->counter_mask0_9 = COUNTER_MASK0_9; |
955 | spin_lock_irqsave(&dev->pending_lock, flags); | 986 | spin_lock_irqsave(&dev->pending_lock, flags); |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 012ccb4f9a37..2f9bc29313af 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -1183,7 +1183,9 @@ static int ipath_query_port(struct ib_device *ibdev, | |||
1183 | props->sm_lid = dev->sm_lid; | 1183 | props->sm_lid = dev->sm_lid; |
1184 | props->sm_sl = dev->sm_sl; | 1184 | props->sm_sl = dev->sm_sl; |
1185 | ibcstat = dd->ipath_lastibcstat; | 1185 | ibcstat = dd->ipath_lastibcstat; |
1186 | props->state = ((ibcstat >> 4) & 0x3) + 1; | 1186 | /* map LinkState to IB portinfo values. */ |
1187 | props->state = ipath_ib_linkstate(dd, ibcstat) + 1; | ||
1188 | |||
1187 | /* See phys_state_show() */ | 1189 | /* See phys_state_show() */ |
1188 | props->phys_state = /* MEA: assumes shift == 0 */ | 1190 | props->phys_state = /* MEA: assumes shift == 0 */ |
1189 | ipath_cvt_physportstate[dd->ipath_lastibcstat & | 1191 | ipath_cvt_physportstate[dd->ipath_lastibcstat & |
@@ -1195,9 +1197,9 @@ static int ipath_query_port(struct ib_device *ibdev, | |||
1195 | props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) - | 1197 | props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) - |
1196 | dev->z_pkey_violations; | 1198 | dev->z_pkey_violations; |
1197 | props->qkey_viol_cntr = dev->qkey_violations; | 1199 | props->qkey_viol_cntr = dev->qkey_violations; |
1198 | props->active_width = IB_WIDTH_4X; | 1200 | props->active_width = dd->ipath_link_width_active; |
1199 | /* See rate_show() */ | 1201 | /* See rate_show() */ |
1200 | props->active_speed = 1; /* Regular 10Mbs speed. */ | 1202 | props->active_speed = dd->ipath_link_speed_active; |
1201 | props->max_vl_num = 1; /* VLCap = VL0 */ | 1203 | props->max_vl_num = 1; /* VLCap = VL0 */ |
1202 | props->init_type_reply = 0; | 1204 | props->init_type_reply = 0; |
1203 | 1205 | ||
@@ -1629,12 +1631,13 @@ int ipath_register_ib_device(struct ipath_devdata *dd) | |||
1629 | idev->pending_index = 0; | 1631 | idev->pending_index = 0; |
1630 | idev->port_cap_flags = | 1632 | idev->port_cap_flags = |
1631 | IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP; | 1633 | IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP; |
1634 | if (dd->ipath_flags & IPATH_HAS_LINK_LATENCY) | ||
1635 | idev->port_cap_flags |= IB_PORT_LINK_LATENCY_SUP; | ||
1632 | idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA; | 1636 | idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA; |
1633 | idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; | 1637 | idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; |
1634 | idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; | 1638 | idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; |
1635 | idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS; | 1639 | idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS; |
1636 | idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT; | 1640 | idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT; |
1637 | idev->link_width_enabled = 3; /* 1x or 4x */ | ||
1638 | 1641 | ||
1639 | /* Snapshot current HW counters to "clear" them. */ | 1642 | /* Snapshot current HW counters to "clear" them. */ |
1640 | ipath_get_counters(dd, &cntrs); | 1643 | ipath_get_counters(dd, &cntrs); |