]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/sg.c
sg: remove unnecessary blk_rq_unmap_user
[linux-2.6-omap-h63xx.git] / drivers / scsi / sg.c
index d6391666502c7cb0dc5d62c9cf045cbb9197bd33..ba9b9bbd4e7385e8d83f3ed4f4a1151b96ab3a1f 100644 (file)
@@ -68,7 +68,6 @@ static void sg_proc_cleanup(void);
 #endif
 
 #define SG_ALLOW_DIO_DEF 0
-#define SG_ALLOW_DIO_CODE /* compile out by commenting this define */
 
 #define SG_MAX_DEVS 32768
 
@@ -117,7 +116,6 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
        unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
        unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */
        unsigned bufflen;       /* Size of (aggregate) data buffer */
-       unsigned b_malloc_len;  /* actual len malloc'ed in buffer */
        struct page **pages;
        int page_order;
        char dio_in_use;        /* 0->indirect IO (or mmap), 1->dio */
@@ -177,7 +175,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
 
 static int sg_fasync(int fd, struct file *filp, int mode);
 /* tasklet or soft irq callback */
-static void sg_cmd_done(void *data, char *sense, int result, int resid);
+static void sg_rq_end_io(struct request *rq, int uptodate);
 static int sg_start_req(Sg_request *srp, unsigned char *cmd);
 static void sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
@@ -190,8 +188,6 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
                        int read_only, Sg_request **o_srp);
 static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
                           unsigned char *cmnd, int timeout, int blocking);
-static int sg_write_xfer(Sg_request * srp);
-static int sg_read_xfer(Sg_request * srp);
 static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
 static void sg_remove_scat(Sg_scatter_hold * schp);
 static void sg_build_reserve(Sg_fd * sfp, int req_size);
@@ -204,7 +200,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
-static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
 #ifdef CONFIG_SCSI_PROC_FS
 static int sg_last_dev(void);
@@ -227,11 +222,6 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
                                  cmd, filp->f_mode & FMODE_WRITE);
 }
 
-static void sg_rq_end_io(struct request *rq, int uptodate)
-{
-       sg_cmd_done(rq->end_io_data, rq->sense, rq->errors, rq->data_len);
-}
-
 static int
 sg_open(struct inode *inode, struct file *filp)
 {
@@ -532,8 +522,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
                err = -EFAULT;
                goto err_out;
        }
-       err = sg_read_xfer(srp);
-      err_out:
+err_out:
        sg_finish_rem_req(srp);
        return (0 == err) ? count : err;
 }
@@ -615,7 +604,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
        else
                hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE;
        hp->dxfer_len = mxsize;
-       hp->dxferp = (char __user *)buf + cmd_size;
+       if (hp->dxfer_direction == SG_DXFER_TO_DEV)
+               hp->dxferp = (char __user *)buf + cmd_size;
+       else
+               hp->dxferp = NULL;
        hp->sbp = NULL;
        hp->timeout = old_hdr.reply_len;        /* structure abuse ... */
        hp->flags = input_size; /* structure abuse ... */
@@ -741,11 +733,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
                sg_finish_rem_req(srp);
                return k;       /* probably out of space --> ENOMEM */
        }
-       if ((k = sg_write_xfer(srp))) {
-               SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n"));
-               sg_finish_rem_req(srp);
-               return k;
-       }
        if (sdp->detached) {
                sg_finish_rem_req(srp);
                return -ENODEV;
@@ -1254,16 +1241,19 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-/* This function is a "bottom half" handler that is called by the
- * mid level when a command is completed (or has failed). */
-static void
-sg_cmd_done(void *data, char *sense, int result, int resid)
+/*
+ * This function is a "bottom half" handler that is called by the mid
+ * level when a command is completed (or has failed).
+ */
+static void sg_rq_end_io(struct request *rq, int uptodate)
 {
-       Sg_request *srp = data;
+       struct sg_request *srp = rq->end_io_data;
        Sg_device *sdp = NULL;
        Sg_fd *sfp;
        unsigned long iflags;
        unsigned int ms;
+       char *sense;
+       int result, resid;
 
        if (NULL == srp) {
                printk(KERN_ERR "sg_cmd_done: NULL request\n");
@@ -1277,6 +1267,9 @@ sg_cmd_done(void *data, char *sense, int result, int resid)
                return;
        }
 
+       sense = rq->sense;
+       result = rq->errors;
+       resid = rq->data_len;
 
        SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
                sdp->disk->disk_name, srp->header.pack_id, result));
