sg = sg_next(sg);
                        }
 
-                       sg_set_page(sg, bvec->bv_page);
-                       sg->length = nbytes;
-                       sg->offset = bvec->bv_offset;
+                       sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset);
                        nsegs++;
                }
                bvprv = bvec;
 
 
        sg_set_buf(sg1, ipad, bs);
 
-       sg_set_page(&sg[1], (void *) sg);
-       sg1[1].length = 0;
+       sg_set_page(&sg[1], (void *) sg, 0, 0);
        sg_set_buf(sg2, opad, bs + ds);
 
        err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest);
 
                 * data in this function or read data in ata_sg_clean.
                 */
                offset = lsg->offset + lsg->length - qc->pad_len;
-               sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT));
-               psg->offset = offset_in_page(offset);
+               sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
+                               qc->pad_len, offset_in_page(offset));
 
                if (qc->tf.flags & ATA_TFLAG_WRITE) {
                        void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
 
                u32 iv[4] = { 0, };
                iv[0] = cpu_to_le32(IV & 0xffffffff);
 
-               sg_set_page(&sg_in, in_page);
-               sg_in.offset = in_offs;
-               sg_in.length = sz;
-
-               sg_set_page(&sg_out, out_page);
-               sg_out.offset = out_offs;
-               sg_out.length = sz;
+               sg_set_page(&sg_in, in_page, sz, in_offs);
+               sg_set_page(&sg_out, out_page, sz, out_offs);
 
                desc.info = iv;
                err = encdecfunc(&desc, &sg_out, &sg_in, sz);
 
        scmd->state = UB_CMDST_INIT;
        scmd->nsg = 1;
        sg = &scmd->sgv[0];
-       sg_set_page(sg, virt_to_page(sc->top_sense));
-       sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
-       sg->length = UB_SENSE_SIZE;
+       sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE,
+                       (unsigned long)sc->top_sense & (PAGE_SIZE-1));
        scmd->len = UB_SENSE_SIZE;
        scmd->lun = cmd->lun;
        scmd->done = ub_top_sense_done;
        cmd->state = UB_CMDST_INIT;
        cmd->nsg = 1;
        sg = &cmd->sgv[0];
-       sg_set_page(sg, virt_to_page(p));
-       sg->offset = (unsigned long)p & (PAGE_SIZE-1);
-       sg->length = 8;
+       sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1));
        cmd->len = 8;
        cmd->lun = lun;
        cmd->done = ub_probe_done;
 
                unsigned long va =
                    (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
 
-               sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va));
-               dma->sglist[i].length = PAGE_SIZE;
+               sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va),
+                               PAGE_SIZE, 0);
        }
 
        /* map sglist to the IOMMU */
 
                                if (vma_list &&
                                    !is_vm_hugetlb_page(vma_list[i + off]))
                                        umem->hugetlb = 0;
-                               sg_set_page(&chunk->page_list[i], page_list[i + off]);
-                               chunk->page_list[i].offset = 0;
-                               chunk->page_list[i].length = PAGE_SIZE;
+                               sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
                        }
 
                        chunk->nmap = ib_dma_map_sg(context->device,
 
        if (!page)
                return -ENOMEM;
 
-       sg_set_page(mem, page);
-       mem->length = PAGE_SIZE << order;
-       mem->offset = 0;
+       sg_set_page(mem, page, PAGE_SIZE << order, 0);
        return 0;
 }
 
        if (ret < 0)
                goto out;
 
