]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - block/ll_rw_blk.c
[BLOCK] blk_rq_map_sg: force clear termination bit
[linux-2.6-omap-h63xx.git] / block / ll_rw_blk.c
index 8025d646ab3085ff5627fc0f082465eba8329ce7..de5ba479c2245b9e747558757fb6444eebc6745e 100644 (file)
@@ -1351,11 +1351,22 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
 new_segment:
                        if (!sg)
                                sg = sglist;
-                       else
+                       else {
+                               /*
+                                * If the driver previously mapped a shorter
+                                * list, we could see a termination bit
+                                * prematurely unless it fully inits the sg
+                                * table on each mapping. We KNOW that there
+                                * must be more entries here or the driver
+                                * would be buggy, so force clear the
+                                * termination bit to avoid doing a full
+                                * sg_init_table() in drivers for each command.
+                                */
+                               sg->page_link &= ~0x02;
                                sg = sg_next(sg);
+                       }
 
-                       memset(sg, 0, sizeof(*sg));
-                       sg->page = bvec->bv_page;
+                       sg_set_page(sg, bvec->bv_page);
                        sg->length = nbytes;
                        sg->offset = bvec->bv_offset;
                        nsegs++;
@@ -1363,6 +1374,9 @@ new_segment:
                bvprv = bvec;
        } /* segments in rq */
 
+       if (sg)
+               __sg_mark_end(sg);
+
        return nsegs;
 }