diff options
author | Asai Thambi SP <asamymuthupa@micron.com> | 2015-05-11 18:53:18 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-06-16 10:24:49 -0400 |
commit | 2132a544727eb17f76bfef8b550a016a41c38821 (patch) | |
tree | 89d44a795e45d6c99860aaeec0d059d23fd79bd1 /drivers/block | |
parent | 686d8e0bb5207c2a651eb5b28ac15db33adda59d (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.c | 143 |
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 | ||
2768 | static 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 | } | ||
3056 | st_out: | 3004 | st_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); |