Commit c104f1fa authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.4/drivers' of git://git.kernel.dk/linux-block

Pull block driver bits from Jens Axboe:

 - A series of fixes for mtip32xx.  Most from Asai at Micron, but also
   one from Greg, getting rid of the dependency on PCIE_HOTPLUG.

 - A few bug fixes for xen-blkfront, and blkback.

 - A virtio-blk fix for Vivek, making resize actually work.

 - Two fixes from Stephen, making larger transfers possible on cciss.
   This is needed for tape drive support.

* 'for-3.4/drivers' of git://git.kernel.dk/linux-block:
  block: mtip32xx: remove HOTPLUG_PCI_PCIE dependancy
  mtip32xx: dump tagmap on failure
  mtip32xx: fix handling of commands in various scenarios
  mtip32xx: Shorten macro names
  mtip32xx: misc changes
  mtip32xx: Add new sysfs entry 'status'
  mtip32xx: make setting comp_time as common
  mtip32xx: Add new bitwise flag 'dd_flag'
  mtip32xx: fix error handling in mtip_init()
  virtio-blk: Call revalidate_disk() upon online disk resize
  xen/blkback: Make optional features be really optional.
  xen/blkback: Squash the discard support for 'file' and 'phy' type.
  mtip32xx: fix incorrect value set for drv_cleanup_done, and re-initialize and start port in mtip_restart_port()
  cciss: Fix scsi tape io with more than 255 scatter gather elements
  cciss: Initialize scsi host max_sectors for tape drive support
  xen-blkfront: make blkif_io_lock spinlock per-device
  xen/blkfront: don't put bdev right after getting it
  xen-blkfront: use bitmap_set() and bitmap_clear()
  xen/blkback: Enable blkback on HVM guests
  xen/blkback: use grant-table.c hypercall wrappers