@@ -1624,14 +1617,24 @@ exit_sg(void)
        idr_destroy(&sg_index_idr);
 }
 
-static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp,
-                         unsigned char *cmd)
+static int sg_start_req(Sg_request *srp, unsigned char *cmd)
 {
-       struct sg_fd *sfp = srp->parentfp;
-       struct request_queue *q = sfp->parentdp->device->request_queue;
+       int res;
        struct request *rq;
+       Sg_fd *sfp = srp->parentfp;
+       sg_io_hdr_t *hp = &srp->header;
+       int dxfer_len = (int) hp->dxfer_len;
+       int dxfer_dir = hp->dxfer_direction;
+       unsigned int iov_count = hp->iovec_count;
+       Sg_scatter_hold *req_schp = &srp->data;
+       Sg_scatter_hold *rsv_schp = &sfp->reserve;
+       struct request_queue *q = sfp->parentdp->device->request_queue;
+       struct rq_map_data *md, map_data;
        int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ;
 
+       SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n",
+                                  dxfer_len));
+
        rq = blk_get_request(q, rw, GFP_ATOMIC);
        if (!rq)
                return -ENOMEM;
@@ -1646,65 +1649,46 @@ static int __sg_start_req(struct sg_request *srp, struct sg_io_hdr *hp,
        rq->sense = srp->sense_b;
        rq->retries = SG_DEFAULT_RETRIES;
 
-       return 0;
-}
-
-static int sg_start_req(Sg_request *srp, unsigned char *cmd)
-{
-       int res;
-       Sg_fd *sfp = srp->parentfp;
-       sg_io_hdr_t *hp = &srp->header;
-       int dxfer_len = (int) hp->dxfer_len;
-       int dxfer_dir = hp->dxfer_direction;
-       unsigned long uaddr = (unsigned long)hp->dxferp;
-       Sg_scatter_hold *req_schp = &srp->data;
-       Sg_scatter_hold *rsv_schp = &sfp->reserve;
-       struct request_queue *q = sfp->parentdp->device->request_queue;
-       unsigned long alignment = queue_dma_alignment(q) | q->dma_pad_mask;
-       struct rq_map_data map_data;
+       if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
+               return 0;
 
-       SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len));
+       if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO &&
+           dxfer_dir != SG_DXFER_UNKNOWN && !iov_count &&
+           !sfp->parentdp->device->host->unchecked_isa_dma &&
+           blk_rq_aligned(q, hp->dxferp, dxfer_len))
+               md = NULL;
+       else
+               md = &map_data;
 
-       res = __sg_start_req(srp, hp, cmd);
-       if (res)
-               return res;
+       if (md) {
+               if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
+                       sg_link_reserve(sfp, srp, dxfer_len);
+               else {
+                       res = sg_build_indirect(req_schp, sfp, dxfer_len);
+                       if (res)
+                               return res;
+               }
 
-       if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE))
-               return 0;
+               md->pages = req_schp->pages;
+               md->page_order = req_schp->page_order;
+               md->nr_entries = req_schp->k_use_sg;
+       }
 
-#ifdef SG_ALLOW_DIO_CODE
-       if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) &&
-           (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) &&
-           (!sfp->parentdp->device->host->unchecked_isa_dma) &&
-           !(uaddr & alignment) && !(dxfer_len & alignment))
-               return sg_build_direct(srp, sfp, dxfer_len);
-#endif
-       if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen))
-               sg_link_reserve(sfp, srp, dxfer_len);
+       if (iov_count)
+               res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
+                                         hp->dxfer_len, GFP_ATOMIC);
        else
