diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_ccw.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index d9da5c42ccbe..0c90f8e71605 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -18,12 +18,15 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev) | |||
18 | { | 18 | { |
19 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 19 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); |
20 | 20 | ||
21 | down(&zfcp_data.config_sema); | 21 | if (!adapter) |
22 | return 0; | ||
23 | |||
24 | mutex_lock(&zfcp_data.config_mutex); | ||
22 | 25 | ||
23 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); | 26 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); |
24 | zfcp_erp_wait(adapter); | 27 | zfcp_erp_wait(adapter); |
25 | 28 | ||
26 | up(&zfcp_data.config_sema); | 29 | mutex_unlock(&zfcp_data.config_mutex); |
27 | 30 | ||
28 | return 0; | 31 | return 0; |
29 | } | 32 | } |
@@ -33,6 +36,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev) | |||
33 | { | 36 | { |
34 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 37 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); |
35 | 38 | ||
39 | if (!adapter) | ||
40 | return 0; | ||
41 | |||
36 | zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL, | 42 | zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL, |
37 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | 43 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); |
38 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 44 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
@@ -63,25 +69,14 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter) | |||
63 | * zfcp_ccw_probe - probe function of zfcp driver | 69 | * zfcp_ccw_probe - probe function of zfcp driver |
64 | * @ccw_device: pointer to belonging ccw device | 70 | * @ccw_device: pointer to belonging ccw device |
65 | * | 71 | * |
66 | * This function gets called by the common i/o layer and sets up the initial | 72 | * This function gets called by the common i/o layer for each FCP |
67 | * data structures for each fcp adapter, which was detected by the system. | 73 | * device found on the current system. This is only a stub to make cio |
68 | * Also the sysfs files for this adapter will be created by this function. | 74 | * work: To only allocate adapter resources for devices actually used, |
69 | * In addition the nameserver port will be added to the ports of the adapter | 75 | * the allocation is deferred to the first call to ccw_set_online. |
70 | * and its sysfs representation will be created too. | ||
71 | */ | 76 | */ |
72 | static int zfcp_ccw_probe(struct ccw_device *ccw_device) | 77 | static int zfcp_ccw_probe(struct ccw_device *ccw_device) |
73 | { | 78 | { |
74 | int retval = 0; | 79 | return 0; |
75 | |||
76 | down(&zfcp_data.config_sema); | ||
77 | if (zfcp_adapter_enqueue(ccw_device)) { | ||
78 | dev_err(&ccw_device->dev, | ||
79 | "Setting up data structures for the " | ||
80 | "FCP adapter failed\n"); | ||
81 | retval = -EINVAL; | ||
82 | } | ||
83 | up(&zfcp_data.config_sema); | ||
84 | return retval; | ||
85 | } | 80 | } |
86 | 81 | ||
87 | /** | 82 | /** |
@@ -102,8 +97,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
102 | LIST_HEAD(port_remove_lh); | 97 | LIST_HEAD(port_remove_lh); |
103 | 98 | ||
104 | ccw_device_set_offline(ccw_device); | 99 | ccw_device_set_offline(ccw_device); |
105 | down(&zfcp_data.config_sema); | 100 | |
101 | mutex_lock(&zfcp_data.config_mutex); | ||
106 | adapter = dev_get_drvdata(&ccw_device->dev); | 102 | adapter = dev_get_drvdata(&ccw_device->dev); |
103 | if (!adapter) | ||
104 | goto out; | ||
107 | 105 | ||
108 | write_lock_irq(&zfcp_data.config_lock); | 106 | write_lock_irq(&zfcp_data.config_lock); |
109 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { | 107 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { |
@@ -129,29 +127,41 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
129 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); | 127 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); |
130 | zfcp_adapter_dequeue(adapter); | 128 | zfcp_adapter_dequeue(adapter); |
131 | 129 | ||
132 | up(&zfcp_data.config_sema); | 130 | out: |
131 | mutex_unlock(&zfcp_data.config_mutex); | ||
133 | } | 132 | } |
134 | 133 | ||
135 | /** | 134 | /** |
136 | * zfcp_ccw_set_online - set_online function of zfcp driver | 135 | * zfcp_ccw_set_online - set_online function of zfcp driver |
137 | * @ccw_device: pointer to belonging ccw device | 136 | * @ccw_device: pointer to belonging ccw device |
138 | * | 137 | * |
139 | * This function gets called by the common i/o layer and sets an adapter | 138 | * This function gets called by the common i/o layer and sets an |
140 | * into state online. Setting an fcp device online means that it will be | 139 | * adapter into state online. The first call will allocate all |
141 | * registered with the SCSI stack, that the QDIO queues will be set up | 140 | * adapter resources that will be retained until the device is removed |
142 | * and that the adapter will be opened (asynchronously). | 141 | * via zfcp_ccw_remove. |
142 | * | ||
143 | * Setting an fcp device online means that it will be registered with | ||
144 | * the SCSI stack, that the QDIO queues will be set up and that the | ||
145 | * adapter will be opened. | ||
143 | */ | 146 | */ |
144 | static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | 147 | static int zfcp_ccw_set_online(struct ccw_device *ccw_device) |
145 | { | 148 | { |
146 | struct zfcp_adapter *adapter; | 149 | struct zfcp_adapter *adapter; |
147 | int retval; | 150 | int ret = 0; |
148 | 151 | ||
149 | down(&zfcp_data.config_sema); | 152 | mutex_lock(&zfcp_data.config_mutex); |
150 | adapter = dev_get_drvdata(&ccw_device->dev); | 153 | adapter = dev_get_drvdata(&ccw_device->dev); |
151 | 154 | ||
152 | retval = zfcp_erp_thread_setup(adapter); | 155 | if (!adapter) { |
153 | if (retval) | 156 | ret = zfcp_adapter_enqueue(ccw_device); |
154 | goto out; | 157 | if (ret) { |
158 | dev_err(&ccw_device->dev, | ||
159 | "Setting up data structures for the " | ||
160 | "FCP adapter failed\n"); | ||
161 | goto out; | ||
162 | } | ||
163 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
164 | } | ||
155 | 165 | ||
156 | /* initialize request counter */ | 166 | /* initialize request counter */ |
157 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | 167 | BUG_ON(!zfcp_reqlist_isempty(adapter)); |
@@ -162,13 +172,11 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
162 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 172 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
163 | "ccsonl2", NULL); | 173 | "ccsonl2", NULL); |
164 | zfcp_erp_wait(adapter); | 174 | zfcp_erp_wait(adapter); |
165 | up(&zfcp_data.config_sema); | 175 | out: |
166 | flush_work(&adapter->scan_work); | 176 | mutex_unlock(&zfcp_data.config_mutex); |
167 | return 0; | 177 | if (!ret) |
168 | 178 | flush_work(&adapter->scan_work); | |
169 | out: | 179 | return ret; |
170 | up(&zfcp_data.config_sema); | ||
171 | return retval; | ||
172 | } | 180 | } |
173 | 181 | ||
174 | /** | 182 | /** |
@@ -182,12 +190,15 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) | |||
182 | { | 190 | { |
183 | struct zfcp_adapter *adapter; | 191 | struct zfcp_adapter *adapter; |
184 | 192 | ||
185 | down(&zfcp_data.config_sema); | 193 | mutex_lock(&zfcp_data.config_mutex); |
186 | adapter = dev_get_drvdata(&ccw_device->dev); | 194 | adapter = dev_get_drvdata(&ccw_device->dev); |
195 | if (!adapter) | ||
196 | goto out; | ||
197 | |||
187 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); | 198 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); |
188 | zfcp_erp_wait(adapter); | 199 | zfcp_erp_wait(adapter); |
189 | zfcp_erp_thread_kill(adapter); | 200 | mutex_unlock(&zfcp_data.config_mutex); |
190 | up(&zfcp_data.config_sema); | 201 | out: |
191 | return 0; | 202 | return 0; |
192 | } | 203 | } |
193 | 204 | ||
@@ -240,11 +251,12 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) | |||
240 | { | 251 | { |
241 | struct zfcp_adapter *adapter; | 252 | struct zfcp_adapter *adapter; |
242 | 253 | ||
243 | down(&zfcp_data.config_sema); | 254 | mutex_lock(&zfcp_data.config_mutex); |
244 | adapter = dev_get_drvdata(&cdev->dev); | 255 | adapter = dev_get_drvdata(&cdev->dev); |
245 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); | 256 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); |
246 | zfcp_erp_wait(adapter); | 257 | zfcp_erp_wait(adapter); |
247 | up(&zfcp_data.config_sema); | 258 | zfcp_erp_thread_kill(adapter); |
259 | mutex_unlock(&zfcp_data.config_mutex); | ||
248 | } | 260 | } |
249 | 261 | ||
250 | static struct ccw_driver zfcp_ccw_driver = { | 262 | static struct ccw_driver zfcp_ccw_driver = { |