-       sg_set_page(&db_tab->page[i].mem, pages[0]);
-       db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE;
-       db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK;
+       sg_set_page(&db_tab->page[i].mem, pages[0], MTHCA_ICM_PAGE_SIZE,
+                       uaddr & ~PAGE_MASK);
 
        ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
        if (ret < 0) {
 
                struct scatterlist sg_in, sg_out;
 
                sg_init_table(&sg_in, 1);
-               sg_set_page(&sg_in, bv_in->bv_page);
-               sg_in.offset = bv_in->bv_offset + ctx->offset_in;
-               sg_in.length = 1 << SECTOR_SHIFT;
+               sg_set_page(&sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in);
 
                sg_init_table(&sg_out, 1);
-               sg_set_page(&sg_out, bv_out->bv_page);
-               sg_out.offset = bv_out->bv_offset + ctx->offset_out;
-               sg_out.length = 1 << SECTOR_SHIFT;
+               sg_set_page(&sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT, bv_out->bv_offset + ctx->offset_out);
 
                ctx->offset_in += sg_in.length;
                if (ctx->offset_in >= bv_in->bv_len) {
 
                if (NULL == pg)
                        goto err;
                BUG_ON(PageHighMem(pg));
-               sg_set_page(&sglist[i], pg);
-               sglist[i].length = PAGE_SIZE;
+               sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
        }
        return sglist;
 
 
                unsigned int len = (i == dma_page->page_count - 1) ?
                        dma_page->tail : PAGE_SIZE - offset;
 
-               dma->SGlist[map_offset].length = len;
-               dma->SGlist[map_offset].offset = offset;
                if (PageHighMem(dma->map[map_offset])) {
                        void *src;
 
                        memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
                        kunmap_atomic(src, KM_BOUNCE_READ);
                        local_irq_restore(flags);
-                       sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset]);
+                       sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
                }
                else {
-                       sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset]);
+                       sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset);
                }
                offset = 0;
                map_offset++;
 
                if (NULL == pg)
                        goto err;
                BUG_ON(PageHighMem(pg));
-               sg_set_page(&sglist[i], pg);
-               sglist[i].length = PAGE_SIZE;
+               sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
        }
        return sglist;
 
        if (PageHighMem(pages[0]))
                /* DMA to highmem pages might not work */
                goto highmem;
-       sg_set_page(&sglist[0], pages[0]);
-       sglist[0].offset = offset;
-       sglist[0].length = PAGE_SIZE - offset;
+       sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
        for (i = 1; i < nr_pages; i++) {
                if (NULL == pages[i])
                        goto nopage;
                if (PageHighMem(pages[i]))
                        goto highmem;
-               sg_set_page(&sglist[i], pages[i]);
-               sglist[i].length = PAGE_SIZE;
+               sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0);
        }
        return sglist;
 
 
        if (!page)
                return -ENOMEM;
 
-       sg_set_page(mem, page);
-       mem->length = PAGE_SIZE << order;
-       mem->offset = 0;
+       sg_set_page(mem, page, PAGE_SIZE << order, 0);
        return 0;
 }
 
 
        sg_init_table(sg_list->sg, sg_list->count);
 
        for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
-               sg->length = min(size, PAGE_SIZE);
-               sg->offset = 0;
                address = (void *) get_zeroed_page(GFP_KERNEL);
                if (address == NULL) {
                        sg_list->count = i;
                        retval = -ENOMEM;
                        goto out;
                }
-               zfcp_address_to_sg(address, sg);
+               zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE));
                size -= sg->length;
        }
 
         data->ct.req = &data->req;
         data->ct.resp = &data->resp;
        data->ct.req_count = data->ct.resp_count = 1;
-       zfcp_address_to_sg(&data->ct_iu_req, &data->req);
-        zfcp_address_to_sg(&data->ct_iu_resp, &data->resp);
-        data->req.length = sizeof(struct ct_iu_gid_pn_req);
-        data->resp.length = sizeof(struct ct_iu_gid_pn_resp);
+       zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req));
+        zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp));
 
        *gid_pn = data;
        return 0;
 
 static inline void
 zfcp_address_to_sg(void *address, struct scatterlist *list)
 {
-       sg_set_page(list, virt_to_page(address));
-       list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
+       sg_set_buf(list, address, 0);
 }
 
 #define REQUEST_LIST_SIZE 128
 
        if (address == NULL)
                goto nomem;
 
-       zfcp_address_to_sg(address, send_els->req);
+       zfcp_address_to_sg(address, send_els->req, sizeof(struct zfcp_ls_adisc));
        address += PAGE_SIZE >> 1;
-       zfcp_address_to_sg(address, send_els->resp);
+       zfcp_address_to_sg(address, send_els->resp, sizeof(struct zfcp_ls_adisc_acc));
        send_els->req_count = send_els->resp_count = 1;
 
        send_els->adapter = adapter;
        adisc = zfcp_sg_to_address(send_els->req);
        send_els->ls_code = adisc->code = ZFCP_LS_ADISC;
 
