|
@@ -715,6 +715,10 @@ void cp_free(struct channel_program *cp)
|
|
* and stores the result to ccwchain list. @cp must have been
|
|
* and stores the result to ccwchain list. @cp must have been
|
|
* initialized by a previous call with cp_init(). Otherwise, undefined
|
|
* initialized by a previous call with cp_init(). Otherwise, undefined
|
|
* behavior occurs.
|
|
* behavior occurs.
|
|
|
|
+ * For each chain composing the channel program:
|
|
|
|
+ * - On entry ch_len holds the count of CCWs to be translated.
|
|
|
|
+ * - On exit ch_len is adjusted to the count of successfully translated CCWs.
|
|
|
|
+ * This allows cp_free to find in ch_len the count of CCWs to free in a chain.
|
|
*
|
|
*
|
|
* The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced
|
|
* The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced
|
|
* as helpers to do ccw chain translation inside the kernel. Basically
|
|
* as helpers to do ccw chain translation inside the kernel. Basically
|
|
@@ -749,11 +753,18 @@ int cp_prefetch(struct channel_program *cp)
|
|
for (idx = 0; idx < len; idx++) {
|
|
for (idx = 0; idx < len; idx++) {
|
|
ret = ccwchain_fetch_one(chain, idx, cp);
|
|
ret = ccwchain_fetch_one(chain, idx, cp);
|
|
if (ret)
|
|
if (ret)
|
|
- return ret;
|
|
|
|
|
|
+ goto out_err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
+out_err:
|
|
|
|
+ /* Only cleanup the chain elements that were actually translated. */
|
|
|
|
+ chain->ch_len = idx;
|
|
|
|
+ list_for_each_entry_continue(chain, &cp->ccwchain_list, next) {
|
|
|
|
+ chain->ch_len = 0;
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|