aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_driver.c
diff options
context:
space:
mode:
authorJohn Gregor <john.gregor@qlogic.com>2007-09-05 04:57:14 -0400
committerRoland Dreier <rolandd@cisco.com>2008-01-25 17:15:27 -0500
commite342c119172f87f2d812bccfd0283f62e1bc1c2a (patch)
tree52eb0e75f5f894ab7f0f3c755f0876f18637e5a9 /drivers/infiniband/hw/ipath/ipath_driver.c
parent9ab4295d1d9ab10a249aea002060685f935a528c (diff)
IB/ipath: Fix sendctrl locking
Code review pointed out that the locking around uses of ipath_sendctrl and kr_sendctrl were, in several places, incorrect and/or inconsistent. Signed-off-by: John Gregor <john.gregor@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_driver.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index fc355981bba..6a48442a8d5 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -803,31 +803,37 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
803 unsigned cnt) 803 unsigned cnt)
804{ 804{
805 unsigned i, last = first + cnt; 805 unsigned i, last = first + cnt;
806 u64 sendctrl, sendorig; 806 unsigned long flags;
807 807
808 ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first); 808 ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
809 sendorig = dd->ipath_sendctrl;
810 for (i = first; i < last; i++) { 809 for (i = first; i < last; i++) {
811 sendctrl = sendorig | INFINIPATH_S_DISARM | 810 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
812 (i << INFINIPATH_S_DISARMPIOBUF_SHIFT); 811 /*
812 * The disarm-related bits are write-only, so it
813 * is ok to OR them in with our copy of sendctrl
814 * while we hold the lock.
815 */
813 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 816 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
814 sendctrl); 817 dd->ipath_sendctrl | INFINIPATH_S_DISARM |
818 (i << INFINIPATH_S_DISARMPIOBUF_SHIFT));
819 /* can't disarm bufs back-to-back per iba7220 spec */
820 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
821 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
815 } 822 }
816 823
817 /* 824 /*
818 * Write it again with current value, in case ipath_sendctrl changed 825 * Disable PIOAVAILUPD, then re-enable, reading scratch in
819 * while we were looping; no critical bits that would require
820 * locking.
821 *
822 * disable PIOAVAILUPD, then re-enable, reading scratch in
823 * between. This seems to avoid a chip timing race that causes 826 * between. This seems to avoid a chip timing race that causes
824 * pioavail updates to memory to stop. 827 * pioavail updates to memory to stop. We xor as we don't
828 * know the state of the bit when we're called.
825 */ 829 */
830 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
826 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 831 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
827 sendorig & ~INFINIPATH_S_PIOBUFAVAILUPD); 832 dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
828 sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); 833 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
829 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 834 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
830 dd->ipath_sendctrl); 835 dd->ipath_sendctrl);
836 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
831} 837}
832 838
833/** 839/**
@@ -2056,6 +2062,8 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
2056 */ 2062 */
2057void ipath_shutdown_device(struct ipath_devdata *dd) 2063void ipath_shutdown_device(struct ipath_devdata *dd)
2058{ 2064{
2065 unsigned long flags;
2066
2059 ipath_dbg("Shutting down the device\n"); 2067 ipath_dbg("Shutting down the device\n");
2060 2068
2061 dd->ipath_flags |= IPATH_LINKUNK; 2069 dd->ipath_flags |= IPATH_LINKUNK;
@@ -2076,9 +2084,13 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
2076 * gracefully stop all sends allowing any in progress to trickle out 2084 * gracefully stop all sends allowing any in progress to trickle out
2077 * first. 2085 * first.
2078 */ 2086 */
2079 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL); 2087 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
2088 dd->ipath_sendctrl = 0;
2089 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
2080 /* flush it */ 2090 /* flush it */
2081 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); 2091 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
2092 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
2093
2082 /* 2094 /*
2083 * enough for anything that's going to trickle out to have actually 2095 * enough for anything that's going to trickle out to have actually
2084 * done so. 2096 * done so.