-       send_els->req->length = sizeof(struct zfcp_ls_adisc);
-       send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc);
-
        /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
           without FC-AL-2 capability, so we don't set it */
        adisc->wwpn = fc_host_port_name(adapter->scsi_host);
 
                        return NULL;
                }
 
-               sg_set_page(&scatterlist[i], page);
+               sg_set_page(&scatterlist[i], page, 0, 0);
        }
 
        return sglist;
 
 iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
 {
        sg_init_table(&ibuf->sg, 1);
-       sg_set_page(&ibuf->sg, sg_page(sg));
-       ibuf->sg.offset = sg->offset;
-       ibuf->sg.length = sg->length;
+       sg_set_page(&ibuf->sg, sg_page(sg), sg->length, sg->offset);
        /*
         * Fastpath: sg element fits into single page
         */
 
 
                STbuffer->sg[0].offset = 0;
                if (page != NULL) {
-                   sg_set_page(&STbuffer->sg[0], page);
-                   STbuffer->sg[0].length = b_size;
+                   sg_set_page(&STbuffer->sg[0], page, b_size, 0);
                    STbuffer->b_data = page_address(page);
                    break;
                }
                        normalize_buffer(STbuffer);
                        return 0;
                }
-               sg_set_page(&STbuffer->sg[segs], page);
-               STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
+               sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
                got += STbuffer->sg[segs].length;
                STbuffer->buffer_size = got;
                STbuffer->sg_segs = ++segs;
 
                   goto out_unlock; */
         }
 
-       sg_set_page(sgl, pages[0]);
-       sgl[0].offset = uaddr & ~PAGE_MASK;
+       sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK);
        if (nr_pages > 1) {
                sgl[0].length = PAGE_SIZE - sgl[0].offset;
                count -= sgl[0].length;
-               for (i=1; i < nr_pages ; i++) {
-                       sg_set_page(&sgl[i], pages[i]);
-                       sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
-                       count -= PAGE_SIZE;
-               }
+               for (i=1; i < nr_pages ; i++)
+                       sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0);
        }
        else {
                sgl[0].length = count;
                                scatter_elem_sz_prev = ret_sz;
                        }
                }
-               sg_set_page(sg, p);
-               sg->length = (ret_sz > num) ? num : ret_sz;
+               sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0);
 
                SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, "
                                 "ret_sz=%d\n", k, num, ret_sz));
 
        sg = &(STbp->sg[0]);
        frp = STbp->frp;
        for (i=count=0; count < length; i++) {
-               sg_set_page(&sg[i], frp[i].page);
                if (length - count > frp[i].length)
-                       sg[i].length = frp[i].length;
+                       sg_set_page(&sg[i], frp[i].page, frp[i].length, 0);
                else
-                       sg[i].length = length - count;
+                       sg_set_page(&sg[i], frp[i].page, length - count, 0);
                count += sg[i].length;
-               sg[i].offset = 0;
        }
        STbp->sg_segs = i;
        STbp->frp_sg_current = length;
         }
 
        /* Populate the scatter/gather list */
