@@ -1192,6 +1192,133 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr,
return 0;
}
+/*
+ * The following 4 functions are proposed for lib/scatterlist.c (without the
+ * "sdeb_" prefix) and will be removed from this driver if the proposal is accepted.
+ */
+static size_t sdeb_sgl_copy_sgl(struct scatterlist *d_sgl, unsigned int d_nents, off_t d_skip,
+ struct scatterlist *s_sgl, unsigned int s_nents, off_t s_skip,
+ size_t n_bytes)
+{
+ size_t len;
+ size_t offset = 0;
+ struct sg_mapping_iter d_iter, s_iter;
+
+ if (n_bytes == 0)
+ return 0;
+ sg_miter_start(&s_iter, s_sgl, s_nents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+ sg_miter_start(&d_iter, d_sgl, d_nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
+ if (!sg_miter_skip(&s_iter, s_skip))
+ goto fini;
+ if (!sg_miter_skip(&d_iter, d_skip))
+ goto fini;
+
+ while (offset < n_bytes) {
+ if (!sg_miter_next(&s_iter))
+ break;
+ if (!sg_miter_next(&d_iter))
+ break;
+ len = min3(d_iter.length, s_iter.length, n_bytes - offset);
+
+ memcpy(d_iter.addr, s_iter.addr, len);
+ offset += len;
+ /* LIFO order (stop d_iter before s_iter) needed with SG_MITER_ATOMIC */
+ d_iter.consumed = len;
+ sg_miter_stop(&d_iter);
+ s_iter.consumed = len;
+ sg_miter_stop(&s_iter);
+ }
+fini:
+ sg_miter_stop(&d_iter);
+ sg_miter_stop(&s_iter);
+ return offset;
+}
+
+static bool sdeb_sgl_compare_sgl_idx(struct scatterlist *x_sgl, unsigned int x_nents, off_t x_skip,
+ struct scatterlist *y_sgl, unsigned int y_nents, off_t y_skip,
+ size_t n_bytes, size_t *miscompare_idx)
+{
+ bool equ = true;
+ size_t len;
+ size_t offset = 0;
+ struct sg_mapping_iter x_iter, y_iter;
+
+ if (n_bytes == 0)
+ return true;
+ sg_miter_start(&x_iter, x_sgl, x_nents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+ sg_miter_start(&y_iter, y_sgl, y_nents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+ if (!sg_miter_skip(&x_iter, x_skip))
+ goto fini;
+ if (!sg_miter_skip(&y_iter, y_skip))
+ goto fini;
+
+ while (offset < n_bytes) {
+ if (!sg_miter_next(&x_iter))
+ break;
+ if (!sg_miter_next(&y_iter))
+ break;
+ len = min3(x_iter.length, y_iter.length, n_bytes - offset);
+
+ equ = !memcmp(x_iter.addr, y_iter.addr, len);
+ if (!equ)
+ goto fini;
+ offset += len;
+ /* LIFO order is important when SG_MITER_ATOMIC is used */
+ y_iter.consumed = len;
+ sg_miter_stop(&y_iter);
+ x_iter.consumed = len;
+ sg_miter_stop(&x_iter);
+ }
+fini:
+ if (miscompare_idx && !equ) {
+ u8 *xp = x_iter.addr;
+ u8 *yp = y_iter.addr;
+ u8 *x_endp;
+
+ for (x_endp = xp + len ; xp < x_endp; ++xp, ++yp) {
+ if (*xp != *yp)
+ break;
+ }
+ *miscompare_idx = offset + len - (x_endp - xp);
+ }
+ sg_miter_stop(&y_iter);
+ sg_miter_stop(&x_iter);
+ return equ;
+}
+
+static bool sdeb_sgl_compare_sgl(struct scatterlist *x_sgl, unsigned int x_nents, off_t x_skip,
+ struct scatterlist *y_sgl, unsigned int y_nents, off_t y_skip,
+ size_t n_bytes)
+{
+ return sdeb_sgl_compare_sgl_idx(x_sgl, x_nents, x_skip, y_sgl, y_nents, y_skip, n_bytes,
+ NULL);
+}
+
+static size_t sdeb_sgl_memset(struct scatterlist *sgl, unsigned int nents, off_t skip,
+ u8 val, size_t n_bytes)
+{
+ size_t offset = 0;
+ size_t len;
+ struct sg_mapping_iter miter;
+
+ if (n_bytes == 0)
+ return 0;
+ sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
+ if (!sg_miter_skip(&miter, skip))
+ goto fini;
+
+ while ((offset < n_bytes) && sg_miter_next(&miter)) {
+ len = min(miter.length, n_bytes - offset);
+ memset(miter.addr, val, len);
+ offset += len;
+ }
+fini:
+ sg_miter_stop(&miter);
+ return offset;
+}
+
+/* end of functions proposed for lib/scatterlist.c */
+
/* Fetches from SCSI "data-out" buffer. Returns number of bytes fetched into
* 'arr' or -1 if error.
*/