aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ehca
diff options
context:
space:
mode:
authorJoachim Fenkes <fenkes@de.ibm.com>2007-09-11 09:34:35 -0400
committerRoland Dreier <rolandd@cisco.com>2007-10-09 22:59:11 -0400
commit0b5de96858e516311f2d3ca45073c2afd2eb5d94 (patch)
tree83fbe9083a68e5a1456a44111dd823b49c71e69a /drivers/infiniband/hw/ehca
parente90d0b3daede2bae2e78f8bf88c19182961cd19d (diff)
IB/ehca: Serialize MR alloc and MR free hvCalls
Some firmware levels exhibit a race condition between H_ALLOC_RESOURCE(MR) and H_FREE_RESOURCE(MR). Work around this problem by locking these hvCalls against each other. Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca')
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 3d68f6536f9c..c16a21374bb5 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -120,15 +120,28 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
120 unsigned long arg7) 120 unsigned long arg7)
121{ 121{
122 long ret; 122 long ret;
123 int i, sleep_msecs; 123 int i, sleep_msecs, do_lock;
124 unsigned long flags;
124 125
125 ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT, 126 ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
126 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 127 opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
127 128
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
128 for (i = 0; i < 5; i++) { 135 for (i = 0; i < 5; i++) {
136 if (do_lock)
137 spin_lock_irqsave(&hcall_lock, flags);
138
129 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, 139 ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
130 arg5, arg6, arg7); 140 arg5, arg6, arg7);
131 141
142 if (do_lock)
143 spin_unlock_irqrestore(&hcall_lock, flags);
144
132 if (H_IS_LONG_BUSY(ret)) { 145 if (H_IS_LONG_BUSY(ret)) {
133 sleep_msecs = get_longbusy_msecs(ret); 146 sleep_msecs = get_longbusy_msecs(ret);
134 msleep_interruptible(sleep_msecs); 147 msleep_interruptible(sleep_msecs);
@@ -161,23 +174,24 @@ static long ehca_plpar_hcall9(unsigned long opcode,
161 unsigned long arg9) 174 unsigned long arg9)
162{ 175{
163 long ret; 176 long ret;
164 int i, sleep_msecs, lock_is_set = 0; 177 int i, sleep_msecs, do_lock;
165 unsigned long flags = 0; 178 unsigned long flags = 0;
166 179
167 ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode, 180 ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
168 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); 181 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
169 182
183 /* lock H_ALLOC_RESOURCE(MR) against itself and H_FREE_RESOURCE(MR) */
184 do_lock = ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5));
185
170 for (i = 0; i < 5; i++) { 186 for (i = 0; i < 5; i++) {
171 if ((opcode == H_ALLOC_RESOURCE) && (arg2 == 5)) { 187 if (do_lock)
172 spin_lock_irqsave(&hcall_lock, flags); 188 spin_lock_irqsave(&hcall_lock, flags);
173 lock_is_set = 1;
174 }
175 189
176 ret = plpar_hcall9(opcode, outs, 190 ret = plpar_hcall9(opcode, outs,
177 arg1, arg2, arg3, arg4, arg5, 191 arg1, arg2, arg3, arg4, arg5,
178 arg6, arg7, arg8, arg9); 192 arg6, arg7, arg8, arg9);
179 193
180 if (lock_is_set) 194 if (do_lock)
181 spin_unlock_irqrestore(&hcall_lock, flags); 195 spin_unlock_irqrestore(&hcall_lock, flags);
182 196
183 if (H_IS_LONG_BUSY(ret)) { 197 if (H_IS_LONG_BUSY(ret)) {
@@ -807,7 +821,7 @@ u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
807 return ehca_plpar_hcall_norets(H_FREE_RESOURCE, 821 return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
808 adapter_handle.handle, /* r4 */ 822 adapter_handle.handle, /* r4 */
809 mr->ipz_mr_handle.handle, /* r5 */ 823 mr->ipz_mr_handle.handle, /* r5 */
810 0, 0, 0, 0, 0); 824 0, 0, 0, 0, 5);
811} 825}
812 826
813u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, 827u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,