-               res = sg_build_indirect(req_schp, sfp, dxfer_len);
+               res = blk_rq_map_user(q, rq, md, hp->dxferp,
+                                     hp->dxfer_len, GFP_ATOMIC);
 
        if (!res) {
-               struct request *rq = srp->rq;
-               Sg_scatter_hold *schp = &srp->data;
-               int iovec_count = (int) hp->iovec_count;
-
-               map_data.pages = schp->pages;
-               map_data.page_order = schp->page_order;
-               map_data.nr_entries = schp->k_use_sg;
-
-               if (iovec_count)
-                       res = blk_rq_map_user_iov(q, rq, &map_data, hp->dxferp,
-                                                 iovec_count,
-                                                 hp->dxfer_len, GFP_ATOMIC);
-               else
-                       res = blk_rq_map_user(q, rq, &map_data, hp->dxferp,
-                                             hp->dxfer_len, GFP_ATOMIC);
+               srp->bio = rq->bio;
 
-               if (!res)
-                       srp->bio = rq->bio;
+               if (!md) {
+                       req_schp->dio_in_use = 1;
+                       hp->info |= SG_INFO_DIRECT_IO;
+               }
        }
-
        return res;
 }
 
@@ -1743,25 +1727,6 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
        return tablesize;       /* number of scat_gath elements allocated */
 }
 
-/* Returns: -ve -> error, 0 -> done, 1 -> try indirect */
-static int
-sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
-{
-       sg_io_hdr_t *hp = &srp->header;
-       Sg_scatter_hold *schp = &srp->data;
-       int res;
-       struct request *rq = srp->rq;
-       struct request_queue *q = sfp->parentdp->device->request_queue;
-
-       res = blk_rq_map_user(q, rq, NULL, hp->dxferp, dxfer_len, GFP_ATOMIC);
-       if (res)
-               return res;
-       srp->bio = rq->bio;
-       schp->dio_in_use = 1;
-       hp->info |= SG_INFO_DIRECT_IO;
-       return 0;
-}
-
 static int
 sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 {
@@ -1843,32 +1808,6 @@ out:
        return -ENOMEM;
 }
 
-static int
-sg_write_xfer(Sg_request * srp)
-{
-       sg_io_hdr_t *hp = &srp->header;
-       Sg_scatter_hold *schp = &srp->data;
-       int num_xfer = 0;
-       int dxfer_dir = hp->dxfer_direction;
-       int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
-
-       if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) ||
-           (SG_DXFER_TO_FROM_DEV == dxfer_dir)) {
-               num_xfer = (int) (new_interface ? hp->dxfer_len : hp->flags);
-               if (schp->bufflen < num_xfer)
-                       num_xfer = schp->bufflen;
-       }
-       if ((num_xfer <= 0) || (schp->dio_in_use) ||
-           (new_interface
-            && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
-               return 0;
-
-       SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, k_use_sg=%d\n",
-                         num_xfer, schp->k_use_sg));
-
-       return 0;
-}
-
 static void
 sg_remove_scat(Sg_scatter_hold * schp)
 {
@@ -1890,31 +1829,6 @@ sg_remove_scat(Sg_scatter_hold * schp)
        memset(schp, 0, sizeof (*schp));
 }
 
-static int
-sg_read_xfer(Sg_request * srp)
-{
-       sg_io_hdr_t *hp = &srp->header;
-       Sg_scatter_hold *schp = &srp->data;
-       int num_xfer = 0;
-       int dxfer_dir = hp->dxfer_direction;
-       int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
-
-       if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir)
-           || (SG_DXFER_TO_FROM_DEV == dxfer_dir)) {
-               num_xfer = hp->dxfer_len;
-               if (schp->bufflen < num_xfer)
-                       num_xfer = schp->bufflen;
-       }
-       if ((num_xfer <= 0) || (schp->dio_in_use) ||
-           (new_interface
-            && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags)))
-               return 0;
-
-       SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n",
-                         num_xfer, (int)hp->iovec_count, schp->k_use_sg));
-       return 0;
-}
-
 static int
 sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
 {
@@ -1926,9 +1840,6 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
        if ((!outp) || (num_read_xfer <= 0))
                return 0;
 
-       blk_rq_unmap_user(srp->bio);
-       srp->bio = NULL;
-
        num = 1 << (PAGE_SHIFT + schp->page_order);
        for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) {
                if (num > num_read_xfer) {
@@ -1986,7 +1897,6 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
                        req_schp->pages = rsv_schp->pages;
 
                        req_schp->bufflen = size;
-                       req_schp->b_malloc_len = rsv_schp->b_malloc_len;
                        req_schp->page_order = rsv_schp->page_order;
                        break;
                } else