-       sg_set_page(&sgl[0], pages[0]);
-       sgl[0].offset = uaddr & ~PAGE_MASK;
+       sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK);
        if (nr_pages > 1) {
                sgl[0].length = PAGE_SIZE - sgl[0].offset;
                count -= sgl[0].length;
                for (i=1; i < nr_pages ; i++) {
-                       sg_set_page(&sgl[i], pages[i]);;
-                       sgl[i].offset = 0;
-                       sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
+                       sg_set_page(&sgl[i], pages[i],
+                                   count < PAGE_SIZE ? count : PAGE_SIZE, 0);;
                        count -= PAGE_SIZE;
                }
        }
 
        while (size > 0 && i < sg_size) {
                pg = virt_to_page(addr);
                offset = offset_in_page(addr);
-               if (sg) {
-                       sg_set_page(&sg[i], pg);
-                       sg[i].offset = offset;
-               }
+               if (sg)
+                       sg_set_page(&sg[i], pg, 0, offset);
                remainder_of_page = PAGE_CACHE_SIZE - offset;
                if (size >= remainder_of_page) {
                        if (sg)
        sg_init_table(&src_sg, 1);
        sg_init_table(&dst_sg, 1);
 
-       sg_set_page(&src_sg, src_page);
-       src_sg.offset = src_offset;
-       src_sg.length = size;
-       sg_set_page(&dst_sg, dst_page);
-       dst_sg.offset = dst_offset;
-       dst_sg.length = size;
+       sg_set_page(&src_sg, src_page, size, src_offset);
+       sg_set_page(&dst_sg, dst_page, size, dst_offset);
        return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
 }
 
        struct scatterlist src_sg, dst_sg;
 
        sg_init_table(&src_sg, 1);
+       sg_set_page(&src_sg, src_page, size, src_offset);
+
        sg_init_table(&dst_sg, 1);
+       sg_set_page(&dst_sg, dst_page, size, dst_offset);
 
-       sg_set_page(&src_sg, src_page);
-       src_sg.offset = src_offset;
-       src_sg.length = size;
-       sg_set_page(&dst_sg, dst_page);
-       dst_sg.offset = dst_offset;
-       dst_sg.length = size;
        return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
 }
 
 
  *
  * can be rewritten as
  *
- * sg_set_page(virt_to_page(some_ptr));
- * sg->offset = (unsigned long) some_ptr & ~PAGE_MASK;
+ * sg_set_buf(sg, some_ptr, length);
  *
  * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens
  */
 
 #define SG_MAGIC       0x87654321
 
 /**
- * sg_set_page - Set sg entry to point at given page
- * @sg:                 SG entry
- * @page:       The page
+ * sg_assign_page - Assign a given page to an SG entry
+ * @sg:                    SG entry
+ * @page:          The page
  *
  * Description:
- *   Use this function to set an sg entry pointing at a page, never assign
- *   the page directly. We encode sg table information in the lower bits
- *   of the page pointer. See sg_page() for looking up the page belonging
- *   to an sg entry.
+ *   Assign page to sg entry. Also see sg_set_page(), the most commonly used
+ *   variant.
  *
  **/
-static inline void sg_set_page(struct scatterlist *sg, struct page *page)
+static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
 {
        unsigned long page_link = sg->page_link & 0x3;
 
        sg->page_link = page_link | (unsigned long) page;
 }
 
+/**
+ * sg_set_page - Set sg entry to point at given page
+ * @sg:                 SG entry
+ * @page:       The page
+ * @len:        Length of data
+ * @offset:     Offset into page
+ *
+ * Description:
+ *   Use this function to set an sg entry pointing at a page, never assign
+ *   the page directly. We encode sg table information in the lower bits
+ *   of the page pointer. See sg_page() for looking up the page belonging
+ *   to an sg entry.
+ *
+ **/
+static inline void sg_set_page(struct scatterlist *sg, struct page *page,
+                              unsigned int len, unsigned int offset)
+{
+       sg_assign_page(sg, page);
+       sg->offset = offset;
+       sg->length = len;
+}
+
 #define sg_page(sg)    ((struct page *) ((sg)->page_link & ~0x3))
 
 /**
 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
                              unsigned int buflen)
 {
-       sg_set_page(sg, virt_to_page(buf));
-       sg->offset = offset_in_page(buf);
-       sg->length = buflen;
+       sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
 }
 
 /*
 
        if (copy > 0) {
                if (copy > len)
                        copy = len;
-               sg_set_page(&sg[elt], virt_to_page(skb->data + offset));
-               sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-               sg[elt].length = copy;
+               sg_set_buf(sg, skb->data + offset, copy);
                elt++;
                if ((len -= copy) == 0)
                        return elt;
 
                        if (copy > len)
                                copy = len;
-                       sg_set_page(&sg[elt], frag->page);
-                       sg[elt].offset = frag->page_offset+offset-start;
-                       sg[elt].length = copy;
+                       sg_set_page(&sg[elt], frag->page, copy,
+                                       frag->page_offset+offset-start);
                        elt++;
                        if (!(len -= copy))
                                return elt;
 
                return -1;
        }
        sg_init_table(sg, 2);
-       sg_set_page(&sg[0], virt_to_page(hdr));
-       sg[0].offset = offset_in_page(hdr);
-       sg[0].length = 16;
-
-       sg_set_page(&sg[1], virt_to_page(data));
-       sg[1].offset = offset_in_page(data);
-       sg[1].length = data_len;
+       sg_set_buf(&sg[0], hdr, 16);
+       sg_set_buf(&sg[1], data, data_len);
 
        if (crypto_hash_setkey(tfm_michael, key, 8))
                return -1;
 
        /* set up scatter list */
        end = skb_tail_pointer(skb);
        sg_init_table(&sg, 1);
