diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_ccw.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 51b6a05f4d12..b04038c74786 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -25,7 +25,8 @@ static int zfcp_ccw_probe(struct ccw_device *ccw_device) | |||
25 | down(&zfcp_data.config_sema); | 25 | down(&zfcp_data.config_sema); |
26 | if (zfcp_adapter_enqueue(ccw_device)) { | 26 | if (zfcp_adapter_enqueue(ccw_device)) { |
27 | dev_err(&ccw_device->dev, | 27 | dev_err(&ccw_device->dev, |
28 | "Setup of data structures failed.\n"); | 28 | "Setting up data structures for the " |
29 | "FCP adapter failed\n"); | ||
29 | retval = -EINVAL; | 30 | retval = -EINVAL; |
30 | } | 31 | } |
31 | up(&zfcp_data.config_sema); | 32 | up(&zfcp_data.config_sema); |
@@ -46,6 +47,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
46 | struct zfcp_adapter *adapter; | 47 | struct zfcp_adapter *adapter; |
47 | struct zfcp_port *port, *p; | 48 | struct zfcp_port *port, *p; |
48 | struct zfcp_unit *unit, *u; | 49 | struct zfcp_unit *unit, *u; |
50 | LIST_HEAD(unit_remove_lh); | ||
51 | LIST_HEAD(port_remove_lh); | ||
49 | 52 | ||
50 | ccw_device_set_offline(ccw_device); | 53 | ccw_device_set_offline(ccw_device); |
51 | down(&zfcp_data.config_sema); | 54 | down(&zfcp_data.config_sema); |
@@ -54,26 +57,26 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
54 | write_lock_irq(&zfcp_data.config_lock); | 57 | write_lock_irq(&zfcp_data.config_lock); |
55 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { | 58 | list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { |
56 | list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { | 59 | list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { |
57 | list_move(&unit->list, &port->unit_remove_lh); | 60 | list_move(&unit->list, &unit_remove_lh); |
58 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, | 61 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, |
59 | &unit->status); | 62 | &unit->status); |
60 | } | 63 | } |
61 | list_move(&port->list, &adapter->port_remove_lh); | 64 | list_move(&port->list, &port_remove_lh); |
62 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 65 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
63 | } | 66 | } |
64 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 67 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
65 | write_unlock_irq(&zfcp_data.config_lock); | 68 | write_unlock_irq(&zfcp_data.config_lock); |
66 | 69 | ||
67 | list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) { | 70 | list_for_each_entry_safe(port, p, &port_remove_lh, list) { |
68 | list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) { | 71 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) { |
69 | if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, | 72 | if (atomic_read(&unit->status) & |
70 | &unit->status)) | 73 | ZFCP_STATUS_UNIT_REGISTERED) |
71 | scsi_remove_device(unit->device); | 74 | scsi_remove_device(unit->device); |
72 | zfcp_unit_dequeue(unit); | 75 | zfcp_unit_dequeue(unit); |
73 | } | 76 | } |
74 | zfcp_port_dequeue(port); | 77 | zfcp_port_dequeue(port); |
75 | } | 78 | } |
76 | zfcp_adapter_wait(adapter); | 79 | wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); |
77 | zfcp_adapter_dequeue(adapter); | 80 | zfcp_adapter_dequeue(adapter); |
78 | 81 | ||
79 | up(&zfcp_data.config_sema); | 82 | up(&zfcp_data.config_sema); |
@@ -156,15 +159,18 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | |||
156 | 159 | ||
157 | switch (event) { | 160 | switch (event) { |
158 | case CIO_GONE: | 161 | case CIO_GONE: |
159 | dev_warn(&adapter->ccw_device->dev, "device gone\n"); | 162 | dev_warn(&adapter->ccw_device->dev, |
163 | "The FCP device has been detached\n"); | ||
160 | zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); | 164 | zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); |
161 | break; | 165 | break; |
162 | case CIO_NO_PATH: | 166 | case CIO_NO_PATH: |
163 | dev_warn(&adapter->ccw_device->dev, "no path\n"); | 167 | dev_warn(&adapter->ccw_device->dev, |
168 | "The CHPID for the FCP device is offline\n"); | ||
164 | zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); | 169 | zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); |
165 | break; | 170 | break; |
166 | case CIO_OPER: | 171 | case CIO_OPER: |
167 | dev_info(&adapter->ccw_device->dev, "operational again\n"); | 172 | dev_info(&adapter->ccw_device->dev, |
173 | "The FCP device is operational again\n"); | ||
168 | zfcp_erp_modify_adapter_status(adapter, 11, NULL, | 174 | zfcp_erp_modify_adapter_status(adapter, 11, NULL, |
169 | ZFCP_STATUS_COMMON_RUNNING, | 175 | ZFCP_STATUS_COMMON_RUNNING, |
170 | ZFCP_SET); | 176 | ZFCP_SET); |
@@ -220,3 +226,20 @@ int __init zfcp_ccw_register(void) | |||
220 | { | 226 | { |
221 | return ccw_driver_register(&zfcp_ccw_driver); | 227 | return ccw_driver_register(&zfcp_ccw_driver); |
222 | } | 228 | } |
229 | |||
230 | /** | ||
231 | * zfcp_get_adapter_by_busid - find zfcp_adapter struct | ||
232 | * @busid: bus id string of zfcp adapter to find | ||
233 | */ | ||
234 | struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid) | ||
235 | { | ||
236 | struct ccw_device *ccw_device; | ||
237 | struct zfcp_adapter *adapter = NULL; | ||
238 | |||
239 | ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | ||
240 | if (ccw_device) { | ||
241 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
242 | put_device(&ccw_device->dev); | ||
243 | } | ||
244 | return adapter; | ||
245 | } | ||