diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index d23027a2f2f0..41635b13ccb1 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -970,6 +970,27 @@ static void zfcp_dummy_release(struct device *dev) | |||
970 | return; | 970 | return; |
971 | } | 971 | } |
972 | 972 | ||
973 | int zfcp_status_read_refill(struct zfcp_adapter *adapter) | ||
974 | { | ||
975 | while (atomic_read(&adapter->stat_miss) > 0) | ||
976 | if (zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL)) | ||
977 | break; | ||
978 | else | ||
979 | atomic_dec(&adapter->stat_miss); | ||
980 | |||
981 | if (ZFCP_STATUS_READS_RECOM <= atomic_read(&adapter->stat_miss)) { | ||
982 | zfcp_erp_adapter_reopen(adapter, 0, 103, NULL); | ||
983 | return 1; | ||
984 | } | ||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static void _zfcp_status_read_scheduler(struct work_struct *work) | ||
989 | { | ||
990 | zfcp_status_read_refill(container_of(work, struct zfcp_adapter, | ||
991 | stat_work)); | ||
992 | } | ||
993 | |||
973 | /* | 994 | /* |
974 | * Enqueues an adapter at the end of the adapter list in the driver data. | 995 | * Enqueues an adapter at the end of the adapter list in the driver data. |
975 | * All adapter internal structures are set up. | 996 | * All adapter internal structures are set up. |
@@ -1063,6 +1084,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
1063 | 1084 | ||
1064 | /* initialize lock of associated request queue */ | 1085 | /* initialize lock of associated request queue */ |
1065 | rwlock_init(&adapter->request_queue.queue_lock); | 1086 | rwlock_init(&adapter->request_queue.queue_lock); |
1087 | INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); | ||
1066 | 1088 | ||
1067 | /* mark adapter unusable as long as sysfs registration is not complete */ | 1089 | /* mark adapter unusable as long as sysfs registration is not complete */ |
1068 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 1090 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
@@ -1123,6 +1145,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
1123 | int retval = 0; | 1145 | int retval = 0; |
1124 | unsigned long flags; | 1146 | unsigned long flags; |
1125 | 1147 | ||
1148 | cancel_work_sync(&adapter->stat_work); | ||
1126 | zfcp_adapter_scsi_unregister(adapter); | 1149 | zfcp_adapter_scsi_unregister(adapter); |
1127 | device_unregister(&adapter->generic_services); | 1150 | device_unregister(&adapter->generic_services); |
1128 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); | 1151 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); |