-       sg_set_page(&sg, virt_to_page(auth));
-       sg.offset = (unsigned long)(auth) % PAGE_SIZE;
-       sg.length = end - (unsigned char *)auth;
+       sg_set_buf(&sg, auth, end - (unsigned char *)auth);
 
        desc.tfm = asoc->ep->auth_hmacs[hmac_id];
        desc.flags = 0;
 
 
                /* Sign the message.  */
                sg_init_table(&sg, 1);
-               sg_set_page(&sg, virt_to_page(&cookie->c));
-               sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE;
-               sg.length = bodysize;
+               sg_set_buf(&sg, &cookie->c, bodysize);
                keylen = SCTP_SECRET_SIZE;
                key = (char *)ep->secret_key[ep->current_key];
                desc.tfm = sctp_sk(ep->base.sk)->hmac;
        /* Check the signature.  */
        keylen = SCTP_SECRET_SIZE;
        sg_init_table(&sg, 1);
-       sg_set_page(&sg, virt_to_page(bear_cookie));
-       sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;
-       sg.length = bodysize;
+       sg_set_buf(&sg, bear_cookie, bodysize);
        key = (char *)ep->secret_key[ep->current_key];
        desc.tfm = sctp_sk(ep->base.sk)->hmac;
        desc.flags = 0;
 
        } else {
                in_page = sg_page(sg);
        }
-       sg_set_page(&desc->infrags[desc->fragno], in_page);
+       sg_assign_page(&desc->infrags[desc->fragno], in_page);
        desc->fragno++;
        desc->fraglen += sg->length;
        desc->pos += sg->length;
        if (ret)
                return ret;
        if (fraglen) {
-               sg_set_page(&desc->outfrags[0], sg_page(sg));
-               desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
-               desc->outfrags[0].length = fraglen;
+               sg_set_page(&desc->outfrags[0], sg_page(sg), fraglen,
+                               sg->offset + sg->length - fraglen);
                desc->infrags[0] = desc->outfrags[0];
-               sg_set_page(&desc->infrags[0], in_page);
+               sg_assign_page(&desc->infrags[0], in_page);
                desc->fragno = 1;
                desc->fraglen = fraglen;
        } else {
        if (ret)
                return ret;
        if (fraglen) {
-               sg_set_page(&desc->frags[0], sg_page(sg));
-               desc->frags[0].offset = sg->offset + sg->length - fraglen;
-               desc->frags[0].length = fraglen;
+               sg_set_page(&desc->frags[0], sg_page(sg), fraglen,
+                               sg->offset + sg->length - fraglen);
                desc->fragno = 1;
                desc->fraglen = fraglen;
        } else {
 
                do {
                        if (thislen > page_len)
                                thislen = page_len;
-                       sg_set_page(sg, buf->pages[i]);
-                       sg->offset = page_offset;
-                       sg->length = thislen;
+                       sg_set_page(sg, buf->pages[i], thislen, page_offset);
                        ret = actor(sg, data);
                        if (ret)
                                goto out;
 
                if (copy > len)
                        copy = len;
 
-               sg_set_page(&sg, virt_to_page(skb->data + offset));
-               sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-               sg.length = copy;
+               sg_set_buf(&sg, skb->data + offset, copy);
 
                err = icv_update(desc, &sg, copy);
                if (unlikely(err))
                        if (copy > len)
                                copy = len;
 
-                       sg_set_page(&sg, frag->page);
-                       sg.offset = frag->page_offset + offset-start;
-                       sg.length = copy;
+                       sg_set_page(&sg, frag->page, copy,
+                                       frag->page_offset + offset-start);
 
                        err = icv_update(desc, &sg, copy);
                        if (unlikely(err))