parents d8dd0b6d 63634806
What: /sys/block/rssd*/registers
Date: March 2012
KernelVersion: 3.3
Contact: Asai Thambi S P <asamymuthupa@micron.com>
Description: This is a read-only file. Dumps below driver information and
hardware registers.
- S ACTive
- Command Issue
- Allocated
- Completed
- PORT IRQ STAT
- HOST IRQ STAT
What: /sys/block/rssd*/status
Date: April 2012
KernelVersion: 3.4
Contact: Asai Thambi S P <asamymuthupa@micron.com>
Description: This is a read-only file. Indicates the status of the device.
...@@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h) ...@@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h)
sh->can_queue = cciss_tape_cmds; sh->can_queue = cciss_tape_cmds;
sh->sg_tablesize = h->maxsgentries; sh->sg_tablesize = h->maxsgentries;
sh->max_cmd_len = MAX_COMMAND_SIZE; sh->max_cmd_len = MAX_COMMAND_SIZE;
sh->max_sectors = h->cciss_max_sectors;
((struct cciss_scsi_adapter_data_t *) ((struct cciss_scsi_adapter_data_t *)
h->scsi_ctlr)->scsi_host = sh; h->scsi_ctlr)->scsi_host = sh;
...@@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c, ...@@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
/* track how many SG entries we are using */ /* track how many SG entries we are using */
if (request_nsgs > h->maxSG) if (request_nsgs > h->maxSG)
h->maxSG = request_nsgs; h->maxSG = request_nsgs;
c->Header.SGTotal = (__u8) request_nsgs + chained; c->Header.SGTotal = (u16) request_nsgs + chained;
if (request_nsgs > h->max_cmd_sgentries) if (request_nsgs > h->max_cmd_sgentries)
c->Header.SGList = h->max_cmd_sgentries; c->Header.SGList = h->max_cmd_sgentries;
else else
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
config BLK_DEV_PCIESSD_MTIP32XX config BLK_DEV_PCIESSD_MTIP32XX
tristate "Block Device Driver for Micron PCIe SSDs" tristate "Block Device Driver for Micron PCIe SSDs"
depends on HOTPLUG_PCI_PCIE depends on PCI
help help
This enables the block driver for Micron PCIe SSDs. This enables the block driver for Micron PCIe SSDs.
This diff is collapsed.
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
/* offset of Device Control register in PCIe extended capabilites space */ /* offset of Device Control register in PCIe extended capabilites space */
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
/* # of times to retry timed out IOs */ /* # of times to retry timed out/failed IOs */
#define MTIP_MAX_RETRIES 5 #define MTIP_MAX_RETRIES 2
/* Various timeout values in ms */ /* Various timeout values in ms */
#define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000 #define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000
...@@ -114,12 +114,41 @@ ...@@ -114,12 +114,41 @@
#define __force_bit2int (unsigned int __force) #define __force_bit2int (unsigned int __force)
/* below are bit numbers in 'flags' defined in mtip_port */ /* below are bit numbers in 'flags' defined in mtip_port */
#define MTIP_FLAG_IC_ACTIVE_BIT 0 #define MTIP_PF_IC_ACTIVE_BIT 0 /* pio/ioctl */
#define MTIP_FLAG_EH_ACTIVE_BIT 1 #define MTIP_PF_EH_ACTIVE_BIT 1 /* error handling */
#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2 #define MTIP_PF_SE_ACTIVE_BIT 2 /* secure erase */
#define MTIP_FLAG_ISSUE_CMDS_BIT 4 #define MTIP_PF_DM_ACTIVE_BIT 3 /* download microcde */
#define MTIP_FLAG_REBUILD_BIT 5 #define MTIP_PF_PAUSE_IO ((1 << MTIP_PF_IC_ACTIVE_BIT) | \
#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 (1 << MTIP_PF_EH_ACTIVE_BIT) | \
(1 << MTIP_PF_SE_ACTIVE_BIT) | \
(1 << MTIP_PF_DM_ACTIVE_BIT))
#define MTIP_PF_SVC_THD_ACTIVE_BIT 4
#define MTIP_PF_ISSUE_CMDS_BIT 5
#define MTIP_PF_REBUILD_BIT 6
#define MTIP_PF_SVC_THD_STOP_BIT 8
/* below are bit numbers in 'dd_flag' defined in driver_data */
#define MTIP_DDF_REMOVE_PENDING_BIT 1
#define MTIP_DDF_OVER_TEMP_BIT 2
#define MTIP_DDF_WRITE_PROTECT_BIT 3
#define MTIP_DDF_STOP_IO ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
(1 << MTIP_DDF_OVER_TEMP_BIT) | \
(1 << MTIP_DDF_WRITE_PROTECT_BIT))
#define MTIP_DDF_CLEANUP_BIT 5
#define MTIP_DDF_RESUME_BIT 6
#define MTIP_DDF_INIT_DONE_BIT 7
#define MTIP_DDF_REBUILD_FAILED_BIT 8
__packed struct smart_attr{
u8 attr_id;
u16 flags;
u8 cur;
u8 worst;
u32 data;
u8 res[3];
};
/* Register Frame Information Structure (FIS), host to device. */ /* Register Frame Information Structure (FIS), host to device. */
struct host_to_dev_fis { struct host_to_dev_fis {
...@@ -345,6 +374,12 @@ struct mtip_port { ...@@ -345,6 +374,12 @@ struct mtip_port {
* when the command slot and all associated data structures * when the command slot and all associated data structures
* are no longer needed. * are no longer needed.
*/ */
u16 *log_buf;
dma_addr_t log_buf_dma;
u8 *smart_buf;
dma_addr_t smart_buf_dma;
unsigned long allocated[SLOTBITS_IN_LONGS]; unsigned long allocated[SLOTBITS_IN_LONGS];
/* /*
* used to queue commands when an internal command is in progress * used to queue commands when an internal command is in progress
...@@ -368,6 +403,7 @@ struct mtip_port { ...@@ -368,6 +403,7 @@ struct mtip_port {
* Timer used to complete commands that have been active for too long. * Timer used to complete commands that have been active for too long.
*/ */
struct timer_list cmd_timer; struct timer_list cmd_timer;
unsigned long ic_pause_timer;
/* /*
* Semaphore used to block threads if there are no * Semaphore used to block threads if there are no
* command slots available. * command slots available.
...@@ -404,13 +440,9 @@ struct driver_data { ...@@ -404,13 +440,9 @@ struct driver_data {
unsigned slot_groups; /* number of slot groups the product supports */ unsigned slot_groups; /* number of slot groups the product supports */
atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
unsigned long index; /* Index to determine the disk name */ unsigned long index; /* Index to determine the disk name */
unsigned int ftlrebuildflag; /* FTL rebuild flag */ unsigned long dd_flag; /* NOTE: use atomic bit operations on this */
atomic_t resumeflag; /* Atomic variable to track suspend/resume */
struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
}; };
......
...@@ -351,6 +351,7 @@ static void virtblk_config_changed_work(struct work_struct *work) ...@@ -351,6 +351,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
cap_str_10, cap_str_2); cap_str_10, cap_str_2);
set_capacity(vblk->disk, capacity); set_capacity(vblk->disk, capacity);
revalidate_disk(vblk->disk);
done: done:
mutex_unlock(&vblk->config_lock); mutex_unlock(&vblk->config_lock);
} }
......
...@@ -321,6 +321,7 @@ struct seg_buf { ...@@ -321,6 +321,7 @@ struct seg_buf {
static void xen_blkbk_unmap(struct pending_req *req) static void xen_blkbk_unmap(struct pending_req *req)
{ {
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
unsigned int i, invcount = 0; unsigned int i, invcount = 0;
grant_handle_t handle; grant_handle_t handle;
int ret; int ret;
...@@ -332,25 +333,12 @@ static void xen_blkbk_unmap(struct pending_req *req) ...@@ -332,25 +333,12 @@ static void xen_blkbk_unmap(struct pending_req *req)
gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i), gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
GNTMAP_host_map, handle); GNTMAP_host_map, handle);
pending_handle(req, i) = BLKBACK_INVALID_HANDLE; pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
pages[invcount] = virt_to_page(vaddr(req, i));
invcount++; invcount++;
} }
ret = HYPERVISOR_grant_table_op( ret = gnttab_unmap_refs(unmap, pages, invcount, false);
GNTTABOP_unmap_grant_ref, unmap, invcount);
BUG_ON(ret); BUG_ON(ret);
/*
* Note, we use invcount, so nr->pages, so we can't index
* using vaddr(req, i).
*/
for (i = 0; i < invcount; i++) {
ret = m2p_remove_override(
virt_to_page(unmap[i].host_addr), false);
if (ret) {
pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n",
(unsigned long)unmap[i].host_addr);
continue;
}
}
} }
static int xen_blkbk_map(struct blkif_request *req, static int xen_blkbk_map(struct blkif_request *req,
...@@ -378,7 +366,7 @@ static int xen_blkbk_map(struct blkif_request *req, ...@@ -378,7 +366,7 @@ static int xen_blkbk_map(struct blkif_request *req,
pending_req->blkif->domid); pending_req->blkif->domid);
} }
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); ret = gnttab_map_refs(map, NULL, &blkbk->pending_page(pending_req, 0), nseg);
BUG_ON(ret); BUG_ON(ret);
/* /*
...@@ -398,15 +386,6 @@ static int xen_blkbk_map(struct blkif_request *req, ...@@ -398,15 +386,6 @@ static int xen_blkbk_map(struct blkif_request *req,
if (ret) if (ret)
continue; continue;
ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
blkbk->pending_page(pending_req, i), NULL);
if (ret) {
pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
(unsigned long)map[i].dev_bus_addr, ret);
/* We could switch over to GNTTABOP_copy */
continue;
}
seg[i].buf = map[i].dev_bus_addr | seg[i].buf = map[i].dev_bus_addr |
(req->u.rw.seg[i].first_sect << 9); (req->u.rw.seg[i].first_sect << 9);
} }
...@@ -419,21 +398,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif, ...@@ -419,21 +398,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
int err = 0; int err = 0;
int status = BLKIF_RSP_OKAY; int status = BLKIF_RSP_OKAY;
struct block_device *bdev = blkif->vbd.bdev; struct block_device *bdev = blkif->vbd.bdev;
unsigned long secure;
blkif->st_ds_req++; blkif->st_ds_req++;
xen_blkif_get(blkif); xen_blkif_get(blkif);
if (blkif->blk_backend_type == BLKIF_BACKEND_PHY || secure = (blkif->vbd.discard_secure &&
blkif->blk_backend_type == BLKIF_BACKEND_FILE) { (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
unsigned long secure = (blkif->vbd.discard_secure && BLKDEV_DISCARD_SECURE : 0;
(req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
BLKDEV_DISCARD_SECURE : 0; err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
err = blkdev_issue_discard(bdev, req->u.discard.nr_sectors,
req->u.discard.sector_number, GFP_KERNEL, secure);
req->u.discard.nr_sectors,
GFP_KERNEL, secure);
} else
err = -EOPNOTSUPP;
if (err == -EOPNOTSUPP) { if (err == -EOPNOTSUPP) {
pr_debug(DRV_PFX "discard op failed, not supported\n"); pr_debug(DRV_PFX "discard op failed, not supported\n");
...@@ -830,7 +806,7 @@ static int __init xen_blkif_init(void) ...@@ -830,7 +806,7 @@ static int __init xen_blkif_init(void)
int i, mmap_pages; int i, mmap_pages;
int rc = 0; int rc = 0;
if (!xen_pv_domain()) if (!xen_domain())
return -ENODEV; return -ENODEV;
blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL);
......
...@@ -146,11 +146,6 @@ enum blkif_protocol { ...@@ -146,11 +146,6 @@ enum blkif_protocol {
BLKIF_PROTOCOL_X86_64 = 3, BLKIF_PROTOCOL_X86_64 = 3,
}; };
enum blkif_backend_type {
BLKIF_BACKEND_PHY = 1,
BLKIF_BACKEND_FILE = 2,
};
struct xen_vbd { struct xen_vbd {
/* What the domain refers to this vbd as. */ /* What the domain refers to this vbd as. */
blkif_vdev_t handle; blkif_vdev_t handle;
...@@ -177,7 +172,6 @@ struct xen_blkif { ...@@ -177,7 +172,6 @@ struct xen_blkif {
unsigned int irq; unsigned int irq;
/* Comms information. */ /* Comms information. */
enum blkif_protocol blk_protocol; enum blkif_protocol blk_protocol;
enum blkif_backend_type blk_backend_type;
union blkif_back_rings blk_rings; union blkif_back_rings blk_rings;
void *blk_ring; void *blk_ring;
/* The VBD attached to this interface. */ /* The VBD attached to this interface. */
......
...@@ -381,72 +381,49 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, ...@@ -381,72 +381,49 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
"%d", state); "%d", state);
if (err) if (err)
xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); dev_warn(&dev->dev, "writing feature-flush-cache (%d)", err);
return err; return err;
} }
int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be) static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
{ {
struct xenbus_device *dev = be->dev; struct xenbus_device *dev = be->dev;
struct xen_blkif *blkif = be->blkif; struct xen_blkif *blkif = be->blkif;
char *type;
int err; int err;
int state = 0; int state = 0;
struct block_device *bdev = be->blkif->vbd.bdev;
struct request_queue *q = bdev_get_queue(bdev);
type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL); if (blk_queue_discard(q)) {
if (!IS_ERR(type)) { err = xenbus_printf(xbt, dev->nodename,
if (strncmp(type, "file", 4) == 0) { "discard-granularity", "%u",
state = 1; q->limits.discard_granularity);
blkif->blk_backend_type = BLKIF_BACKEND_FILE; if (err) {
dev_warn(&dev->dev, "writing discard-granularity (%d)", err);
return;
} }
if (strncmp(type, "phy", 3) == 0) { err = xenbus_printf(xbt, dev->nodename,
struct block_device *bdev = be->blkif->vbd.bdev; "discard-alignment", "%u",
struct request_queue *q = bdev_get_queue(bdev); q->limits.discard_alignment);
if (blk_queue_discard(q)) { if (err) {
err = xenbus_printf(xbt, dev->nodename, dev_warn(&dev->dev, "writing discard-alignment (%d)", err);
"discard-granularity", "%u", return;
q->limits.discard_granularity); }
if (err) { state = 1;
xenbus_dev_fatal(dev, err, /* Optional. */
"writing discard-granularity"); err = xenbus_printf(xbt, dev->nodename,
goto kfree; "discard-secure", "%d",
} blkif->vbd.discard_secure);
err = xenbus_printf(xbt, dev->nodename, if (err) {
"discard-alignment", "%u", dev_warn(dev-dev, "writing discard-secure (%d)", err);
q->limits.discard_alignment); return;
if (err) {
xenbus_dev_fatal(dev, err,
"writing discard-alignment");
goto kfree;
}
state = 1;
blkif->blk_backend_type = BLKIF_BACKEND_PHY;
}
/* Optional. */
err = xenbus_printf(xbt, dev->nodename,
"discard-secure", "%d",
blkif->vbd.discard_secure);
if (err) {
xenbus_dev_fatal(dev, err,
"writting discard-secure");
goto kfree;
}
} }
} else {
err = PTR_ERR(type);
xenbus_dev_fatal(dev, err, "reading type");
goto out;
} }
err = xenbus_printf(xbt, dev->nodename, "feature-discard", err = xenbus_printf(xbt, dev->nodename, "feature-discard",
"%d", state); "%d", state);
if (err) if (err)
xenbus_dev_fatal(dev, err, "writing feature-discard"); dev_warn(&dev->dev, "writing feature-discard (%d)", err);
kfree:
kfree(type);
out:
return err;
} }
int xen_blkbk_barrier(struct xenbus_transaction xbt, int xen_blkbk_barrier(struct xenbus_transaction xbt,
struct backend_info *be, int state) struct backend_info *be, int state)
...@@ -457,7 +434,7 @@ int xen_blkbk_barrier(struct xenbus_transaction xbt, ...@@ -457,7 +434,7 @@ int xen_blkbk_barrier(struct xenbus_transaction xbt,
err = xenbus_printf(xbt, dev->nodename, "feature-barrier", err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
"%d", state); "%d", state);
if (err) if (err)
xenbus_dev_fatal(dev, err, "writing feature-barrier"); dev_warn(&dev->dev, "writing feature-barrier (%d)", err);
return err; return err;
} }
...@@ -689,14 +666,12 @@ static void connect(struct backend_info *be) ...@@ -689,14 +666,12 @@ static void connect(struct backend_info *be)
return; return;
} }
err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); /* If we can't advertise it is OK. */
if (err) xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
goto abort;
err = xen_blkbk_discard(xbt, be); xen_blkbk_discard(xbt, be);
/* If we can't advertise it is OK. */ xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
(unsigned long long)vbd_sz(&be->blkif->vbd)); (unsigned long long)vbd_sz(&be->blkif->vbd));
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/bitmap.h>
#include <xen/xen.h> #include <xen/xen.h>
#include <xen/xenbus.h> #include <xen/xenbus.h>
...@@ -81,6 +82,7 @@ static const struct block_device_operations xlvbd_block_fops; ...@@ -81,6 +82,7 @@ static const struct block_device_operations xlvbd_block_fops;
*/ */
struct blkfront_info struct blkfront_info
{ {
spinlock_t io_lock;
struct mutex mutex; struct mutex mutex;
struct xenbus_device *xbdev; struct xenbus_device *xbdev;
struct gendisk *gd; struct gendisk *gd;
...@@ -105,8 +107,6 @@ struct blkfront_info ...@@ -105,8 +107,6 @@ struct blkfront_info
int is_ready; int is_ready;
}; };
static DEFINE_SPINLOCK(blkif_io_lock);
static unsigned int nr_minors; static unsigned int nr_minors;
static unsigned long *minors; static unsigned long *minors;
static DEFINE_SPINLOCK(minor_lock); static DEFINE_SPINLOCK(minor_lock);
...@@ -177,8 +177,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) ...@@ -177,8 +177,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr)
spin_lock(&minor_lock); spin_lock(&minor_lock);
if (find_next_bit(minors, end, minor) >= end) { if (find_next_bit(minors, end, minor) >= end) {
for (; minor < end; ++minor) bitmap_set(minors, minor, nr);
__set_bit(minor, minors);
rc = 0; rc = 0;
} else } else
rc = -EBUSY; rc = -EBUSY;
...@@ -193,8 +192,7 @@ static void xlbd_release_minors(unsigned int minor, unsigned int nr) ...@@ -193,8 +192,7 @@ static void xlbd_release_minors(unsigned int minor, unsigned int nr)
BUG_ON(end > nr_minors); BUG_ON(end > nr_minors);
spin_lock(&minor_lock); spin_lock(&minor_lock);
for (; minor < end; ++minor) bitmap_clear(minors, minor, nr);
__clear_bit(minor, minors);
spin_unlock(&minor_lock); spin_unlock(&minor_lock);
} }
...@@ -419,7 +417,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) ...@@ -419,7 +417,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
struct request_queue *rq; struct request_queue *rq;
struct blkfront_info *info = gd->private_data; struct blkfront_info *info = gd->private_data;
rq = blk_init_queue(do_blkif_request, &blkif_io_lock); rq = blk_init_queue(do_blkif_request, &info->io_lock);
if (rq == NULL) if (rq == NULL)
return -1; return -1;
...@@ -636,14 +634,14 @@ static void xlvbd_release_gendisk(struct blkfront_info *info) ...@@ -636,14 +634,14 @@ static void xlvbd_release_gendisk(struct blkfront_info *info)
if (info->rq == NULL) if (info->rq == NULL)
return; return;
spin_lock_irqsave(&blkif_io_lock, flags); spin_lock_irqsave(&info->io_lock, flags);
/* No more blkif_request(). */ /* No more blkif_request(). */
blk_stop_queue(info->rq); blk_stop_queue(info->rq);
/* No more gnttab callback work. */ /* No more gnttab callback work. */
gnttab_cancel_free_callback(&info->callback); gnttab_cancel_free_callback(&info->callback);
spin_unlock_irqrestore(&blkif_io_lock, flags); spin_unlock_irqrestore(&info->io_lock, flags);
/* Flush gnttab callback work. Must be done with no locks held. */ /* Flush gnttab callback work. Must be done with no locks held. */
flush_work_sync(&info->work); flush_work_sync(&info->work);
...@@ -675,16 +673,16 @@ static void blkif_restart_queue(struct work_struct *work) ...@@ -675,16 +673,16 @@ static void blkif_restart_queue(struct work_struct *work)
{ {
struct blkfront_info *info = container_of(work, struct blkfront_info, work); struct blkfront_info *info = container_of(work, struct blkfront_info, work);
spin_lock_irq(&blkif_io_lock); spin_lock_irq(&info->io_lock);
if (info->connected == BLKIF_STATE_CONNECTED) if (info->connected == BLKIF_STATE_CONNECTED)
kick_pending_request_queues(info); kick_pending_request_queues(info);
spin_unlock_irq(&blkif_io_lock); spin_unlock_irq(&info->io_lock);
} }
static void blkif_free(struct blkfront_info *info, int suspend) static void blkif_free(struct blkfront_info *info, int suspend)
{ {
/* Prevent new requests being issued until we fix things up. */ /* Prevent new requests being issued until we fix things up. */
spin_lock_irq(&blkif_io_lock); spin_lock_irq(&info->io_lock);
info->connected = suspend ? info->connected = suspend ?
BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
/* No more blkif_request(). */ /* No more blkif_request(). */
...@@ -692,7 +690,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) ...@@ -692,7 +690,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
blk_stop_queue(info->rq); blk_stop_queue(info->rq);
/* No more gnttab callback work. */ /* No more gnttab callback work. */
gnttab_cancel_free_callback(&info->callback); gnttab_cancel_free_callback(&info->callback);
spin_unlock_irq(&blkif_io_lock); spin_unlock_irq(&info->io_lock);
/* Flush gnttab callback work. Must be done with no locks held. */ /* Flush gnttab callback work. Must be done with no locks held. */
flush_work_sync(&info->work); flush_work_sync(&info->work);
...@@ -728,10 +726,10 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -728,10 +726,10 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
struct blkfront_info *info = (struct blkfront_info *)dev_id; struct blkfront_info *info = (struct blkfront_info *)dev_id;
int error; int error;
spin_lock_irqsave(&blkif_io_lock, flags); spin_lock_irqsave(&info->io_lock, flags);
if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
spin_unlock_irqrestore(&blkif_io_lock, flags); spin_unlock_irqrestore(&info->io_lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -816,7 +814,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -816,7 +814,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
kick_pending_request_queues(info); kick_pending_request_queues(info);
spin_unlock_irqrestore(&blkif_io_lock, flags); spin_unlock_irqrestore(&info->io_lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -991,6 +989,7 @@ static int blkfront_probe(struct xenbus_device *dev, ...@@ -991,6 +989,7 @@ static int blkfront_probe(struct xenbus_device *dev,
} }
mutex_init(&info->mutex); mutex_init(&info->mutex);
spin_lock_init(&info->io_lock);
info->xbdev = dev; info->xbdev = dev;
info->vdevice = vdevice; info->vdevice = vdevice;
info->connected = BLKIF_STATE_DISCONNECTED; info->connected = BLKIF_STATE_DISCONNECTED;
...@@ -1068,7 +1067,7 @@ static int blkif_recover(struct blkfront_info *info) ...@@ -1068,7 +1067,7 @@ static int blkif_recover(struct blkfront_info *info)
xenbus_switch_state(info->xbdev, XenbusStateConnected); xenbus_switch_state(info->xbdev, XenbusStateConnected);
spin_lock_irq(&blkif_io_lock); spin_lock_irq(&info->io_lock);
/* Now safe for us to use the shared ring */ /* Now safe for us to use the shared ring */
info->connected = BLKIF_STATE_CONNECTED; info->connected = BLKIF_STATE_CONNECTED;
...@@ -1079,7 +1078,7 @@ static int blkif_recover(struct blkfront_info *info) ...@@ -1079,7 +1078,7 @@ static int blkif_recover(struct blkfront_info *info)
/* Kick any other new requests queued since we resumed */ /* Kick any other new requests queued since we resumed */
kick_pending_request_queues(info); kick_pending_request_queues(info);
spin_unlock_irq(&blkif_io_lock); spin_unlock_irq(&info->io_lock);
return 0; return 0;
} }
...@@ -1277,10 +1276,10 @@ static void blkfront_connect(struct blkfront_info *info) ...@@ -1277,10 +1276,10 @@ static void blkfront_connect(struct blkfront_info *info)
xenbus_switch_state(info->xbdev, XenbusStateConnected); xenbus_switch_state(info->xbdev, XenbusStateConnected);
/* Kick pending requests. */ /* Kick pending requests. */
spin_lock_irq(&blkif_io_lock); spin_lock_irq(&info->io_lock);
info->connected = BLKIF_STATE_CONNECTED; info->connected = BLKIF_STATE_CONNECTED;
kick_pending_request_queues(info); kick_pending_request_queues(info);
spin_unlock_irq(&blkif_io_lock); spin_unlock_irq(&info->io_lock);
add_disk(info->gd); add_disk(info->gd);
...@@ -1410,7 +1409,6 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) ...@@ -1410,7 +1409,6 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
mutex_lock(&blkfront_mutex); mutex_lock(&blkfront_mutex);
bdev = bdget_disk(disk, 0); bdev = bdget_disk(disk, 0);
bdput(bdev);
if (bdev->bd_openers) if (bdev->bd_openers)
goto out; goto out;
...@@ -1441,6 +1439,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) ...@@ -1441,6 +1439,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
} }
out: out:
bdput(bdev);
mutex_unlock(&blkfront_mutex); mutex_unlock(&blkfront_mutex);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment