Merge branch 'for-3.2/core' into for-3.2/drivers
authorJens Axboe <jaxboe@fusionio.com>
Tue, 23 Aug 2011 18:01:11 +0000 (20:01 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Tue, 23 Aug 2011 18:01:11 +0000 (20:01 +0200)
Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
Documentation/blockdev/cciss.txt
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/loop.c
drivers/block/nbd.c

index f5bb0a3bb8c0d5d18bdcfdd2bf8ce70765ed4dc5..53d99edd1d75acf45fc63152b111d5fbcc6ea202 100644 (file)
@@ -71,3 +71,10 @@ Description: Value of 1 indicates the controller can honor the reset_devices
                a dump device, as kdump requires resetting the device in order
                to work reliably.
 
+Where:         /sys/bus/pci/devices/<dev>/ccissX/transport_mode
+Date:          July 2011
+Kernel Version:        3.0
+Contact:       iss_storagedev@hp.com
+Description:   Value of "simple" indicates that the controller has been placed
+               in "simple mode". Value of "performant" indicates that the
+               controller has been placed in "performant mode".
index c00c6a5ab21f6b0d253bf465eb6e1274d5994d18..71464e09ec1841a39f031d972b281488e5d703af 100644 (file)
@@ -78,6 +78,16 @@ The device naming scheme is:
 /dev/cciss/c1d1p2              Controller 1, disk 1, partition 2
 /dev/cciss/c1d1p3              Controller 1, disk 1, partition 3
 
+CCISS simple mode support
+-------------------------
+
+The "cciss_simple_mode=1" boot parameter may be used to prevent the driver
+from putting the controller into "performant" mode. The difference is that
+with simple mode, each command completion requires an interrupt, while with
+"performant mode" (the default, and ordinarily better performing) it is
+possible to have multiple command completions indicated by a single
+interrupt.
+
 SCSI tape drive and medium changer support
 ------------------------------------------
 
index 8f4ef656a1af4ca435ff3ecc5e0d6079e6a1e34d..6da7edea700a274815fb4367598478197a853f4e 100644 (file)
@@ -68,6 +68,10 @@ static int cciss_tape_cmds = 6;
 module_param(cciss_tape_cmds, int, 0644);
 MODULE_PARM_DESC(cciss_tape_cmds,
        "number of commands to allocate for tape devices (default: 6)");
+static int cciss_simple_mode;
+module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cciss_simple_mode,
+       "Use 'simple mode' rather than 'performant mode'");
 
 static DEFINE_MUTEX(cciss_mutex);
 static struct proc_dir_entry *proc_cciss;
@@ -176,6 +180,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol,
                        unsigned int block_size, InquiryData_struct *inq_buff,
                                   drive_info_struct *drv);
 static void __devinit cciss_interrupt_mode(ctlr_info_t *);
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
 static void start_io(ctlr_info_t *h);
 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
                        __u8 page_code, unsigned char scsi3addr[],
@@ -388,7 +393,7 @@ static void cciss_seq_show_header(struct seq_file *seq)
                h->product_name,
                (unsigned long)h->board_id,
                h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
-               h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT],
+               h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
                h->num_luns,
                h->Qdepth, h->commands_outstanding,
                h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -636,6 +641,18 @@ static ssize_t host_store_rescan(struct device *dev,
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 
+static ssize_t host_show_transport_mode(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct ctlr_info *h = to_hba(dev);
+
+       return snprintf(buf, 20, "%s\n",
+               h->transMethod & CFGTBL_Trans_Performant ?
+                       "performant" : "simple");
+}
+static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL);
+
 static ssize_t dev_show_unique_id(struct device *dev,
                                 struct device_attribute *attr,
                                 char *buf)
@@ -808,6 +825,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL);
 static struct attribute *cciss_host_attrs[] = {
        &dev_attr_rescan.attr,
        &dev_attr_resettable.attr,
+       &dev_attr_transport_mode.attr,
        NULL
 };
 
@@ -3984,6 +4002,9 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
 {
        __u32 trans_support;
 
+       if (cciss_simple_mode)
+               return;
+
        dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
        /* Attempt to put controller into performant mode if supported */
        /* Does board support performant mode? */
@@ -4081,7 +4102,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h)
 default_int_mode:
 #endif                         /* CONFIG_PCI_MSI */
        /* if we get here we're going to use the default interrupt mode */
-       h->intr[PERF_MODE_INT] = h->pdev->irq;
+       h->intr[h->intr_mode] = h->pdev->irq;
        return;
 }
 
@@ -4341,6 +4362,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
        }
        cciss_enable_scsi_prefetch(h);
        cciss_p600_dma_prefetch_quirk(h);
+       err = cciss_enter_simple_mode(h);
+       if (err)
+               goto err_out_free_res;
        cciss_put_controller_into_performant_mode(h);
        return 0;
 
@@ -4843,20 +4867,20 @@ static int cciss_request_irq(ctlr_info_t *h,
        irqreturn_t (*intxhandler)(int, void *))
 {
        if (h->msix_vector || h->msi_vector) {
-               if (!request_irq(h->intr[PERF_MODE_INT], msixhandler,
+               if (!request_irq(h->intr[h->intr_mode], msixhandler,
                                IRQF_DISABLED, h->devname, h))
                        return 0;
                dev_err(&h->pdev->dev, "Unable to get msi irq %d"
-                       " for %s\n", h->intr[PERF_MODE_INT],
+                       " for %s\n", h->intr[h->intr_mode],
                        h->devname);
                return -1;
        }
 
-       if (!request_irq(h->intr[PERF_MODE_INT], intxhandler,
+       if (!request_irq(h->intr[h->intr_mode], intxhandler,
                        IRQF_DISABLED, h->devname, h))
                return 0;
        dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
-               h->intr[PERF_MODE_INT], h->devname);
+               h->intr[h->intr_mode], h->devname);
        return -1;
 }
 
@@ -4887,7 +4911,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
 {
        int ctlr = h->ctlr;
 
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
 #ifdef CONFIG_PCI_MSI
        if (h->msix_vector)
                pci_disable_msix(h->pdev);
@@ -4953,6 +4977,7 @@ reinit_after_soft_reset:
        h = hba[i];
        h->pdev = pdev;
        h->busy_initializing = 1;
+       h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
        INIT_LIST_HEAD(&h->cmpQ);
        INIT_LIST_HEAD(&h->reqQ);
        mutex_init(&h->busy_shutting_down);
@@ -5009,7 +5034,7 @@ reinit_after_soft_reset:
 
        dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
               h->devname, pdev->device, pci_name(pdev),
-              h->intr[PERF_MODE_INT], dac ? "" : " not");
+              h->intr[h->intr_mode], dac ? "" : " not");
 
        if (cciss_allocate_cmd_pool(h))
                goto clean4;
@@ -5056,7 +5081,7 @@ reinit_after_soft_reset:
                spin_lock_irqsave(&h->lock, flags);
                h->access.set_intr_mask(h, CCISS_INTR_OFF);
                spin_unlock_irqrestore(&h->lock, flags);
-               free_irq(h->intr[PERF_MODE_INT], h);
+               free_irq(h->intr[h->intr_mode], h);
                rc = cciss_request_irq(h, cciss_msix_discard_completions,
                                        cciss_intx_discard_completions);
                if (rc) {
@@ -5133,7 +5158,7 @@ clean4:
        cciss_free_cmd_pool(h);
        cciss_free_scatterlists(h);
        cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
 clean2:
        unregister_blkdev(h->major, h->devname);
 clean1:
@@ -5172,9 +5197,31 @@ static void cciss_shutdown(struct pci_dev *pdev)
        if (return_code != IO_OK)
                dev_warn(&h->pdev->dev, "Error flushing cache\n");
        h->access.set_intr_mask(h, CCISS_INTR_OFF);
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
+}
+
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
+{
+       u32 trans_support;
+
+       trans_support = readl(&(h->cfgtable->TransportSupport));
+       if (!(trans_support & SIMPLE_MODE))
+               return -ENOTSUPP;
+
+       h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+       writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+       writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+       cciss_wait_for_mode_change_ack(h);
+       print_cfg_table(h);
+       if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+               dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
+               return -ENODEV;
+       }
+       h->transMethod = CFGTBL_Trans_Simple;
+       return 0;
 }
 
+
 static void __devexit cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *h;
index c049548e68b7ba39d27cf7b9c216868c8fc2b18e..7fda30e4a2416195696b6a4eebd560d74fca6917 100644 (file)
@@ -92,6 +92,7 @@ struct ctlr_info
        unsigned int intr[4];
        unsigned int msix_vector;
        unsigned int msi_vector;
+       int     intr_mode;
        int     cciss_max_sectors;
        BYTE    cciss_read;
        BYTE    cciss_write;
index 76c8da78212bffec71f5dc7af025a84e4028d456..936cac3c3126600636ec1d94e128b2a9174db84d 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/kthread.h>
 #include <linux/splice.h>
 #include <linux/sysfs.h>
+#include <linux/falloc.h>
 
 #include <asm/uaccess.h>
 
@@ -484,6 +485,29 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
                        }
                }
 
