mtip32xx: fix crash on surprise removal of the drive
pci and block layers have changed a lot compared to when SRSI support was added. Given the current state of pci and block layers, this driver do not have to do any specific handling. Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com> Signed-off-by: Selvan Mani <smani@micron.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
686d8e0bb5
commit
2132a54472
1 changed files with 46 additions and 99 deletions
|
@ -895,6 +895,10 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
|
|||
|
||||
/* Acknowledge the interrupt status on the port.*/
|
||||
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);
|
||||
|
||||
/* Demux port status */
|
||||
|
@ -2765,49 +2769,6 @@ static void mtip_hw_debugfs_exit(struct driver_data *dd)
|
|||
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);
|
||||
put_disk(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
|
||||
*
|
||||
|
@ -2955,7 +2916,6 @@ static int mtip_service_thread(void *data)
|
|||
unsigned long slot, slot_start, slot_wrap;
|
||||
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
||||
struct mtip_port *port = dd->port;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
if (kthread_should_stop() ||
|
||||
|
@ -3041,18 +3001,6 @@ restart_eh:
|
|||
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:
|
||||
return 0;
|
||||
}
|
||||
|
@ -3380,6 +3328,7 @@ static int mtip_hw_exit(struct driver_data *dd)
|
|||
/* Release the IRQ. */
|
||||
irq_set_affinity_hint(dd->pdev->irq, NULL);
|
||||
devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
|
||||
msleep(1000);
|
||||
|
||||
/* Free dma regions */
|
||||
mtip_dma_free(dd);
|
||||
|
@ -4075,52 +4024,51 @@ static int mtip_block_remove(struct driver_data *dd)
|
|||
{
|
||||
struct kobject *kobj;
|
||||
|
||||
if (!dd->sr) {
|
||||
mtip_hw_debugfs_exit(dd);
|
||||
mtip_hw_debugfs_exit(dd);
|
||||
|
||||
if (dd->mtip_svc_handler) {
|
||||
set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
|
||||
wake_up_interruptible(&dd->port->svc_wait);
|
||||
kthread_stop(dd->mtip_svc_handler);
|
||||
}
|
||||
|
||||
/* Clean up the sysfs attributes, if created */
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
|
||||
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
|
||||
if (kobj) {
|
||||
mtip_hw_sysfs_exit(dd, kobj);
|
||||
kobject_put(kobj);
|
||||
}
|
||||
if (dd->mtip_svc_handler) {
|
||||
set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
|
||||
wake_up_interruptible(&dd->port->svc_wait);
|
||||
kthread_stop(dd->mtip_svc_handler);
|
||||
}
|
||||
|
||||
/* Clean up the sysfs attributes, if created */
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
|
||||
kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
|
||||
if (kobj) {
|
||||
mtip_hw_sysfs_exit(dd, kobj);
|
||||
kobject_put(kobj);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dd->sr)
|
||||
mtip_standby_drive(dd);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
} else {
|
||||
else
|
||||
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
||||
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. */
|
||||
mtip_hw_exit(dd);
|
||||
|
@ -4516,6 +4464,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
"Completion workers still active!\n");
|
||||
}
|
||||
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
/* Clean up the block layer. */
|
||||
mtip_block_remove(dd);
|
||||
|
||||
|
@ -4533,10 +4482,8 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
list_del_init(&dd->remove_list);
|
||||
spin_unlock_irqrestore(&dev_lock, flags);
|
||||
|
||||
if (!dd->sr)
|
||||
kfree(dd);
|
||||
else
|
||||
set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
|
||||
kfree(dd);
|
||||
set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
|
||||
|
||||
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
|
Loading…
Reference in a new issue