aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
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
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')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c40
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c10
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c24
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c19
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c7
6 files changed, 72 insertions, 29 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index fc355981bbab..6a48442a8d59 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.
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 5de3243a47c3..92dae6f5b395 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2149,11 +2149,15 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
2149 2149
2150static int ipath_force_pio_avail_update(struct ipath_devdata *dd) 2150static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
2151{ 2151{
2152 u64 reg = dd->ipath_sendctrl; 2152 unsigned long flags;
2153 2153
2154 clear_bit(IPATH_S_PIOBUFAVAILUPD, &reg); 2154 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
2155 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, reg); 2155 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
2156 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
2157 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
2156 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); 2158 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
2159 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
2160 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
2157 2161
2158 return 0; 2162 return 0;
2159} 2163}
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 9e9d6fafcf0d..1c65ab907a33 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -345,7 +345,7 @@ static int init_chip_first(struct ipath_devdata *dd,
345 dd->ipath_piobcnt2k, dd->ipath_pio2kbase); 345 dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
346 346
347 spin_lock_init(&dd->ipath_tid_lock); 347 spin_lock_init(&dd->ipath_tid_lock);
348 348 spin_lock_init(&dd->ipath_sendctrl_lock);
349 spin_lock_init(&dd->ipath_gpio_lock); 349 spin_lock_init(&dd->ipath_gpio_lock);
350 spin_lock_init(&dd->ipath_eep_st_lock); 350 spin_lock_init(&dd->ipath_eep_st_lock);
351 mutex_init(&dd->ipath_eep_lock); 351 mutex_init(&dd->ipath_eep_lock);
@@ -372,9 +372,9 @@ static int init_chip_reset(struct ipath_devdata *dd,
372 *pdp = dd->ipath_pd[0]; 372 *pdp = dd->ipath_pd[0];
373 /* ensure chip does no sends or receives while we re-initialize */ 373 /* ensure chip does no sends or receives while we re-initialize */
374 dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U; 374 dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
375 ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0); 375 ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
376 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0); 376 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
377 ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0); 377 ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
378 378
379 rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt); 379 rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
380 if (dd->ipath_portcnt != rtmp) 380 if (dd->ipath_portcnt != rtmp)
@@ -487,6 +487,7 @@ static void enable_chip(struct ipath_devdata *dd,
487 struct ipath_portdata *pd, int reinit) 487 struct ipath_portdata *pd, int reinit)
488{ 488{
489 u32 val; 489 u32 val;
490 unsigned long flags;
490 int i; 491 int i;
491 492
492 if (!reinit) 493 if (!reinit)
@@ -495,11 +496,13 @@ static void enable_chip(struct ipath_devdata *dd,
495 ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 496 ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
496 dd->ipath_rcvctrl); 497 dd->ipath_rcvctrl);
497 498
499 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
498 /* Enable PIO send, and update of PIOavail regs to memory. */ 500 /* Enable PIO send, and update of PIOavail regs to memory. */
499 dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE | 501 dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
500 INFINIPATH_S_PIOBUFAVAILUPD; 502 INFINIPATH_S_PIOBUFAVAILUPD;
501 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 503 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
502 dd->ipath_sendctrl); 504 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
505 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
503 506
504 /* 507 /*
505 * enable port 0 receive, and receive interrupt. other ports 508 * enable port 0 receive, and receive interrupt. other ports
@@ -696,6 +699,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
696 u64 val; 699 u64 val;
697 struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ 700 struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
698 gfp_t gfp_flags = GFP_USER | __GFP_COMP; 701 gfp_t gfp_flags = GFP_USER | __GFP_COMP;
702 unsigned long flags;
699 703
700 ret = init_housekeeping(dd, &pd, reinit); 704 ret = init_housekeeping(dd, &pd, reinit);
701 if (ret) 705 if (ret)
@@ -827,8 +831,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
827 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 831 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
828 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED); 832 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
829 ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL); 833 ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
830 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 834
831 INFINIPATH_S_PIOENABLE); 835 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
836 dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE;
837 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
838 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
839 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
832 840
833 /* 841 /*
834 * before error clears, since we expect serdes pll errors during 842 * before error clears, since we expect serdes pll errors during
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index ad41cccd2e9f..eac2e9c55281 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -795,6 +795,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
795{ 795{
796 int i, im; 796 int i, im;
797 __le64 val; 797 __le64 val;
798 unsigned long flags;
798 799
799 /* disable error interrupts, to avoid confusion */ 800 /* disable error interrupts, to avoid confusion */
800 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL); 801 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
@@ -813,11 +814,14 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
813 dd->ipath_control); 814 dd->ipath_control);
814 815
815 /* ensure pio avail updates continue */ 816 /* ensure pio avail updates continue */
817 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
816 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 818 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
817 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD); 819 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
818 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); 820 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
819 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 821 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
820 dd->ipath_sendctrl); 822 dd->ipath_sendctrl);
823 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
824 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
821 825
822 /* 826 /*
823 * We just enabled pioavailupdate, so dma copy is almost certainly 827 * We just enabled pioavailupdate, so dma copy is almost certainly
@@ -922,6 +926,7 @@ static noinline void ipath_bad_regread(struct ipath_devdata *dd)
922 926
923static void handle_layer_pioavail(struct ipath_devdata *dd) 927static void handle_layer_pioavail(struct ipath_devdata *dd)
924{ 928{
929 unsigned long flags;
925 int ret; 930 int ret;
926 931
927 ret = ipath_ib_piobufavail(dd->verbs_dev); 932 ret = ipath_ib_piobufavail(dd->verbs_dev);
@@ -930,9 +935,12 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
930 935
931 return; 936 return;
932set: 937set:
933 set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); 938 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
939 dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
934 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 940 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
935 dd->ipath_sendctrl); 941 dd->ipath_sendctrl);
942 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
943 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
936} 944}
937 945
938/* 946/*
@@ -1168,9 +1176,14 @@ irqreturn_t ipath_intr(int irq, void *data)
1168 handle_urcv(dd, istat); 1176 handle_urcv(dd, istat);
1169 1177
1170 if (istat & INFINIPATH_I_SPIOBUFAVAIL) { 1178 if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
1171 clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); 1179 unsigned long flags;
1180
1181 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
1182 dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL;
1172 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 1183 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
1173 dd->ipath_sendctrl); 1184 dd->ipath_sendctrl);
1185 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
1186 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
1174 1187
1175 handle_layer_pioavail(dd); 1188 handle_layer_pioavail(dd);
1176 } 1189 }
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 65f7c7f7b5d9..81759c2031f9 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -376,6 +376,7 @@ struct ipath_devdata {
376 dma_addr_t *ipath_physshadow; 376 dma_addr_t *ipath_physshadow;
377 /* lock to workaround chip bug 9437 */ 377 /* lock to workaround chip bug 9437 */
378 spinlock_t ipath_tid_lock; 378 spinlock_t ipath_tid_lock;
379 spinlock_t ipath_sendctrl_lock;
379 380
380 /* 381 /*
381 * IPATH_STATUS_*, 382 * IPATH_STATUS_*,
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index 54c61a972de2..1b4f7e113b21 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -479,9 +479,14 @@ done:
479 479
480static void want_buffer(struct ipath_devdata *dd) 480static void want_buffer(struct ipath_devdata *dd)
481{ 481{
482 set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); 482 unsigned long flags;
483
484 spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
485 dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
483 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 486 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
484 dd->ipath_sendctrl); 487 dd->ipath_sendctrl);
488 ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
489 spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
485} 490}
486 491
487/** 492/**