+               /*
+                * We use punch hole to reclaim the free space used by the
+                * image a.k.a. discard. However we do support discard if
+                * encryption is enabled, because it may give an attacker
+                * useful information.
+                */
+               if (bio->bi_rw & REQ_DISCARD) {
+                       struct file *file = lo->lo_backing_file;
+                       int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+
+                       if ((!file->f_op->fallocate) ||
+                           lo->lo_encrypt_key_size) {
+                               ret = -EOPNOTSUPP;
+                               goto out;
+                       }
+                       ret = file->f_op->fallocate(file, mode, pos,
+                                                   bio->bi_size);
+                       if (unlikely(ret && ret != -EINVAL &&
+                                    ret != -EOPNOTSUPP))
+                               ret = -EIO;
+                       goto out;
+               }
+
                ret = lo_send(lo, bio, pos);
 
                if ((bio->bi_rw & REQ_FUA) && !ret) {
@@ -814,6 +838,35 @@ static void loop_sysfs_exit(struct loop_device *lo)
                           &loop_attribute_group);
 }
 
+static void loop_config_discard(struct loop_device *lo)
+{
+       struct file *file = lo->lo_backing_file;
+       struct inode *inode = file->f_mapping->host;
+       struct request_queue *q = lo->lo_queue;
+
+       /*
+        * We use punch hole to reclaim the free space used by the
+        * image a.k.a. discard. However we do support discard if
+        * encryption is enabled, because it may give an attacker
+        * useful information.
+        */
+       if ((!file->f_op->fallocate) ||
+           lo->lo_encrypt_key_size) {
+               q->limits.discard_granularity = 0;
+               q->limits.discard_alignment = 0;
+               q->limits.max_discard_sectors = 0;
+               q->limits.discard_zeroes_data = 0;
+               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+               return;
+       }
+
+       q->limits.discard_granularity = inode->i_sb->s_blocksize;
+       q->limits.discard_alignment = inode->i_sb->s_blocksize;
+       q->limits.max_discard_sectors = UINT_MAX >> 9;
+       q->limits.discard_zeroes_data = 1;
+       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
                       struct block_device *bdev, unsigned int arg)
 {
@@ -1090,6 +1143,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
                if (figure_loop_size(lo))
                        return -EFBIG;
        }
+       loop_config_discard(lo);
 
        memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
        memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
index f533f3375e24751feaf4e065b920291c7abe149d..c3f0ee16594dac8d33b92d2dafd02a6ee4e1526d 100644 (file)
@@ -127,8 +127,7 @@ static void sock_shutdown(struct nbd_device *lo, int lock)
        if (lock)
                mutex_lock(&lo->tx_lock);
        if (lo->sock) {
-               printk(KERN_WARNING "%s: shutting down socket\n",
-                       lo->disk->disk_name);
+               dev_warn(disk_to_dev(lo->disk), "shutting down socket\n");
                kernel_sock_shutdown(lo->sock, SHUT_RDWR);
                lo->sock = NULL;
        }
@@ -158,8 +157,9 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
        sigset_t blocked, oldset;
 
        if (unlikely(!sock)) {
-               printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
-                      lo->disk->disk_name, (send ? "send" : "recv"));
+               dev_err(disk_to_dev(lo->disk),
+                       "Attempted %s on closed socket in sock_xmit\n",
+                       (send ? "send" : "recv"));
                return -EINVAL;
        }
 
@@ -250,8 +250,8 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
        result = sock_xmit(lo, 1, &request, sizeof(request),
                        (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
        if (result <= 0) {
-               printk(KERN_ERR "%s: Send control failed (result %d)\n",
-                               lo->disk->disk_name, result);
+               dev_err(disk_to_dev(lo->disk),
+                       "Send control failed (result %d)\n", result);
                goto error_out;
        }
 
@@ -270,8 +270,9 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
                                        lo->disk->disk_name, req, bvec->bv_len);
                        result = sock_send_bvec(lo, bvec, flags);
                        if (result <= 0) {
-                               printk(KERN_ERR "%s: Send data failed (result %d)\n",
-                                               lo->disk->disk_name, result);
+                               dev_err(disk_to_dev(lo->disk),
+                                       "Send data failed (result %d)\n",
+                                       result);
                                goto error_out;
                        }
                }
@@ -328,14 +329,13 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
        reply.magic = 0;
        result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
        if (result <= 0) {
-               printk(KERN_ERR "%s: Receive control failed (result %d)\n",
-                               lo->disk->disk_name, result);
+               dev_err(disk_to_dev(lo->disk),
+                       "Receive control failed (result %d)\n", result);
                goto harderror;
        }
 
        if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-               printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
-                               lo->disk->disk_name,
+               dev_err(disk_to_dev(lo->disk), "Wrong magic (0x%lx)\n",
                                (unsigned long)ntohl(reply.magic));
                result = -EPROTO;
                goto harderror;
@@ -347,15 +347,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
                if (result != -ENOENT)
                        goto harderror;
 
