]> err.no Git - linux-2.6/blobdiff - drivers/scsi/sg.c
[SCSI] sgiwd93: use cached memory access to make driver work on IP28
[linux-2.6] / drivers / scsi / sg.c
index 7238b2dfc4975d9a53a82f07dfd55ff427b27e19..aba28f335b88ffd677764a4aeaade2d91e95137a 100644 (file)
@@ -48,6 +48,7 @@ static int sg_version_num = 30534;    /* 2 digits for each component */
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
+#include <linux/blktrace_api.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -602,8 +603,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
         * but is is possible that the app intended SG_DXFER_TO_DEV, because there
         * is a non-zero input_size, so emit a warning.
         */
-       if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV)
-               if (printk_ratelimit())
+       if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
+               static char cmd[TASK_COMM_LEN];
+               if (strcmp(current->comm, cmd) && printk_ratelimit()) {
                        printk(KERN_WARNING
                               "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--"
                               "guessing data in;\n" KERN_WARNING "   "
@@ -611,6 +613,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
                               old_hdr.reply_len - (int)SZ_SG_HEADER,
                               input_size, (unsigned int) cmnd[0],
                               current->comm);
+                       strcpy(cmd, current->comm);
+               }
+       }
        k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
        return (k < 0) ? k : count;
 }
@@ -1063,6 +1068,17 @@ sg_ioctl(struct inode *inode, struct file *filp,
        case BLKSECTGET:
                return put_user(sdp->device->request_queue->max_sectors * 512,
                                ip);
+       case BLKTRACESETUP:
+               return blk_trace_setup(sdp->device->request_queue,
+                                      sdp->disk->disk_name,
+                                      sdp->device->sdev_gendev.devt,
+                                      (char *)arg);
+       case BLKTRACESTART:
+               return blk_trace_startstop(sdp->device->request_queue, 1);
+       case BLKTRACESTOP:
+               return blk_trace_startstop(sdp->device->request_queue, 0);
+       case BLKTRACETEARDOWN:
+               return blk_trace_remove(sdp->device->request_queue);
        default:
                if (read_only)
                        return -EPERM;  /* don't know so take safe approach */
@@ -1169,7 +1185,7 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
                len = vma->vm_end - sa;
                len = (len < sg->length) ? len : sg->length;
                if (offset < len) {
-                       page = virt_to_page(page_address(sg->page) + offset);
+                       page = virt_to_page(page_address(sg_page(sg)) + offset);
                        get_page(page); /* increment page count */
                        break;
                }
@@ -1418,7 +1434,6 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
                goto out;
        }
 
-       class_set_devdata(cl_dev, sdp);
        error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1);
        if (error)
                goto cdev_add_err;
@@ -1431,11 +1446,14 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
                                MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
                                cl_dev->dev, "%s",
                                disk->disk_name);
-               if (IS_ERR(sg_class_member))
-                       printk(KERN_WARNING "sg_add: "
-                               "class_device_create failed\n");
+               if (IS_ERR(sg_class_member)) {
+                       printk(KERN_ERR "sg_add: "
+                              "class_device_create failed\n");
+                       error = PTR_ERR(sg_class_member);
+                       goto cdev_add_err;
+               }
                class_set_devdata(sg_class_member, sdp);
-               error = sysfs_create_link(&scsidp->sdev_gendev.kobj, 
+               error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
                                          &sg_class_member->kobj, "generic");
                if (error)
                        printk(KERN_ERR "sg_add: unable to make symlink "
@@ -1447,6 +1465,8 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
                    "Attached scsi generic sg%d type %d\n", sdp->index,
                    scsidp->type);
 
+       class_set_devdata(cl_dev, sdp);
+
        return 0;
 
 cdev_add_err:
@@ -1652,6 +1672,7 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
        schp->buffer = kzalloc(sg_bufflen, gfp_flags);
        if (!schp->buffer)
                return -ENOMEM;
+       sg_init_table(schp->buffer, tablesize);
        schp->sglist_len = sg_bufflen;
        return tablesize;       /* number of scat_gath elements allocated */
 }
@@ -1717,16 +1738,12 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
                   goto out_unlock; */
         }
 
-       sgl[0].page = 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++) {
-                       sgl[i].page = 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;
@@ -1754,7 +1771,7 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
        int i;
 
        for (i=0; i < nr_pages; i++) {
-               struct page *page = sgl[i].page;
+               struct page *page = sg_page(&sgl[i]);
 
                if (dirtied)
                        SetPageDirty(page);
@@ -1854,8 +1871,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
                                scatter_elem_sz_prev = ret_sz;
                        }
                }
-               sg->page = 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));
@@ -1907,14 +1923,14 @@ sg_write_xfer(Sg_request * srp)
                onum = 1;
 
        ksglen = sg->length;
-       p = page_address(sg->page);
+       p = page_address(sg_page(sg));
        for (j = 0, k = 0; j < onum; ++j) {
                res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
                if (res)
                        return res;
 
                for (; p; sg = sg_next(sg), ksglen = sg->length,
-                    p = page_address(sg->page)) {
+                    p = page_address(sg_page(sg))) {
                        if (usglen <= 0)
                                break;
                        if (ksglen > usglen) {
@@ -1991,12 +2007,12 @@ sg_remove_scat(Sg_scatter_hold * schp)
                } else {
                        int k;
 
-                       for (k = 0; (k < schp->k_use_sg) && sg->page;
+                       for (k = 0; (k < schp->k_use_sg) && sg_page(sg);
                             ++k, sg = sg_next(sg)) {
                                SCSI_LOG_TIMEOUT(5, printk(
                                    "sg_remove_scat: k=%d, pg=0x%p, len=%d\n",
-                                   k, sg->page, sg->length));
-                               sg_page_free(sg->page, sg->length);
+                                   k, sg_page(sg), sg->length));
+                               sg_page_free(sg_page(sg), sg->length);
                        }
                }
                kfree(schp->buffer);
@@ -2038,7 +2054,7 @@ sg_read_xfer(Sg_request * srp)
        } else
                onum = 1;
 
-       p = page_address(sg->page);
+       p = page_address(sg_page(sg));
        ksglen = sg->length;
        for (j = 0, k = 0; j < onum; ++j) {
                res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
@@ -2046,7 +2062,7 @@ sg_read_xfer(Sg_request * srp)
                        return res;
 
                for (; p; sg = sg_next(sg), ksglen = sg->length,
-                    p = page_address(sg->page)) {
+                    p = page_address(sg_page(sg))) {
                        if (usglen <= 0)
                                break;
                        if (ksglen > usglen) {
@@ -2092,15 +2108,15 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
        if ((!outp) || (num_read_xfer <= 0))
                return 0;
 
-       for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, sg = sg_next(sg)) {
+       for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) {
                num = sg->length;
                if (num > num_read_xfer) {
-                       if (__copy_to_user(outp, page_address(sg->page),
+                       if (__copy_to_user(outp, page_address(sg_page(sg)),
                                           num_read_xfer))
                                return -EFAULT;
                        break;
                } else {
-                       if (__copy_to_user(outp, page_address(sg->page),
+                       if (__copy_to_user(outp, page_address(sg_page(sg)),
                                           num))
                                return -EFAULT;
                        num_read_xfer -= num;
@@ -2525,7 +2541,7 @@ sg_idr_max_id(int id, void *p, void *data)
 static int
 sg_last_dev(void)
 {
-       int k = 0;
+       int k = -1;
        unsigned long iflags;
 
        read_lock_irqsave(&sg_index_lock, iflags);