diff options
author | Joachim Fenkes <fenkes@de.ibm.com> | 2007-12-10 12:59:10 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-12-12 17:09:43 -0500 |
commit | 4faf7757955239c1b259e7dab224d4638a99b456 (patch) | |
tree | d6e56aef1706cf26c0daa67bad150cb88ad7f52f /drivers/infiniband/hw/ehca/hcp_if.c | |
parent | 1457edc72d187f452be1374c7d9281f1dfa16f32 (diff) |
IB/ehca: Serialize HCA-related hCalls if necessary
Several pSeries firmware versions share a rare locking issue in the
HCA-related hCalls. Check for a feature flag that indicates the issue
being fixed and serialize all HCA hCalls if not.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca/hcp_if.c')
-rw-r--r-- | drivers/infiniband/hw/ehca/hcp_if.c | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c index c16a21374bb5..331b5e82ef77 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.c +++ b/drivers/infiniband/hw/ehca/hcp_if.c | |||
@@ -89,6 +89,7 @@ | |||
89 | #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx" | 89 | #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx" |
90 | 90 | ||
91 | static DEFINE_SPINLOCK(hcall_lock); | 91 | static DEFINE_SPINLOCK(hcall_lock); |
92 | extern int ehca_lock_hcalls; | ||
92 | 93 | ||
93 | static u32 get_longbusy_msecs(int longbusy_rc) | 94 | static u32 get_longbusy_msecs(int longbusy_rc) |
94 | { | 95 | { |
@@ -120,26 +121,21 @@ static long ehca_plpar_hcall_norets(unsigned long opcode, | |||
120 | unsigned long arg7) | 121 | unsigned long arg7) |
121 | { | 122 | { |
122 | long ret; | 123 | long ret; |
123 | int i, sleep_msecs, do_lock; | 124 | int i, sleep_msecs; |
124 | unsigned long flags; | 125 | unsigned long flags = 0; |
125 | 126 | ||
126 | ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT, | 127 | ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT, |
127 | opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); | 128 | opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
128 | 129 | ||
129 | /* lock H_FREE_RESOURCE(MR) against itself and H_ALLOC_RESOURCE(MR) */ | ||
130 | if ((opcode == H_FREE_RESOURCE) && (arg7 == 5)) { | ||
131 | arg7 = 0; /* better not upset firmware */ | ||
132 | do_lock = 1; | ||
133 | } | ||
134 | |||
135 | for (i = 0; i < 5; i++) { | 130 | for (i = 0; i < 5; i++) { |
136 | if (do_lock) | 131 | /* serialize hCalls to work around firmware issue */ |
132 | if (ehca_lock_hcalls) | ||
137 | spin_lock_irqsave(&hcall_lock, flags); | 133 | spin_lock_irqsave(&hcall_lock, flags); |
138 | 134 | ||
139 | ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, | 135 | ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, |
140 | arg5, arg6, arg7); | 136 | arg5, arg6, arg7); |
141 | 137 | ||
142 | if (do_lock) | 138 | if (ehca_lock_hcalls) |
143 | spin_unlock_irqrestore(&hcall_lock, flags); | 139 | spin_unlock_irqrestore(&hcall_lock, flags); |
144 | 140 | ||
145 | if (H_IS_LONG_BUSY(ret)) { | 141 | if (H_IS_LONG_BUSY(ret)) { |
@@ -174,24 +170,22 @@ static long ehca_plpar_hcall9(unsigned long opcode, | |||
174 | unsigned long arg9) | 170 | unsigned long arg9) |
175 | { | 171 | { |
176 | long ret; | 172 | long ret; |
177 | int i, sleep_msecs, do_lock; | 173 | int i, sleep_msecs; |
178 | unsigned long flags = 0; | 174 | unsigned long flags = 0; |
179 | 175 | ||
180 | ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode, | 176 | ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode, |
181 | arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); | 177 | arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); |
182 | 178 | ||
183 | /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */ | ||
184 | do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)); | ||
185 | |||
186 | for (i = 0; i < 5; i++) { | 179 | for (i = 0; i < 5; i++) { |
187 | if (do_lock) | 180 | /* serialize hCalls to work around firmware issue */ |
181 | if (ehca_lock_hcalls) | ||
188 | spin_lock_irqsave(&hcall_lock, flags); | 182 | spin_lock_irqsave(&hcall_lock, flags); |
189 | 183 | ||
190 | ret = plpar_hcall9(opcode, outs, | 184 | ret = plpar_hcall9(opcode, outs, |
191 | arg1, arg2, arg3, arg4, arg5, | 185 | arg1, arg2, arg3, arg4, arg5, |
192 | arg6, arg7, arg8, arg9); | 186 | arg6, arg7, arg8, arg9); |
193 | 187 | ||
194 | if (do_lock) | 188 | if (ehca_lock_hcalls) |
195 | spin_unlock_irqrestore(&hcall_lock, flags); | 189 | spin_unlock_irqrestore(&hcall_lock, flags); |
196 | 190 | ||
197 | if (H_IS_LONG_BUSY(ret)) { | 191 | if (H_IS_LONG_BUSY(ret)) { |
@@ -821,7 +815,7 @@ u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, | |||
821 | return ehca_plpar_hcall_norets(H_FREE_RESOURCE, | 815 | return ehca_plpar_hcall_norets(H_FREE_RESOURCE, |
822 | adapter_handle.handle, /* r4 */ | 816 | adapter_handle.handle, /* r4 */ |
823 | mr->ipz_mr_handle.handle, /* r5 */ | 817 | mr->ipz_mr_handle.handle, /* r5 */ |
824 | 0, 0, 0, 0, 5); | 818 | 0, 0, 0, 0, 0); |
825 | } | 819 | } |
826 | 820 | ||
827 | u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, | 821 | u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, |