aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAsai Thambi SP <asamymuthupa@micron.com>2015-05-11 18:53:18 -0400
committerJens Axboe <axboe@fb.com>2015-06-16 10:24:49 -0400
commit2132a544727eb17f76bfef8b550a016a41c38821 (patch)
tree89d44a795e45d6c99860aaeec0d059d23fd79bd1 /drivers/block
parent686d8e0bb5207c2a651eb5b28ac15db33adda59d (diff)
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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c143
1 files changed, 45 insertions, 98 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 92cb60194ed2..0c429b51e535 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -895,6 +895,10 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
895 895
896 /* Acknowledge the interrupt status on the port.*/ 896 /* Acknowledge the interrupt status on the port.*/
897 port_stat = readl(port->mmio + PORT_IRQ_STAT); 897 port_stat = readl(port->mmio + PORT_IRQ_STAT);
898 if (unlikely(port_stat == 0xFFFFFFFF)) {
899 mtip_check_surprise_removal(dd->pdev);
900 return IRQ_HANDLED;
901 }
898 writel(port_stat, port->mmio + PORT_IRQ_STAT); 902 writel(port_stat, port->mmio + PORT_IRQ_STAT);
899 903
900 /* Demux port status */ 904 /* Demux port status */
@@ -2765,49 +2769,6 @@ static void mtip_hw_debugfs_exit(struct driver_data *dd)
2765 debugfs_remove_recursive(dd->dfs_node); 2769 debugfs_remove_recursive(dd->dfs_node);
2766} 2770}
2767 2771
2768static int mtip_free_orphan(struct driver_data *dd)
2769{
2770 struct kobject *kobj;
2771
2772 if (dd->bdev) {
2773 if (dd->bdev->bd_holders >= 1)
2774 return -2;
2775
2776 bdput(dd->bdev);
2777 dd->bdev = NULL;
2778 }
2779
2780 mtip_hw_debugfs_exit(dd);
2781
2782 spin_lock(&rssd_index_lock);
2783 ida_remove(&rssd_index_ida, dd->index);
2784 spin_unlock(&rssd_index_lock);
2785
2786 if (!test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag) &&
2787 test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) {
2788 put_disk(dd->disk);
2789 } else {
2790 if (dd->disk) {
2791 kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
2792 if (kobj) {
2793 mtip_hw_sysfs_exit(dd, kobj);
2794 kobject_put(kobj);
2795 }
2796 del_gendisk(dd->disk);
2797 put_disk(dd->disk);
2798 dd->disk = NULL;
2799 }
2800 if (dd->queue) {
2801 dd->queue->queuedata = NULL;
2802 blk_cleanup_queue(dd->queue);
2803 blk_mq_free_tag_set(&dd->tags);
2804 dd->queue = NULL;
2805 }
2806 }
2807 kfree(dd);
2808 return 0;
2809}
2810
2811/* 2772/*
2812 * Perform any init/resume time hardware setup 2773 * Perform any init/resume time hardware setup
2813 * 2774 *
@@ -2955,7 +2916,6 @@ static int mtip_service_thread(void *data)
2955 unsigned long slot, slot_start, slot_wrap; 2916 unsigned long slot, slot_start, slot_wrap;
2956 unsigned int num_cmd_slots = dd->slot_groups * 32; 2917 unsigned int num_cmd_slots = dd->slot_groups * 32;
2957 struct mtip_port *port = dd->port; 2918 struct mtip_port *port = dd->port;
2958 int ret;
2959 2919
2960 while (1) { 2920 while (1) {
2961 if (kthread_should_stop() || 2921 if (kthread_should_stop() ||
@@ -3041,18 +3001,6 @@ restart_eh:
3041 if (kthread_should_stop()) 3001 if (kthread_should_stop())
3042 goto st_out; 3002 goto st_out;
3043 } 3003 }
3044
3045 while (1) {
3046 ret = mtip_free_orphan(dd);
3047 if (!ret) {
3048 /* NOTE: All data structures are invalid, do not
3049 * access any here */
3050 return 0;
3051 }
3052 msleep_interruptible(1000);
3053 if (kthread_should_stop())
3054 goto st_out;
3055 }
3056st_out: 3004st_out:
3057 return 0; 3005 return 0;
3058} 3006}
@@ -3380,6 +3328,7 @@ static int mtip_hw_exit(struct driver_data *dd)
3380 /* Release the IRQ. */ 3328 /* Release the IRQ. */
3381 irq_set_affinity_hint(dd->pdev->irq, NULL); 3329 irq_set_affinity_hint(dd->pdev->irq, NULL);
3382 devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd); 3330 devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
3331 msleep(1000);
3383 3332
3384 /* Free dma regions */ 3333 /* Free dma regions */
3385 mtip_dma_free(dd); 3334 mtip_dma_free(dd);
@@ -4075,52 +4024,51 @@ static int mtip_block_remove(struct driver_data *dd)
4075{ 4024{
4076 struct kobject *kobj; 4025 struct kobject *kobj;
4077 4026
4078 if (!dd->sr) { 4027 mtip_hw_debugfs_exit(dd);
4079 mtip_hw_debugfs_exit(dd);
4080 4028
4081 if (dd->mtip_svc_handler) { 4029 if (dd->mtip_svc_handler) {
4082 set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags); 4030 set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
4083 wake_up_interruptible(&dd->port->svc_wait); 4031 wake_up_interruptible(&dd->port->svc_wait);
4084 kthread_stop(dd->mtip_svc_handler); 4032 kthread_stop(dd->mtip_svc_handler);
4085 } 4033 }
4086 4034
4087 /* Clean up the sysfs attributes, if created */ 4035 /* Clean up the sysfs attributes, if created */
4088 if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) { 4036 if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
4089 kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); 4037 kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
4090 if (kobj) { 4038 if (kobj) {
4091 mtip_hw_sysfs_exit(dd, kobj); 4039 mtip_hw_sysfs_exit(dd, kobj);
4092 kobject_put(kobj); 4040 kobject_put(kobj);
4093 }
4094 } 4041 }
4042 }
4095 4043
4044 if (!dd->sr)
4096 mtip_standby_drive(dd); 4045 mtip_standby_drive(dd);
4097 4046 else
4098 /*
4099 * Delete our gendisk structure. This also removes the device
4100 * from /dev
4101 */
4102 if (dd->bdev) {
4103 bdput(dd->bdev);
4104 dd->bdev = NULL;
4105 }
4106 if (dd->disk) {
4107 del_gendisk(dd->disk);
4108 if (dd->disk->queue) {
4109 blk_cleanup_queue(dd->queue);
4110 blk_mq_free_tag_set(&dd->tags);
4111 dd->queue = NULL;
4112 }
4113 put_disk(dd->disk);
4114 }
4115 dd->disk = NULL;
4116
4117 spin_lock(&rssd_index_lock);
4118 ida_remove(&rssd_index_ida, dd->index);
4119 spin_unlock(&rssd_index_lock);
4120 } else {
4121 dev_info(&dd->pdev->dev, "device %s surprise removal\n", 4047 dev_info(&dd->pdev->dev, "device %s surprise removal\n",
4122 dd->disk->disk_name); 4048 dd->disk->disk_name);
4049
4050 /*
4051 * Delete our gendisk structure. This also removes the device
4052 * from /dev
4053 */
4054 if (dd->bdev) {
4055 bdput(dd->bdev);
4056 dd->bdev = NULL;
4057 }
4058 if (dd->disk) {
4059 del_gendisk(dd->disk);
4060 if (dd->disk->queue) {
4061 blk_cleanup_queue(dd->queue);
4062 blk_mq_free_tag_set(&dd->tags);
4063 dd->queue = NULL;
4064 }
4065 put_disk(dd->disk);
4123 } 4066 }
4067 dd->disk = NULL;
4068
4069 spin_lock(&rssd_index_lock);
4070 ida_remove(&rssd_index_ida, dd->index);
4071 spin_unlock(&rssd_index_lock);
4124 4072
4125 /* De-initialize the protocol layer. */ 4073 /* De-initialize the protocol layer. */
4126 mtip_hw_exit(dd); 4074 mtip_hw_exit(dd);
@@ -4516,6 +4464,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
4516 "Completion workers still active!\n"); 4464 "Completion workers still active!\n");
4517 } 4465 }
4518 4466
4467 blk_mq_stop_hw_queues(dd->queue);
4519 /* Clean up the block layer. */ 4468 /* Clean up the block layer. */
4520 mtip_block_remove(dd); 4469 mtip_block_remove(dd);
4521 4470
@@ -4533,10 +4482,8 @@ static void mtip_pci_remove(struct pci_dev *pdev)
4533 list_del_init(&dd->remove_list); 4482 list_del_init(&dd->remove_list);
4534 spin_unlock_irqrestore(&dev_lock, flags); 4483 spin_unlock_irqrestore(&dev_lock, flags);
4535 4484
4536 if (!dd->sr) 4485 kfree(dd);
4537 kfree(dd); 4486 set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
4538 else
4539 set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
4540 4487
4541 pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); 4488 pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
4542 pci_set_drvdata(pdev, NULL); 4489 pci_set_drvdata(pdev, NULL);