aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_ccw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_ccw.c')
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c94
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 */
72static int zfcp_ccw_probe(struct ccw_device *ccw_device) 77static 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); 130out:
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 */
144static int zfcp_ccw_set_online(struct ccw_device *ccw_device) 147static 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); 175out:
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); 201out:
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
250static struct ccw_driver zfcp_ccw_driver = { 262static struct ccw_driver zfcp_ccw_driver = {