mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-17 20:54:10 +00:00
Merge branch 'for-4.2/drivers' of git://git.kernel.dk/linux-block
Pull block driver updates from Jens Axboe: "This contains: - a few race fixes for null_blk, from Akinobu Mita. - a series of fixes for mtip32xx, from Asai Thambi and Selvan Mani at Micron. - NVMe: * Fix for missing error return on allocation failure, from Axel Lin. * Code consolidation and cleanups from Christoph. * Memory barrier addition, syncing queue count and queue pointers. From Jon Derrick. * Various fixes from Keith, an addition to support user issue reset from sysfs or ioctl, and automatic namespace rescan. * Fix from Matias, avoiding losing some request flags when marking the request failfast. - small cleanups and sparse fixups for ps3vram. From Geert Uytterhoeven and Geoff Lavand. - s390/dasd dead code removal, from Jarod Wilson. - a set of fixes and optimizations for loop, from Ming Lei. - conversion to blkdev_reread_part() of loop, dasd, ndb. From Ming Lei. - updates to cciss. From Tomas Henzl" * 'for-4.2/drivers' of git://git.kernel.dk/linux-block: (44 commits) mtip32xx: Fix accessing freed memory block: nvme-scsi: Catch kcalloc failure NVMe: Fix IO for extended metadata formats nvme: don't overwrite req->cmd_flags on sync cmd mtip32xx: increase wait time for hba reset mtip32xx: fix minor number mtip32xx: remove unnecessary sleep in mtip_ftl_rebuild_poll() mtip32xx: fix crash on surprise removal of the drive mtip32xx: Abort I/O during secure erase operation mtip32xx: fix incorrectly setting MTIP_DDF_SEC_LOCK_BIT mtip32xx: remove unused variable 'port->allocated' mtip32xx: fix rmmod issue MAINTAINERS: Update ps3vram block driver block/ps3vram: Remove obsolete reference to MTD block/ps3vram: Fix sparse warnings NVMe: Automatic namespace rescan NVMe: Memory barrier before queue_count is incremented NVMe: add sysfs and ioctl controller reset null_blk: restart request processing on completion handler null_blk: prevent timer handler running on a different CPU where started ...
This commit is contained in:
commit
6a398a3ef4
13 changed files with 993 additions and 1492 deletions
|
@ -7982,6 +7982,7 @@ F: sound/ppc/snd_ps3*
|
||||||
|
|
||||||
PS3VRAM DRIVER
|
PS3VRAM DRIVER
|
||||||
M: Jim Paris <jim@jtan.com>
|
M: Jim Paris <jim@jtan.com>
|
||||||
|
M: Geoff Levand <geoff@infradead.org>
|
||||||
L: linuxppc-dev@lists.ozlabs.org
|
L: linuxppc-dev@lists.ozlabs.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/block/ps3vram.c
|
F: drivers/block/ps3vram.c
|
||||||
|
|
|
@ -86,8 +86,6 @@ static DEFINE_MUTEX(loop_index_mutex);
|
||||||
static int max_part;
|
static int max_part;
|
||||||
static int part_shift;
|
static int part_shift;
|
||||||
|
|
||||||
static struct workqueue_struct *loop_wq;
|
|
||||||
|
|
||||||
static int transfer_xor(struct loop_device *lo, int cmd,
|
static int transfer_xor(struct loop_device *lo, int cmd,
|
||||||
struct page *raw_page, unsigned raw_off,
|
struct page *raw_page, unsigned raw_off,
|
||||||
struct page *loop_page, unsigned loop_off,
|
struct page *loop_page, unsigned loop_off,
|
||||||
|
@ -476,6 +474,28 @@ static int loop_flush(struct loop_device *lo)
|
||||||
return loop_switch(lo, NULL);
|
return loop_switch(lo, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void loop_reread_partitions(struct loop_device *lo,
|
||||||
|
struct block_device *bdev)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bd_mutex has been held already in release path, so don't
|
||||||
|
* acquire it if this function is called in such case.
|
||||||
|
*
|
||||||
|
* If the reread partition isn't from release path, lo_refcnt
|
||||||
|
* must be at least one and it can only become zero when the
|
||||||
|
* current holder is released.
|
||||||
|
*/
|
||||||
|
if (!atomic_read(&lo->lo_refcnt))
|
||||||
|
rc = __blkdev_reread_part(bdev);
|
||||||
|
else
|
||||||
|
rc = blkdev_reread_part(bdev);
|
||||||
|
if (rc)
|
||||||
|
pr_warn("%s: partition scan of loop%d (%s) failed (rc=%d)\n",
|
||||||
|
__func__, lo->lo_number, lo->lo_file_name, rc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* loop_change_fd switched the backing store of a loopback device to
|
* loop_change_fd switched the backing store of a loopback device to
|
||||||
* a new file. This is useful for operating system installers to free up
|
* a new file. This is useful for operating system installers to free up
|
||||||
|
@ -524,7 +544,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
||||||
|
|
||||||
fput(old_file);
|
fput(old_file);
|
||||||
if (lo->lo_flags & LO_FLAGS_PARTSCAN)
|
if (lo->lo_flags & LO_FLAGS_PARTSCAN)
|
||||||
ioctl_by_bdev(bdev, BLKRRPART, 0);
|
loop_reread_partitions(lo, bdev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_putf:
|
out_putf:
|
||||||
|
@ -725,6 +745,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
||||||
size = get_loop_size(lo, file);
|
size = get_loop_size(lo, file);
|
||||||
if ((loff_t)(sector_t)size != size)
|
if ((loff_t)(sector_t)size != size)
|
||||||
goto out_putf;
|
goto out_putf;
|
||||||
|
error = -ENOMEM;
|
||||||
|
lo->wq = alloc_workqueue("kloopd%d",
|
||||||
|
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16,
|
||||||
|
lo->lo_number);
|
||||||
|
if (!lo->wq)
|
||||||
|
goto out_putf;
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
|
@ -755,7 +781,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
||||||
if (part_shift)
|
if (part_shift)
|
||||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||||
if (lo->lo_flags & LO_FLAGS_PARTSCAN)
|
if (lo->lo_flags & LO_FLAGS_PARTSCAN)
|
||||||
ioctl_by_bdev(bdev, BLKRRPART, 0);
|
loop_reread_partitions(lo, bdev);
|
||||||
|
|
||||||
/* Grab the block_device to prevent its destruction after we
|
/* Grab the block_device to prevent its destruction after we
|
||||||
* put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
|
* put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
|
||||||
|
@ -827,7 +853,7 @@ static int loop_clr_fd(struct loop_device *lo)
|
||||||
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
|
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
|
||||||
* command to fail with EBUSY.
|
* command to fail with EBUSY.
|
||||||
*/
|
*/
|
||||||
if (lo->lo_refcnt > 1) {
|
if (atomic_read(&lo->lo_refcnt) > 1) {
|
||||||
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
|
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
mutex_unlock(&lo->lo_ctl_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -836,6 +862,9 @@ static int loop_clr_fd(struct loop_device *lo)
|
||||||
if (filp == NULL)
|
if (filp == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* freeze request queue during the transition */
|
||||||
|
blk_mq_freeze_queue(lo->lo_queue);
|
||||||
|
|
||||||
spin_lock_irq(&lo->lo_lock);
|
spin_lock_irq(&lo->lo_lock);
|
||||||
lo->lo_state = Lo_rundown;
|
lo->lo_state = Lo_rundown;
|
||||||
lo->lo_backing_file = NULL;
|
lo->lo_backing_file = NULL;
|
||||||
|
@ -867,11 +896,15 @@ static int loop_clr_fd(struct loop_device *lo)
|
||||||
lo->lo_state = Lo_unbound;
|
lo->lo_state = Lo_unbound;
|
||||||
/* This is safe: open() is still holding a reference. */
|
/* This is safe: open() is still holding a reference. */
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
|
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||||
|
|
||||||
if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
|
if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
|
||||||
ioctl_by_bdev(bdev, BLKRRPART, 0);
|
loop_reread_partitions(lo, bdev);
|
||||||
lo->lo_flags = 0;
|
lo->lo_flags = 0;
|
||||||
if (!part_shift)
|
if (!part_shift)
|
||||||
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
|
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
|
||||||
|
destroy_workqueue(lo->wq);
|
||||||
|
lo->wq = NULL;
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
mutex_unlock(&lo->lo_ctl_mutex);
|
||||||
/*
|
/*
|
||||||
* Need not hold lo_ctl_mutex to fput backing file.
|
* Need not hold lo_ctl_mutex to fput backing file.
|
||||||
|
@ -943,7 +976,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||||
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
|
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
|
||||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
||||||
ioctl_by_bdev(lo->lo_device, BLKRRPART, 0);
|
loop_reread_partitions(lo, lo->lo_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
||||||
|
@ -1324,9 +1357,7 @@ static int lo_open(struct block_device *bdev, fmode_t mode)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&lo->lo_ctl_mutex);
|
atomic_inc(&lo->lo_refcnt);
|
||||||
lo->lo_refcnt++;
|
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&loop_index_mutex);
|
mutex_unlock(&loop_index_mutex);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1337,11 +1368,10 @@ static void lo_release(struct gendisk *disk, fmode_t mode)
|
||||||
struct loop_device *lo = disk->private_data;
|
struct loop_device *lo = disk->private_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (atomic_dec_return(&lo->lo_refcnt))
|
||||||
|
return;
|
||||||
|
|
||||||
mutex_lock(&lo->lo_ctl_mutex);
|
mutex_lock(&lo->lo_ctl_mutex);
|
||||||
|
|
||||||
if (--lo->lo_refcnt)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
|
if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
|
||||||
/*
|
/*
|
||||||
* In autoclear mode, stop the loop thread
|
* In autoclear mode, stop the loop thread
|
||||||
|
@ -1358,7 +1388,6 @@ static void lo_release(struct gendisk *disk, fmode_t mode)
|
||||||
loop_flush(lo);
|
loop_flush(lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
mutex_unlock(&lo->lo_ctl_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,9 +1454,13 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
const struct blk_mq_queue_data *bd)
|
const struct blk_mq_queue_data *bd)
|
||||||
{
|
{
|
||||||
struct loop_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
|
struct loop_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
|
||||||
|
struct loop_device *lo = cmd->rq->q->queuedata;
|
||||||
|
|
||||||
blk_mq_start_request(bd->rq);
|
blk_mq_start_request(bd->rq);
|
||||||
|
|
||||||
|
if (lo->lo_state != Lo_bound)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
if (cmd->rq->cmd_flags & REQ_WRITE) {
|
if (cmd->rq->cmd_flags & REQ_WRITE) {
|
||||||
struct loop_device *lo = cmd->rq->q->queuedata;
|
struct loop_device *lo = cmd->rq->q->queuedata;
|
||||||
bool need_sched = true;
|
bool need_sched = true;
|
||||||
|
@ -1441,9 +1474,9 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
spin_unlock_irq(&lo->lo_lock);
|
spin_unlock_irq(&lo->lo_lock);
|
||||||
|
|
||||||
if (need_sched)
|
if (need_sched)
|
||||||
queue_work(loop_wq, &lo->write_work);
|
queue_work(lo->wq, &lo->write_work);
|
||||||
} else {
|
} else {
|
||||||
queue_work(loop_wq, &cmd->read_work);
|
queue_work(lo->wq, &cmd->read_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLK_MQ_RQ_QUEUE_OK;
|
return BLK_MQ_RQ_QUEUE_OK;
|
||||||
|
@ -1455,9 +1488,6 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
|
||||||
struct loop_device *lo = cmd->rq->q->queuedata;
|
struct loop_device *lo = cmd->rq->q->queuedata;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
|
||||||
if (lo->lo_state != Lo_bound)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY))
|
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
@ -1594,6 +1624,7 @@ static int loop_add(struct loop_device **l, int i)
|
||||||
disk->flags |= GENHD_FL_NO_PART_SCAN;
|
disk->flags |= GENHD_FL_NO_PART_SCAN;
|
||||||
disk->flags |= GENHD_FL_EXT_DEVT;
|
disk->flags |= GENHD_FL_EXT_DEVT;
|
||||||
mutex_init(&lo->lo_ctl_mutex);
|
mutex_init(&lo->lo_ctl_mutex);
|
||||||
|
atomic_set(&lo->lo_refcnt, 0);
|
||||||
lo->lo_number = i;
|
lo->lo_number = i;
|
||||||
spin_lock_init(&lo->lo_lock);
|
spin_lock_init(&lo->lo_lock);
|
||||||
disk->major = LOOP_MAJOR;
|
disk->major = LOOP_MAJOR;
|
||||||
|
@ -1711,7 +1742,7 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
mutex_unlock(&lo->lo_ctl_mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (lo->lo_refcnt > 0) {
|
if (atomic_read(&lo->lo_refcnt) > 0) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
mutex_unlock(&lo->lo_ctl_mutex);
|
mutex_unlock(&lo->lo_ctl_mutex);
|
||||||
break;
|
break;
|
||||||
|
@ -1806,13 +1837,6 @@ static int __init loop_init(void)
|
||||||
goto misc_out;
|
goto misc_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop_wq = alloc_workqueue("kloopd",
|
|
||||||
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);
|
|
||||||
if (!loop_wq) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto misc_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
|
blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
|
||||||
THIS_MODULE, loop_probe, NULL, NULL);
|
THIS_MODULE, loop_probe, NULL, NULL);
|
||||||
|
|
||||||
|
@ -1850,8 +1874,6 @@ static void __exit loop_exit(void)
|
||||||
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
|
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
|
||||||
unregister_blkdev(LOOP_MAJOR, "loop");
|
unregister_blkdev(LOOP_MAJOR, "loop");
|
||||||
|
|
||||||
destroy_workqueue(loop_wq);
|
|
||||||
|
|
||||||
misc_deregister(&loop_misc);
|
misc_deregister(&loop_misc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct loop_func_table;
|
||||||
|
|
||||||
struct loop_device {
|
struct loop_device {
|
||||||
int lo_number;
|
int lo_number;
|
||||||
int lo_refcnt;
|
atomic_t lo_refcnt;
|
||||||
loff_t lo_offset;
|
loff_t lo_offset;
|
||||||
loff_t lo_sizelimit;
|
loff_t lo_sizelimit;
|
||||||
int lo_flags;
|
int lo_flags;
|
||||||
|
@ -54,6 +54,7 @@ struct loop_device {
|
||||||
gfp_t old_gfp_mask;
|
gfp_t old_gfp_mask;
|
||||||
|
|
||||||
spinlock_t lo_lock;
|
spinlock_t lo_lock;
|
||||||
|
struct workqueue_struct *wq;
|
||||||
struct list_head write_cmd_head;
|
struct list_head write_cmd_head;
|
||||||
struct work_struct write_work;
|
struct work_struct write_work;
|
||||||
bool write_started;
|
bool write_started;
|
||||||
|
|
|
@ -163,12 +163,6 @@ static bool mtip_check_surprise_removal(struct pci_dev *pdev)
|
||||||
else
|
else
|
||||||
dev_warn(&dd->pdev->dev,
|
dev_warn(&dd->pdev->dev,
|
||||||
"%s: dd->queue is NULL\n", __func__);
|
"%s: dd->queue is NULL\n", __func__);
|
||||||
if (dd->port) {
|
|
||||||
set_bit(MTIP_PF_SR_CLEANUP_BIT, &dd->port->flags);
|
|
||||||
wake_up_interruptible(&dd->port->svc_wait);
|
|
||||||
} else
|
|
||||||
dev_warn(&dd->pdev->dev,
|
|
||||||
"%s: dd->port is NULL\n", __func__);
|
|
||||||
return true; /* device removed */
|
return true; /* device removed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,8 +263,11 @@ static int mtip_hba_reset(struct driver_data *dd)
|
||||||
/* Flush */
|
/* Flush */
|
||||||
readl(dd->mmio + HOST_CTL);
|
readl(dd->mmio + HOST_CTL);
|
||||||
|
|
||||||
/* Spin for up to 2 seconds, waiting for reset acknowledgement */
|
/*
|
||||||
timeout = jiffies + msecs_to_jiffies(2000);
|
* Spin for up to 10 seconds waiting for reset acknowledgement. Spec
|
||||||
|
* is 1 sec but in LUN failure conditions, up to 10 secs are required
|
||||||
|
*/
|
||||||
|
timeout = jiffies + msecs_to_jiffies(10000);
|
||||||
do {
|
do {
|
||||||
mdelay(10);
|
mdelay(10);
|
||||||
if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
|
if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
|
||||||
|
@ -623,8 +620,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
||||||
|
|
||||||
set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||||
|
|
||||||
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) &&
|
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
|
||||||
test_bit(MTIP_TAG_INTERNAL, port->allocated)) {
|
|
||||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||||
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
|
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
|
||||||
|
|
||||||
|
@ -896,6 +892,10 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
|
||||||
|
|
||||||
/* Acknowledge the interrupt status on the port.*/
|
/* Acknowledge the interrupt status on the port.*/
|
||||||
port_stat = readl(port->mmio + PORT_IRQ_STAT);
|
port_stat = readl(port->mmio + PORT_IRQ_STAT);
|
||||||
|
if (unlikely(port_stat == 0xFFFFFFFF)) {
|
||||||
|
mtip_check_surprise_removal(dd->pdev);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
writel(port_stat, port->mmio + PORT_IRQ_STAT);
|
writel(port_stat, port->mmio + PORT_IRQ_STAT);
|
||||||
|
|
||||||
/* Demux port status */
|
/* Demux port status */
|
||||||
|
@ -991,15 +991,10 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
||||||
reply = port->rxfis + RX_FIS_D2H_REG;
|
reply = port->rxfis + RX_FIS_D2H_REG;
|
||||||
task_file_data = readl(port->mmio+PORT_TFDATA);
|
task_file_data = readl(port->mmio+PORT_TFDATA);
|
||||||
|
|
||||||
if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
|
|
||||||
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
|
||||||
|
|
||||||
if ((task_file_data & 1))
|
if ((task_file_data & 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
|
if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
|
||||||
set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
|
||||||
set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
|
||||||
port->ic_pause_timer = jiffies;
|
port->ic_pause_timer = jiffies;
|
||||||
return true;
|
return true;
|
||||||
} else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
|
} else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
|
||||||
|
@ -1011,8 +1006,10 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
||||||
((fis->command == 0xFC) &&
|
((fis->command == 0xFC) &&
|
||||||
(fis->features == 0x27 || fis->features == 0x72 ||
|
(fis->features == 0x27 || fis->features == 0x72 ||
|
||||||
fis->features == 0x62 || fis->features == 0x26))) {
|
fis->features == 0x62 || fis->features == 0x26))) {
|
||||||
|
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
||||||
/* Com reset after secure erase or lowlevel format */
|
/* Com reset after secure erase or lowlevel format */
|
||||||
mtip_restart_port(port);
|
mtip_restart_port(port);
|
||||||
|
clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,9 +1109,10 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||||
int_cmd = mtip_get_int_command(dd);
|
int_cmd = mtip_get_int_command(dd);
|
||||||
|
|
||||||
set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
||||||
port->ic_pause_timer = 0;
|
|
||||||
|
|
||||||
clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
if (fis->command == ATA_CMD_SEC_ERASE_PREP)
|
||||||
|
set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
||||||
|
|
||||||
clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
|
clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
|
||||||
|
|
||||||
if (atomic == GFP_KERNEL) {
|
if (atomic == GFP_KERNEL) {
|
||||||
|
@ -1251,11 +1249,11 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
||||||
exec_ic_exit:
|
exec_ic_exit:
|
||||||
/* Clear the allocated and active bits for the internal command. */
|
/* Clear the allocated and active bits for the internal command. */
|
||||||
mtip_put_int_command(dd, int_cmd);
|
mtip_put_int_command(dd, int_cmd);
|
||||||
|
clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
||||||
if (rv >= 0 && mtip_pause_ncq(port, fis)) {
|
if (rv >= 0 && mtip_pause_ncq(port, fis)) {
|
||||||
/* NCQ paused */
|
/* NCQ paused */
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
|
||||||
wake_up_interruptible(&port->svc_wait);
|
wake_up_interruptible(&port->svc_wait);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -2625,18 +2623,6 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
|
||||||
readl(dd->mmio + HOST_IRQ_STAT));
|
readl(dd->mmio + HOST_IRQ_STAT));
|
||||||
size += sprintf(&buf[size], "\n");
|
size += sprintf(&buf[size], "\n");
|
||||||
|
|
||||||
size += sprintf(&buf[size], "L/ Allocated : [ 0x");
|
|
||||||
|
|
||||||
for (n = dd->slot_groups-1; n >= 0; n--) {
|
|
||||||
if (sizeof(long) > sizeof(u32))
|
|
||||||
group_allocated =
|
|
||||||
dd->port->allocated[n/2] >> (32*(n&1));
|
|
||||||
else
|
|
||||||
group_allocated = dd->port->allocated[n];
|
|
||||||
size += sprintf(&buf[size], "%08X ", group_allocated);
|
|
||||||
}
|
|
||||||
size += sprintf(&buf[size], "]\n");
|
|
||||||
|
|
||||||
size += sprintf(&buf[size], "L/ Commands in Q : [ 0x");
|
size += sprintf(&buf[size], "L/ Commands in Q : [ 0x");
|
||||||
|
|
||||||
for (n = dd->slot_groups-1; n >= 0; n--) {
|
for (n = dd->slot_groups-1; n >= 0; n--) {
|
||||||
|
@ -2780,48 +2766,6 @@ static void mtip_hw_debugfs_exit(struct driver_data *dd)
|
||||||
debugfs_remove_recursive(dd->dfs_node);
|
debugfs_remove_recursive(dd->dfs_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtip_free_orphan(struct driver_data *dd)
|
|
||||||
{
|
|
||||||
struct kobject *kobj;
|
|
||||||
|
|
||||||
if (dd->bdev) {
|
|
||||||
if (dd->bdev->bd_holders >= 1)
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
bdput(dd->bdev);
|
|
||||||
dd->bdev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mtip_hw_debugfs_exit(dd);
|
|
||||||
|
|
||||||
spin_lock(&rssd_index_lock);
|
|
||||||
ida_remove(&rssd_index_ida, dd->index);
|
|
||||||
spin_unlock(&rssd_index_lock);
|
|
||||||
|
|
||||||
if (!test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag) &&
|
|
||||||
test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) {
|
|
||||||
put_disk(dd->disk);
|
|
||||||
} else {
|
|
||||||
if (dd->disk) {
|
|
||||||
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
|
|
||||||
if (kobj) {
|
|
||||||
mtip_hw_sysfs_exit(dd, kobj);
|
|
||||||
kobject_put(kobj);
|
|
||||||
}
|
|
||||||
del_gendisk(dd->disk);
|
|
||||||
dd->disk = NULL;
|
|
||||||
}
|
|
||||||
if (dd->queue) {
|
|
||||||
dd->queue->queuedata = NULL;
|
|
||||||
blk_cleanup_queue(dd->queue);
|
|
||||||
blk_mq_free_tag_set(&dd->tags);
|
|
||||||
dd->queue = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree(dd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform any init/resume time hardware setup
|
* Perform any init/resume time hardware setup
|
||||||
*
|
*
|
||||||
|
@ -2944,7 +2888,6 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
||||||
mtip_block_initialize(dd);
|
mtip_block_initialize(dd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ssleep(10);
|
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
|
||||||
/* Check for timeout */
|
/* Check for timeout */
|
||||||
|
@ -2969,7 +2912,6 @@ static int mtip_service_thread(void *data)
|
||||||
unsigned long slot, slot_start, slot_wrap;
|
unsigned long slot, slot_start, slot_wrap;
|
||||||
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
||||||
struct mtip_port *port = dd->port;
|
struct mtip_port *port = dd->port;
|
||||||
int ret;
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (kthread_should_stop() ||
|
if (kthread_should_stop() ||
|
||||||
|
@ -2990,10 +2932,6 @@ static int mtip_service_thread(void *data)
|
||||||
test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
|
test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
|
||||||
goto st_out;
|
goto st_out;
|
||||||
|
|
||||||
/* If I am an orphan, start self cleanup */
|
|
||||||
if (test_bit(MTIP_PF_SR_CLEANUP_BIT, &port->flags))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
|
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
|
||||||
&dd->dd_flag)))
|
&dd->dd_flag)))
|
||||||
goto st_out;
|
goto st_out;
|
||||||
|
@ -3047,26 +2985,6 @@ restart_eh:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for pci remove to exit */
|
|
||||||
while (1) {
|
|
||||||
if (test_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag))
|
|
||||||
break;
|
|
||||||
msleep_interruptible(1000);
|
|
||||||
if (kthread_should_stop())
|
|
||||||
goto st_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
ret = mtip_free_orphan(dd);
|
|
||||||
if (!ret) {
|
|
||||||
/* NOTE: All data structures are invalid, do not
|
|
||||||
* access any here */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
msleep_interruptible(1000);
|
|
||||||
if (kthread_should_stop())
|
|
||||||
goto st_out;
|
|
||||||
}
|
|
||||||
st_out:
|
st_out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3394,6 +3312,7 @@ static int mtip_hw_exit(struct driver_data *dd)
|
||||||
/* Release the IRQ. */
|
/* Release the IRQ. */
|
||||||
irq_set_affinity_hint(dd->pdev->irq, NULL);
|
irq_set_affinity_hint(dd->pdev->irq, NULL);
|
||||||
devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
|
devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
|
||||||
|
msleep(1000);
|
||||||
|
|
||||||
/* Free dma regions */
|
/* Free dma regions */
|
||||||
mtip_dma_free(dd);
|
mtip_dma_free(dd);
|
||||||
|
@ -3699,6 +3618,26 @@ static const struct block_device_operations mtip_block_ops = {
|
||||||
.owner = THIS_MODULE
|
.owner = THIS_MODULE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline bool is_se_active(struct driver_data *dd)
|
||||||
|
{
|
||||||
|
if (unlikely(test_bit(MTIP_PF_SE_ACTIVE_BIT, &dd->port->flags))) {
|
||||||
|
if (dd->port->ic_pause_timer) {
|
||||||
|
unsigned long to = dd->port->ic_pause_timer +
|
||||||
|
msecs_to_jiffies(1000);
|
||||||
|
if (time_after(jiffies, to)) {
|
||||||
|
clear_bit(MTIP_PF_SE_ACTIVE_BIT,
|
||||||
|
&dd->port->flags);
|
||||||
|
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
|
||||||
|
dd->port->ic_pause_timer = 0;
|
||||||
|
wake_up_interruptible(&dd->port->svc_wait);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Block layer make request function.
|
* Block layer make request function.
|
||||||
*
|
*
|
||||||
|
@ -3716,6 +3655,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq)
|
||||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||||
unsigned int nents;
|
unsigned int nents;
|
||||||
|
|
||||||
|
if (is_se_active(dd))
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
|
if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
|
||||||
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
|
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
|
||||||
&dd->dd_flag))) {
|
&dd->dd_flag))) {
|
||||||
|
@ -3900,7 +3842,8 @@ static int mtip_block_initialize(struct driver_data *dd)
|
||||||
|
|
||||||
dd->disk->driverfs_dev = &dd->pdev->dev;
|
dd->disk->driverfs_dev = &dd->pdev->dev;
|
||||||
dd->disk->major = dd->major;
|
dd->disk->major = dd->major;
|
||||||
dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS;
|
dd->disk->first_minor = index * MTIP_MAX_MINORS;
|
||||||
|
dd->disk->minors = MTIP_MAX_MINORS;
|
||||||
dd->disk->fops = &mtip_block_ops;
|
dd->disk->fops = &mtip_block_ops;
|
||||||
dd->disk->private_data = dd;
|
dd->disk->private_data = dd;
|
||||||
dd->index = index;
|
dd->index = index;
|
||||||
|
@ -4066,52 +4009,51 @@ static int mtip_block_remove(struct driver_data *dd)
|
||||||
{
|
{
|
||||||
struct kobject *kobj;
|
struct kobject *kobj;
|
||||||
|
|
||||||
if (!dd->sr) {
|
mtip_hw_debugfs_exit(dd);
|
||||||
mtip_hw_debugfs_exit(dd);
|
|
||||||
|
|
||||||
if (dd->mtip_svc_handler) {
|
if (dd->mtip_svc_handler) {
|
||||||
set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
|
set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
|
||||||
wake_up_interruptible(&dd->port->svc_wait);
|
wake_up_interruptible(&dd->port->svc_wait);
|
||||||
kthread_stop(dd->mtip_svc_handler);
|
kthread_stop(dd->mtip_svc_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the sysfs attributes, if created */
|
/* Clean up the sysfs attributes, if created */
|
||||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
|
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
|
||||||
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
|
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
|
||||||
if (kobj) {
|
if (kobj) {
|
||||||
mtip_hw_sysfs_exit(dd, kobj);
|
mtip_hw_sysfs_exit(dd, kobj);
|
||||||
kobject_put(kobj);
|
kobject_put(kobj);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dd->sr)
|
||||||
mtip_standby_drive(dd);
|
mtip_standby_drive(dd);
|
||||||
|
else
|
||||||
/*
|
|
||||||
* Delete our gendisk structure. This also removes the device
|
|
||||||
* from /dev
|
|
||||||
*/
|
|
||||||
if (dd->bdev) {
|
|
||||||
bdput(dd->bdev);
|
|
||||||
dd->bdev = NULL;
|
|
||||||
}
|
|
||||||
if (dd->disk) {
|
|
||||||
if (dd->disk->queue) {
|
|
||||||
del_gendisk(dd->disk);
|
|
||||||
blk_cleanup_queue(dd->queue);
|
|
||||||
blk_mq_free_tag_set(&dd->tags);
|
|
||||||
dd->queue = NULL;
|
|
||||||
} else
|
|
||||||
put_disk(dd->disk);
|
|
||||||
}
|
|
||||||
dd->disk = NULL;
|
|
||||||
|
|
||||||
spin_lock(&rssd_index_lock);
|
|
||||||
ida_remove(&rssd_index_ida, dd->index);
|
|
||||||
spin_unlock(&rssd_index_lock);
|
|
||||||
} else {
|
|
||||||
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
||||||
dd->disk->disk_name);
|
dd->disk->disk_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete our gendisk structure. This also removes the device
|
||||||
|
* from /dev
|
||||||
|
*/
|
||||||
|
if (dd->bdev) {
|
||||||
|
bdput(dd->bdev);
|
||||||
|
dd->bdev = NULL;
|
||||||
}
|
}
|
||||||
|
if (dd->disk) {
|
||||||
|
del_gendisk(dd->disk);
|
||||||
|
if (dd->disk->queue) {
|
||||||
|
blk_cleanup_queue(dd->queue);
|
||||||
|
blk_mq_free_tag_set(&dd->tags);
|
||||||
|
dd->queue = NULL;
|
||||||
|
}
|
||||||
|
put_disk(dd->disk);
|
||||||
|
}
|
||||||
|
dd->disk = NULL;
|
||||||
|
|
||||||
|
spin_lock(&rssd_index_lock);
|
||||||
|
ida_remove(&rssd_index_ida, dd->index);
|
||||||
|
spin_unlock(&rssd_index_lock);
|
||||||
|
|
||||||
/* De-initialize the protocol layer. */
|
/* De-initialize the protocol layer. */
|
||||||
mtip_hw_exit(dd);
|
mtip_hw_exit(dd);
|
||||||
|
@ -4140,12 +4082,12 @@ static int mtip_block_shutdown(struct driver_data *dd)
|
||||||
dev_info(&dd->pdev->dev,
|
dev_info(&dd->pdev->dev,
|
||||||
"Shutting down %s ...\n", dd->disk->disk_name);
|
"Shutting down %s ...\n", dd->disk->disk_name);
|
||||||
|
|
||||||
|
del_gendisk(dd->disk);
|
||||||
if (dd->disk->queue) {
|
if (dd->disk->queue) {
|
||||||
del_gendisk(dd->disk);
|
|
||||||
blk_cleanup_queue(dd->queue);
|
blk_cleanup_queue(dd->queue);
|
||||||
blk_mq_free_tag_set(&dd->tags);
|
blk_mq_free_tag_set(&dd->tags);
|
||||||
} else
|
}
|
||||||
put_disk(dd->disk);
|
put_disk(dd->disk);
|
||||||
dd->disk = NULL;
|
dd->disk = NULL;
|
||||||
dd->queue = NULL;
|
dd->queue = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4507,6 +4449,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||||
"Completion workers still active!\n");
|
"Completion workers still active!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blk_mq_stop_hw_queues(dd->queue);
|
||||||
/* Clean up the block layer. */
|
/* Clean up the block layer. */
|
||||||
mtip_block_remove(dd);
|
mtip_block_remove(dd);
|
||||||
|
|
||||||
|
@ -4524,10 +4467,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
||||||
list_del_init(&dd->remove_list);
|
list_del_init(&dd->remove_list);
|
||||||
spin_unlock_irqrestore(&dev_lock, flags);
|
spin_unlock_irqrestore(&dev_lock, flags);
|
||||||
|
|
||||||
if (!dd->sr)
|
kfree(dd);
|
||||||
kfree(dd);
|
|
||||||
else
|
|
||||||
set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
|
|
||||||
|
|
||||||
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
|
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
|
|
|
@ -142,7 +142,6 @@ enum {
|
||||||
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
|
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
|
||||||
MTIP_PF_ISSUE_CMDS_BIT = 5,
|
MTIP_PF_ISSUE_CMDS_BIT = 5,
|
||||||
MTIP_PF_REBUILD_BIT = 6,
|
MTIP_PF_REBUILD_BIT = 6,
|
||||||
MTIP_PF_SR_CLEANUP_BIT = 7,
|
|
||||||
MTIP_PF_SVC_THD_STOP_BIT = 8,
|
MTIP_PF_SVC_THD_STOP_BIT = 8,
|
||||||
|
|
||||||
/* below are bit numbers in 'dd_flag' defined in driver_data */
|
/* below are bit numbers in 'dd_flag' defined in driver_data */
|
||||||
|
@ -150,7 +149,6 @@ enum {
|
||||||
MTIP_DDF_REMOVE_PENDING_BIT = 1,
|
MTIP_DDF_REMOVE_PENDING_BIT = 1,
|
||||||
MTIP_DDF_OVER_TEMP_BIT = 2,
|
MTIP_DDF_OVER_TEMP_BIT = 2,
|
||||||
MTIP_DDF_WRITE_PROTECT_BIT = 3,
|
MTIP_DDF_WRITE_PROTECT_BIT = 3,
|
||||||
MTIP_DDF_REMOVE_DONE_BIT = 4,
|
|
||||||
MTIP_DDF_CLEANUP_BIT = 5,
|
MTIP_DDF_CLEANUP_BIT = 5,
|
||||||
MTIP_DDF_RESUME_BIT = 6,
|
MTIP_DDF_RESUME_BIT = 6,
|
||||||
MTIP_DDF_INIT_DONE_BIT = 7,
|
MTIP_DDF_INIT_DONE_BIT = 7,
|
||||||
|
@ -412,19 +410,13 @@ struct mtip_port {
|
||||||
* by the DMA when the driver issues internal commands.
|
* by the DMA when the driver issues internal commands.
|
||||||
*/
|
*/
|
||||||
dma_addr_t sector_buffer_dma;
|
dma_addr_t sector_buffer_dma;
|
||||||
/*
|
|
||||||
* Bit significant, used to determine if a command slot has
|
|
||||||
* been allocated. i.e. the slot is in use. Bits are cleared
|
|
||||||
* when the command slot and all associated data structures
|
|
||||||
* are no longer needed.
|
|
||||||
*/
|
|
||||||
u16 *log_buf;
|
u16 *log_buf;
|
||||||
dma_addr_t log_buf_dma;
|
dma_addr_t log_buf_dma;
|
||||||
|
|
||||||
u8 *smart_buf;
|
u8 *smart_buf;
|
||||||
dma_addr_t smart_buf_dma;
|
dma_addr_t smart_buf_dma;
|
||||||
|
|
||||||
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
|
||||||
* or error handling is active
|
* or error handling is active
|
||||||
|
|
|
@ -711,7 +711,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||||
bdev->bd_inode->i_size = 0;
|
bdev->bd_inode->i_size = 0;
|
||||||
set_capacity(nbd->disk, 0);
|
set_capacity(nbd->disk, 0);
|
||||||
if (max_part > 0)
|
if (max_part > 0)
|
||||||
ioctl_by_bdev(bdev, BLKRRPART, 0);
|
blkdev_reread_part(bdev);
|
||||||
if (nbd->disconnect) /* user requested, ignore socket errors */
|
if (nbd->disconnect) /* user requested, ignore socket errors */
|
||||||
return 0;
|
return 0;
|
||||||
return nbd->harderror;
|
return nbd->harderror;
|
||||||
|
|
|
@ -243,6 +243,17 @@ static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
|
||||||
cmd = container_of(entry, struct nullb_cmd, ll_list);
|
cmd = container_of(entry, struct nullb_cmd, ll_list);
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
end_cmd(cmd);
|
end_cmd(cmd);
|
||||||
|
|
||||||
|
if (cmd->rq) {
|
||||||
|
struct request_queue *q = cmd->rq->q;
|
||||||
|
|
||||||
|
if (!q->mq_ops && blk_queue_stopped(q)) {
|
||||||
|
spin_lock(q->queue_lock);
|
||||||
|
if (blk_queue_stopped(q))
|
||||||
|
blk_start_queue(q);
|
||||||
|
spin_unlock(q->queue_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
} while (entry);
|
} while (entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +268,7 @@ static void null_cmd_end_timer(struct nullb_cmd *cmd)
|
||||||
if (llist_add(&cmd->ll_list, &cq->list)) {
|
if (llist_add(&cmd->ll_list, &cq->list)) {
|
||||||
ktime_t kt = ktime_set(0, completion_nsec);
|
ktime_t kt = ktime_set(0, completion_nsec);
|
||||||
|
|
||||||
hrtimer_start(&cq->timer, kt, HRTIMER_MODE_REL);
|
hrtimer_start(&cq->timer, kt, HRTIMER_MODE_REL_PINNED);
|
||||||
}
|
}
|
||||||
|
|
||||||
put_cpu();
|
put_cpu();
|
||||||
|
@ -334,6 +345,7 @@ static int null_rq_prep_fn(struct request_queue *q, struct request *req)
|
||||||
req->special = cmd;
|
req->special = cmd;
|
||||||
return BLKPREP_OK;
|
return BLKPREP_OK;
|
||||||
}
|
}
|
||||||
|
blk_stop_queue(q);
|
||||||
|
|
||||||
return BLKPREP_DEFER;
|
return BLKPREP_DEFER;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ps3vram - Use extra PS3 video ram as MTD block device.
|
* ps3vram - Use extra PS3 video ram as block device.
|
||||||
*
|
*
|
||||||
* Copyright 2009 Sony Corporation
|
* Copyright 2009 Sony Corporation
|
||||||
*
|
*
|
||||||
|
@ -73,8 +73,8 @@ struct ps3vram_priv {
|
||||||
|
|
||||||
u64 memory_handle;
|
u64 memory_handle;
|
||||||
u64 context_handle;
|
u64 context_handle;
|
||||||
u32 *ctrl;
|
u32 __iomem *ctrl;
|
||||||
void *reports;
|
void __iomem *reports;
|
||||||
u8 *xdr_buf;
|
u8 *xdr_buf;
|
||||||
|
|
||||||
u32 *fifo_base;
|
u32 *fifo_base;
|
||||||
|
@ -104,7 +104,7 @@ static char *size = "256M";
|
||||||
module_param(size, charp, 0);
|
module_param(size, charp, 0);
|
||||||
MODULE_PARM_DESC(size, "memory size");
|
MODULE_PARM_DESC(size, "memory size");
|
||||||
|
|
||||||
static u32 *ps3vram_get_notifier(void *reports, int notifier)
|
static u32 __iomem *ps3vram_get_notifier(void __iomem *reports, int notifier)
|
||||||
{
|
{
|
||||||
return reports + DMA_NOTIFIER_OFFSET_BASE +
|
return reports + DMA_NOTIFIER_OFFSET_BASE +
|
||||||
DMA_NOTIFIER_SIZE * notifier;
|
DMA_NOTIFIER_SIZE * notifier;
|
||||||
|
@ -113,22 +113,22 @@ static u32 *ps3vram_get_notifier(void *reports, int notifier)
|
||||||
static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev)
|
static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev)
|
||||||
{
|
{
|
||||||
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
||||||
u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
|
u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
notify[i] = 0xffffffff;
|
iowrite32be(0xffffffff, notify + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
|
static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
|
||||||
unsigned int timeout_ms)
|
unsigned int timeout_ms)
|
||||||
{
|
{
|
||||||
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
||||||
u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
|
u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
for (timeout = 20; timeout; timeout--) {
|
for (timeout = 20; timeout; timeout--) {
|
||||||
if (!notify[3])
|
if (!ioread32be(notify + 3))
|
||||||
return 0;
|
return 0;
|
||||||
udelay(10);
|
udelay(10);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
|
||||||
timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!notify[3])
|
if (!ioread32be(notify + 3))
|
||||||
return 0;
|
return 0;
|
||||||
msleep(1);
|
msleep(1);
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
@ -148,8 +148,8 @@ static void ps3vram_init_ring(struct ps3_system_bus_device *dev)
|
||||||
{
|
{
|
||||||
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
|
||||||
|
|
||||||
priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
|
iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT);
|
||||||
priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
|
iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
|
static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
|
||||||
|
@ -159,14 +159,14 @@ static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
|
||||||
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET])
|
if (ioread32be(priv->ctrl + CTRL_PUT) == ioread32be(priv->ctrl + CTRL_GET))
|
||||||
return 0;
|
return 0;
|
||||||
msleep(1);
|
msleep(1);
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
|
||||||
dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n",
|
dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n",
|
||||||
priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET],
|
ioread32be(priv->ctrl + CTRL_PUT), ioread32be(priv->ctrl + CTRL_GET),
|
||||||
priv->ctrl[CTRL_TOP]);
|
ioread32be(priv->ctrl + CTRL_TOP));
|
||||||
|
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev)
|
||||||
|
|
||||||
ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
|
ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
|
||||||
|
|
||||||
priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
|
iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT);
|
||||||
|
|
||||||
/* asking the HV for a blit will kick the FIFO */
|
/* asking the HV for a blit will kick the FIFO */
|
||||||
status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
|
status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
|
||||||
|
@ -207,8 +207,8 @@ static void ps3vram_fire_ring(struct ps3_system_bus_device *dev)
|
||||||
|
|
||||||
mutex_lock(&ps3_gpu_mutex);
|
mutex_lock(&ps3_gpu_mutex);
|
||||||
|
|
||||||
priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET +
|
iowrite32be(FIFO_BASE + FIFO_OFFSET + (priv->fifo_ptr - priv->fifo_base)
|
||||||
(priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
|
* sizeof(u32), priv->ctrl + CTRL_PUT);
|
||||||
|
|
||||||
/* asking the HV for a blit will kick the FIFO */
|
/* asking the HV for a blit will kick the FIFO */
|
||||||
status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
|
status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
|
||||||
|
|
|
@ -99,9 +99,8 @@ void dasd_gendisk_free(struct dasd_block *block)
|
||||||
int dasd_scan_partitions(struct dasd_block *block)
|
int dasd_scan_partitions(struct dasd_block *block)
|
||||||
{
|
{
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
int retry, rc;
|
int rc;
|
||||||
|
|
||||||
retry = 5;
|
|
||||||
bdev = bdget_disk(block->gdp, 0);
|
bdev = bdget_disk(block->gdp, 0);
|
||||||
if (!bdev) {
|
if (!bdev) {
|
||||||
DBF_DEV_EVENT(DBF_ERR, block->base, "%s",
|
DBF_DEV_EVENT(DBF_ERR, block->base, "%s",
|
||||||
|
@ -116,19 +115,11 @@ int dasd_scan_partitions(struct dasd_block *block)
|
||||||
rc);
|
rc);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* See fs/partition/check.c:register_disk,rescan_partitions
|
rc = blkdev_reread_part(bdev);
|
||||||
* Can't call rescan_partitions directly. Use ioctl.
|
if (rc)
|
||||||
*/
|
|
||||||
rc = ioctl_by_bdev(bdev, BLKRRPART, 0);
|
|
||||||
while (rc == -EBUSY && retry > 0) {
|
|
||||||
schedule();
|
|
||||||
rc = ioctl_by_bdev(bdev, BLKRRPART, 0);
|
|
||||||
retry--;
|
|
||||||
DBF_DEV_EVENT(DBF_ERR, block->base,
|
DBF_DEV_EVENT(DBF_ERR, block->base,
|
||||||
"scan partitions error, retry %d rc %d",
|
"scan partitions error, rc %d", rc);
|
||||||
retry, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since the matching blkdev_put call to the blkdev_get in
|
* Since the matching blkdev_put call to the blkdev_get in
|
||||||
|
|
|
@ -74,7 +74,7 @@ struct nvme_dev {
|
||||||
struct blk_mq_tag_set tagset;
|
struct blk_mq_tag_set tagset;
|
||||||
struct blk_mq_tag_set admin_tagset;
|
struct blk_mq_tag_set admin_tagset;
|
||||||
u32 __iomem *dbs;
|
u32 __iomem *dbs;
|
||||||
struct pci_dev *pci_dev;
|
struct device *dev;
|
||||||
struct dma_pool *prp_page_pool;
|
struct dma_pool *prp_page_pool;
|
||||||
struct dma_pool *prp_small_pool;
|
struct dma_pool *prp_small_pool;
|
||||||
int instance;
|
int instance;
|
||||||
|
@ -92,6 +92,7 @@ struct nvme_dev {
|
||||||
work_func_t reset_workfn;
|
work_func_t reset_workfn;
|
||||||
struct work_struct reset_work;
|
struct work_struct reset_work;
|
||||||
struct work_struct probe_work;
|
struct work_struct probe_work;
|
||||||
|
struct work_struct scan_work;
|
||||||
char name[12];
|
char name[12];
|
||||||
char serial[20];
|
char serial[20];
|
||||||
char model[40];
|
char model[40];
|
||||||
|
@ -146,25 +147,15 @@ static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector)
|
||||||
return (sector >> (ns->lba_shift - 9));
|
return (sector >> (ns->lba_shift - 9));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
|
||||||
* nvme_free_iod - frees an nvme_iod
|
void *buf, unsigned bufflen);
|
||||||
* @dev: The device that the I/O was submitted to
|
int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
|
||||||
* @iod: The memory to free
|
void *buffer, void __user *ubuffer, unsigned bufflen,
|
||||||
*/
|
u32 *result, unsigned timeout);
|
||||||
void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod);
|
int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id);
|
||||||
|
int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid,
|
||||||
int nvme_setup_prps(struct nvme_dev *, struct nvme_iod *, int, gfp_t);
|
struct nvme_id_ns **id);
|
||||||
struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
|
int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log);
|
||||||
unsigned long addr, unsigned length);
|
|
||||||
void nvme_unmap_user_pages(struct nvme_dev *dev, int write,
|
|
||||||
struct nvme_iod *iod);
|
|
||||||
int nvme_submit_io_cmd(struct nvme_dev *, struct nvme_ns *,
|
|
||||||
struct nvme_command *, u32 *);
|
|
||||||
int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns);
|
|
||||||
int nvme_submit_admin_cmd(struct nvme_dev *, struct nvme_command *,
|
|
||||||
u32 *result);
|
|
||||||
int nvme_identify(struct nvme_dev *, unsigned nsid, unsigned cns,
|
|
||||||
dma_addr_t dma_addr);
|
|
||||||
int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||||
dma_addr_t dma_addr, u32 *result);
|
dma_addr_t dma_addr, u32 *result);
|
||||||
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
|
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
|
||||||
|
|
|
@ -179,6 +179,10 @@ enum {
|
||||||
NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4,
|
NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NVME_AER_NOTICE_NS_CHANGED = 0x0002,
|
||||||
|
};
|
||||||
|
|
||||||
struct nvme_lba_range_type {
|
struct nvme_lba_range_type {
|
||||||
__u8 type;
|
__u8 type;
|
||||||
__u8 attributes;
|
__u8 attributes;
|
||||||
|
@ -579,5 +583,6 @@ struct nvme_passthru_cmd {
|
||||||
#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd)
|
#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd)
|
||||||
#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io)
|
#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io)
|
||||||
#define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd)
|
#define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct nvme_passthru_cmd)
|
||||||
|
#define NVME_IOCTL_RESET _IO('N', 0x44)
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_NVME_H */
|
#endif /* _UAPI_LINUX_NVME_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue