diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_driver.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 93 |
1 files changed, 88 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 6ccba365a24..1f152ded1e3 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/io.h> | ||
37 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
38 | #include <linux/netdevice.h> | 39 | #include <linux/netdevice.h> |
39 | #include <linux/vmalloc.h> | 40 | #include <linux/vmalloc.h> |
@@ -280,6 +281,89 @@ void __attribute__((weak)) ipath_disable_wc(struct ipath_devdata *dd) | |||
280 | { | 281 | { |
281 | } | 282 | } |
282 | 283 | ||
284 | /* | ||
285 | * Perform a PIO buffer bandwidth write test, to verify proper system | ||
286 | * configuration. Even when all the setup calls work, occasionally | ||
287 | * BIOS or other issues can prevent write combining from working, or | ||
288 | * can cause other bandwidth problems to the chip. | ||
289 | * | ||
290 | * This test simply writes the same buffer over and over again, and | ||
291 | * measures close to the peak bandwidth to the chip (not testing | ||
292 | * data bandwidth to the wire). On chips that use an address-based | ||
293 | * trigger to send packets to the wire, this is easy. On chips that | ||
294 | * use a count to trigger, we want to make sure that the packet doesn't | ||
295 | * go out on the wire, or trigger flow control checks. | ||
296 | */ | ||
297 | static void ipath_verify_pioperf(struct ipath_devdata *dd) | ||
298 | { | ||
299 | u32 pbnum, cnt, lcnt; | ||
300 | u32 __iomem *piobuf; | ||
301 | u32 *addr; | ||
302 | u64 msecs, emsecs; | ||
303 | |||
304 | piobuf = ipath_getpiobuf(dd, &pbnum); | ||
305 | if (!piobuf) { | ||
306 | dev_info(&dd->pcidev->dev, | ||
307 | "No PIObufs for checking perf, skipping\n"); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Enough to give us a reasonable test, less than piobuf size, and | ||
313 | * likely multiple of store buffer length. | ||
314 | */ | ||
315 | cnt = 1024; | ||
316 | |||
317 | addr = vmalloc(cnt); | ||
318 | if (!addr) { | ||
319 | dev_info(&dd->pcidev->dev, | ||
320 | "Couldn't get memory for checking PIO perf," | ||
321 | " skipping\n"); | ||
322 | goto done; | ||
323 | } | ||
324 | |||
325 | preempt_disable(); /* we want reasonably accurate elapsed time */ | ||
326 | msecs = 1 + jiffies_to_msecs(jiffies); | ||
327 | for (lcnt = 0; lcnt < 10000U; lcnt++) { | ||
328 | /* wait until we cross msec boundary */ | ||
329 | if (jiffies_to_msecs(jiffies) >= msecs) | ||
330 | break; | ||
331 | udelay(1); | ||
332 | } | ||
333 | |||
334 | writeq(0, piobuf); /* length 0, no dwords actually sent */ | ||
335 | ipath_flush_wc(); | ||
336 | |||
337 | /* | ||
338 | * this is only roughly accurate, since even with preempt we | ||
339 | * still take interrupts that could take a while. Running for | ||
340 | * >= 5 msec seems to get us "close enough" to accurate values | ||
341 | */ | ||
342 | msecs = jiffies_to_msecs(jiffies); | ||
343 | for (emsecs = lcnt = 0; emsecs <= 5UL; lcnt++) { | ||
344 | __iowrite32_copy(piobuf + 64, addr, cnt >> 2); | ||
345 | emsecs = jiffies_to_msecs(jiffies) - msecs; | ||
346 | } | ||
347 | |||
348 | /* 1 GiB/sec, slightly over IB SDR line rate */ | ||
349 | if (lcnt < (emsecs * 1024U)) | ||
350 | ipath_dev_err(dd, | ||
351 | "Performance problem: bandwidth to PIO buffers is " | ||
352 | "only %u MiB/sec\n", | ||
353 | lcnt / (u32) emsecs); | ||
354 | else | ||
355 | ipath_dbg("PIO buffer bandwidth %u MiB/sec is OK\n", | ||
356 | lcnt / (u32) emsecs); | ||
357 | |||
358 | preempt_enable(); | ||
359 | |||
360 | vfree(addr); | ||
361 | |||
362 | done: | ||
363 | /* disarm piobuf, so it's available again */ | ||
364 | ipath_disarm_piobufs(dd, pbnum, 1); | ||
365 | } | ||
366 | |||
283 | static int __devinit ipath_init_one(struct pci_dev *pdev, | 367 | static int __devinit ipath_init_one(struct pci_dev *pdev, |
284 | const struct pci_device_id *ent) | 368 | const struct pci_device_id *ent) |
285 | { | 369 | { |
@@ -298,8 +382,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
298 | 382 | ||
299 | ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit); | 383 | ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit); |
300 | 384 | ||
301 | read_bars(dd, pdev, &bar0, &bar1); | ||
302 | |||
303 | ret = pci_enable_device(pdev); | 385 | ret = pci_enable_device(pdev); |
304 | if (ret) { | 386 | if (ret) { |
305 | /* This can happen iff: | 387 | /* This can happen iff: |
@@ -445,9 +527,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
445 | goto bail_regions; | 527 | goto bail_regions; |
446 | } | 528 | } |
447 | 529 | ||
448 | dd->ipath_deviceid = ent->device; /* save for later use */ | ||
449 | dd->ipath_vendorid = ent->vendor; | ||
450 | |||
451 | dd->ipath_pcirev = pdev->revision; | 530 | dd->ipath_pcirev = pdev->revision; |
452 | 531 | ||
453 | #if defined(__powerpc__) | 532 | #if defined(__powerpc__) |
@@ -515,6 +594,8 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
515 | ret = 0; | 594 | ret = 0; |
516 | } | 595 | } |
517 | 596 | ||
597 | ipath_verify_pioperf(dd); | ||
598 | |||
518 | ipath_device_create_group(&pdev->dev, dd); | 599 | ipath_device_create_group(&pdev->dev, dd); |
519 | ipathfs_add_device(dd); | 600 | ipathfs_add_device(dd); |
520 | ipath_user_add(dd); | 601 | ipath_user_add(dd); |
@@ -2005,6 +2086,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd) | |||
2005 | INFINIPATH_IBCC_LINKINITCMD_SHIFT); | 2086 | INFINIPATH_IBCC_LINKINITCMD_SHIFT); |
2006 | ipath_cancel_sends(dd, 0); | 2087 | ipath_cancel_sends(dd, 0); |
2007 | 2088 | ||
2089 | signal_ib_event(dd, IB_EVENT_PORT_ERR); | ||
2090 | |||
2008 | /* disable IBC */ | 2091 | /* disable IBC */ |
2009 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; | 2092 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; |
2010 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | 2093 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, |