-               printk(KERN_ERR "%s: Unexpected reply (%p)\n",
-                               lo->disk->disk_name, reply.handle);
+               dev_err(disk_to_dev(lo->disk), "Unexpected reply (%p)\n",
+                       reply.handle);
                result = -EBADR;
                goto harderror;
        }
 
        if (ntohl(reply.error)) {
-               printk(KERN_ERR "%s: Other side returned error (%d)\n",
-                               lo->disk->disk_name, ntohl(reply.error));
+               dev_err(disk_to_dev(lo->disk), "Other side returned error (%d)\n",
+                       ntohl(reply.error));
                req->errors++;
                return req;
        }
@@ -369,8 +369,8 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
                rq_for_each_segment(bvec, req, iter) {
                        result = sock_recv_bvec(lo, bvec);
                        if (result <= 0) {
-                               printk(KERN_ERR "%s: Receive data failed (result %d)\n",
-                                               lo->disk->disk_name, result);
+                               dev_err(disk_to_dev(lo->disk), "Receive data failed (result %d)\n",
+                                       result);
                                req->errors++;
                                return req;
                        }
@@ -405,10 +405,10 @@ static int nbd_do_it(struct nbd_device *lo)
 
        BUG_ON(lo->magic != LO_MAGIC);
 
-       lo->pid = current->pid;
-       ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+       lo->pid = task_pid_nr(current);
+       ret = device_create_file(disk_to_dev(lo->disk), &pid_attr);
        if (ret) {
-               printk(KERN_ERR "nbd: sysfs_create_file failed!");
+               dev_err(disk_to_dev(lo->disk), "device_create_file failed!\n");
                lo->pid = 0;
                return ret;
        }
@@ -416,7 +416,7 @@ static int nbd_do_it(struct nbd_device *lo)
        while ((req = nbd_read_stat(lo)) != NULL)
                nbd_end_request(req);
 
-       sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+       device_remove_file(disk_to_dev(lo->disk), &pid_attr);
        lo->pid = 0;
        return 0;
 }
@@ -457,8 +457,8 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
        if (rq_data_dir(req) == WRITE) {
                nbd_cmd(req) = NBD_CMD_WRITE;
                if (lo->flags & NBD_READ_ONLY) {
-                       printk(KERN_ERR "%s: Write on read-only\n",
-                                       lo->disk->disk_name);
+                       dev_err(disk_to_dev(lo->disk),
+                               "Write on read-only\n");
                        goto error_out;
                }
        }
@@ -468,16 +468,15 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
        mutex_lock(&lo->tx_lock);
        if (unlikely(!lo->sock)) {
                mutex_unlock(&lo->tx_lock);
-               printk(KERN_ERR "%s: Attempted send on closed socket\n",
-                      lo->disk->disk_name);
+               dev_err(disk_to_dev(lo->disk),
+                       "Attempted send on closed socket\n");
                goto error_out;
        }
 
        lo->active_req = req;
 
        if (nbd_send_req(lo, req) != 0) {
-               printk(KERN_ERR "%s: Request send failed\n",
-                               lo->disk->disk_name);
+               dev_err(disk_to_dev(lo->disk), "Request send failed\n");
                req->errors++;
                nbd_end_request(req);
        } else {
@@ -549,8 +548,8 @@ static void do_nbd_request(struct request_queue *q)
                BUG_ON(lo->magic != LO_MAGIC);
 
                if (unlikely(!lo->sock)) {
-                       printk(KERN_ERR "%s: Attempted send on closed socket\n",
-                               lo->disk->disk_name);
+                       dev_err(disk_to_dev(lo->disk),
+                               "Attempted send on closed socket\n");
                        req->errors++;
                        nbd_end_request(req);
                        spin_lock_irq(q->queue_lock);
@@ -576,7 +575,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
        case NBD_DISCONNECT: {
                struct request sreq;
 
-               printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+               dev_info(disk_to_dev(lo->disk), "NBD_DISCONNECT\n");
 
                blk_rq_init(NULL, &sreq);
                sreq.cmd_type = REQ_TYPE_SPECIAL;
@@ -674,7 +673,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                file = lo->file;
                lo->file = NULL;
                nbd_clear_que(lo);
-               printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
+               dev_warn(disk_to_dev(lo->disk), "queue cleared\n");
                if (file)
                        fput(file);
                lo->bytesize = 0;
@@ -694,8 +693,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                return 0;
 
        case NBD_PRINT_DEBUG:
-               printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
-                       bdev->bd_disk->disk_name,
+               dev_info(disk_to_dev(lo->disk),
+                       "next = %p, prev = %p, head = %p\n",
                        lo->queue_head.next, lo->queue_head.prev,
                        &lo->queue_head);
                return 0;
@@ -745,7 +744,7 @@ static int __init nbd_init(void)
        BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
        if (max_part < 0) {
-               printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+               printk(KERN_ERR "nbd: max_part must be >= 0\n");
                return -EINVAL;
        }
 
This page took 0.038093 seconds and 5 git commands to generate.