Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Asai Thambi SP and committed by
Jens Axboe
2132a544 686d8e0b

+46 -99
+46 -99
drivers/block/mtip32xx/mtip32xx.c
··· 895 895 896 896 /* Acknowledge the interrupt status on the port.*/ 897 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 902 writel(port_stat, port->mmio + PORT_IRQ_STAT); 899 903 900 904 /* Demux port status */ ··· 2769 2765 debugfs_remove_recursive(dd->dfs_node); 2770 2766 } 2771 2767 2772 - static int mtip_free_orphan(struct driver_data *dd) 2773 - { 2774 - struct kobject *kobj; 2775 - 2776 - if (dd->bdev) { 2777 - if (dd->bdev->bd_holders >= 1) 2778 - return -2; 2779 - 2780 - bdput(dd->bdev); 2781 - dd->bdev = NULL; 2782 - } 2783 - 2784 - mtip_hw_debugfs_exit(dd); 2785 - 2786 - spin_lock(&rssd_index_lock); 2787 - ida_remove(&rssd_index_ida, dd->index); 2788 - spin_unlock(&rssd_index_lock); 2789 - 2790 - if (!test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag) && 2791 - test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) { 2792 - put_disk(dd->disk); 2793 - } else { 2794 - if (dd->disk) { 2795 - kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); 2796 - if (kobj) { 2797 - mtip_hw_sysfs_exit(dd, kobj); 2798 - kobject_put(kobj); 2799 - } 2800 - del_gendisk(dd->disk); 2801 - put_disk(dd->disk); 2802 - dd->disk = NULL; 2803 - } 2804 - if (dd->queue) { 2805 - dd->queue->queuedata = NULL; 2806 - blk_cleanup_queue(dd->queue); 2807 - blk_mq_free_tag_set(&dd->tags); 2808 - dd->queue = NULL; 2809 - } 2810 - } 2811 - kfree(dd); 2812 - return 0; 2813 - } 2814 - 2815 2768 /* 2816 2769 * Perform any init/resume time hardware setup 2817 2770 * ··· 2916 2955 unsigned long slot, slot_start, slot_wrap; 2917 2956 unsigned int num_cmd_slots = dd->slot_groups * 32; 2918 2957 struct mtip_port *port = dd->port; 2919 - int ret; 2920 2958 2921 2959 while (1) { 2922 2960 if (kthread_should_stop() || ··· 2997 3037 while (1) { 2998 3038 if (test_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag)) 2999 3039 break; 3000 - msleep_interruptible(1000); 3001 - if (kthread_should_stop()) 3002 - goto st_out; 3003 - } 3004 - 3005 - while (1) { 3006 - ret = mtip_free_orphan(dd); 3007 - if (!ret) { 3008 - /* NOTE: All data structures are invalid, do not 3009 - * access any here */ 3010 - return 0; 3011 - } 3012 3040 msleep_interruptible(1000); 3013 3041 if (kthread_should_stop()) 3014 3042 goto st_out; ··· 3328 3380 /* Release the IRQ. */ 3329 3381 irq_set_affinity_hint(dd->pdev->irq, NULL); 3330 3382 devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd); 3383 + msleep(1000); 3331 3384 3332 3385 /* Free dma regions */ 3333 3386 mtip_dma_free(dd); ··· 4024 4075 { 4025 4076 struct kobject *kobj; 4026 4077 4027 - if (!dd->sr) { 4028 - mtip_hw_debugfs_exit(dd); 4078 + mtip_hw_debugfs_exit(dd); 4029 4079 4030 - if (dd->mtip_svc_handler) { 4031 - set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags); 4032 - wake_up_interruptible(&dd->port->svc_wait); 4033 - kthread_stop(dd->mtip_svc_handler); 4080 + if (dd->mtip_svc_handler) { 4081 + set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags); 4082 + wake_up_interruptible(&dd->port->svc_wait); 4083 + kthread_stop(dd->mtip_svc_handler); 4084 + } 4085 + 4086 + /* Clean up the sysfs attributes, if created */ 4087 + if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) { 4088 + kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); 4089 + if (kobj) { 4090 + mtip_hw_sysfs_exit(dd, kobj); 4091 + kobject_put(kobj); 4034 4092 } 4093 + } 4035 4094 4036 - /* Clean up the sysfs attributes, if created */ 4037 - if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) { 4038 - kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); 4039 - if (kobj) { 4040 - mtip_hw_sysfs_exit(dd, kobj); 4041 - kobject_put(kobj); 4042 - } 4043 - } 4044 - 4095 + if (!dd->sr) 4045 4096 mtip_standby_drive(dd); 4046 - 4047 - /* 4048 - * Delete our gendisk structure. This also removes the device 4049 - * from /dev 4050 - */ 4051 - if (dd->bdev) { 4052 - bdput(dd->bdev); 4053 - dd->bdev = NULL; 4054 - } 4055 - if (dd->disk) { 4056 - del_gendisk(dd->disk); 4057 - if (dd->disk->queue) { 4058 - blk_cleanup_queue(dd->queue); 4059 - blk_mq_free_tag_set(&dd->tags); 4060 - dd->queue = NULL; 4061 - } 4062 - put_disk(dd->disk); 4063 - } 4064 - dd->disk = NULL; 4065 - 4066 - spin_lock(&rssd_index_lock); 4067 - ida_remove(&rssd_index_ida, dd->index); 4068 - spin_unlock(&rssd_index_lock); 4069 - } else { 4097 + else 4070 4098 dev_info(&dd->pdev->dev, "device %s surprise removal\n", 4071 4099 dd->disk->disk_name); 4100 + 4101 + /* 4102 + * Delete our gendisk structure. This also removes the device 4103 + * from /dev 4104 + */ 4105 + if (dd->bdev) { 4106 + bdput(dd->bdev); 4107 + dd->bdev = NULL; 4072 4108 } 4109 + if (dd->disk) { 4110 + del_gendisk(dd->disk); 4111 + if (dd->disk->queue) { 4112 + blk_cleanup_queue(dd->queue); 4113 + blk_mq_free_tag_set(&dd->tags); 4114 + dd->queue = NULL; 4115 + } 4116 + put_disk(dd->disk); 4117 + } 4118 + dd->disk = NULL; 4119 + 4120 + spin_lock(&rssd_index_lock); 4121 + ida_remove(&rssd_index_ida, dd->index); 4122 + spin_unlock(&rssd_index_lock); 4073 4123 4074 4124 /* De-initialize the protocol layer. */ 4075 4125 mtip_hw_exit(dd); ··· 4464 4516 "Completion workers still active!\n"); 4465 4517 } 4466 4518 4519 + blk_mq_stop_hw_queues(dd->queue); 4467 4520 /* Clean up the block layer. */ 4468 4521 mtip_block_remove(dd); 4469 4522 ··· 4482 4533 list_del_init(&dd->remove_list); 4483 4534 spin_unlock_irqrestore(&dev_lock, flags); 4484 4535 4485 - if (!dd->sr) 4486 - kfree(dd); 4487 - else 4488 - set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag); 4536 + kfree(dd); 4537 + set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag); 4489 4538 4490 4539 pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); 4491 4540 pci_set_drvdata(pdev, NULL);