aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_sysfs.c')
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c250
1 files changed, 143 insertions, 107 deletions
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index d31000886ca8..f539e006683c 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * sysfs attributes. 4 * sysfs attributes.
5 * 5 *
6 * Copyright IBM Corporation 2008 6 * Copyright IBM Corporation 2008, 2009
7 */ 7 */
8 8
9#define KMSG_COMPONENT "zfcp" 9#define KMSG_COMPONENT "zfcp"
@@ -19,30 +19,44 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \
19 struct device_attribute *at,\ 19 struct device_attribute *at,\
20 char *buf) \ 20 char *buf) \
21{ \ 21{ \
22 struct _feat_def *_feat = dev_get_drvdata(dev); \ 22 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
23 sysfs_device); \
23 \ 24 \
24 return sprintf(buf, _format, _value); \ 25 return sprintf(buf, _format, _value); \
25} \ 26} \
26static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ 27static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
27 zfcp_sysfs_##_feat##_##_name##_show, NULL); 28 zfcp_sysfs_##_feat##_##_name##_show, NULL);
28 29
29ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", 30#define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \
30 atomic_read(&adapter->status)); 31static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
31ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", 32 struct device_attribute *at,\
32 (unsigned long long) adapter->peer_wwnn); 33 char *buf) \
33ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", 34{ \
34 (unsigned long long) adapter->peer_wwpn); 35 struct ccw_device *cdev = to_ccwdev(dev); \
35ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", 36 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); \
36 adapter->peer_d_id); 37 int i; \
37ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", 38 \
38 adapter->hydra_version); 39 if (!adapter) \
39ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n", 40 return -ENODEV; \
40 adapter->fsf_lic_version); 41 \
41ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, hardware_version, "0x%08x\n", 42 i = sprintf(buf, _format, _value); \
42 adapter->hardware_version); 43 zfcp_ccw_adapter_put(adapter); \
43ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, in_recovery, "%d\n", 44 return i; \
44 (atomic_read(&adapter->status) & 45} \
45 ZFCP_STATUS_COMMON_ERP_INUSE) != 0); 46static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \
47 zfcp_sysfs_adapter_##_name##_show, NULL);
48
49ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
50ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n",
51 (unsigned long long) adapter->peer_wwnn);
52ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n",
53 (unsigned long long) adapter->peer_wwpn);
54ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
55ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
56ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
57ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version);
58ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) &
59 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
46 60
47ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", 61ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
48 atomic_read(&port->status)); 62 atomic_read(&port->status));
@@ -73,7 +87,8 @@ static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \
73 struct device_attribute *attr, \ 87 struct device_attribute *attr, \
74 char *buf) \ 88 char *buf) \
75{ \ 89{ \
76 struct _feat_def *_feat = dev_get_drvdata(dev); \ 90 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
91 sysfs_device); \
77 \ 92 \
78 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ 93 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \
79 return sprintf(buf, "1\n"); \ 94 return sprintf(buf, "1\n"); \
@@ -84,15 +99,13 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
84 struct device_attribute *attr,\ 99 struct device_attribute *attr,\
85 const char *buf, size_t count)\ 100 const char *buf, size_t count)\
86{ \ 101{ \
87 struct _feat_def *_feat = dev_get_drvdata(dev); \ 102 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
103 sysfs_device); \
88 unsigned long val; \ 104 unsigned long val; \
89 int retval = 0; \ 105 int retval = 0; \
90 \ 106 \
91 mutex_lock(&zfcp_data.config_mutex); \ 107 if (!(_feat && get_device(&_feat->sysfs_device))) \
92 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \ 108 return -EBUSY; \
93 retval = -EBUSY; \
94 goto out; \
95 } \
96 \ 109 \
97 if (strict_strtoul(buf, 0, &val) || val != 0) { \ 110 if (strict_strtoul(buf, 0, &val) || val != 0) { \
98 retval = -EINVAL; \ 111 retval = -EINVAL; \
@@ -105,29 +118,82 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
105 _reopen_id, NULL); \ 118 _reopen_id, NULL); \
106 zfcp_erp_wait(_adapter); \ 119 zfcp_erp_wait(_adapter); \
107out: \ 120out: \
108 mutex_unlock(&zfcp_data.config_mutex); \ 121 put_device(&_feat->sysfs_device); \
109 return retval ? retval : (ssize_t) count; \ 122 return retval ? retval : (ssize_t) count; \
110} \ 123} \
111static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ 124static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
112 zfcp_sysfs_##_feat##_failed_show, \ 125 zfcp_sysfs_##_feat##_failed_show, \
113 zfcp_sysfs_##_feat##_failed_store); 126 zfcp_sysfs_##_feat##_failed_store);
114 127
115ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2");
116ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); 128ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
117ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); 129ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
118 130
131static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
132 struct device_attribute *attr,
133 char *buf)
134{
135 struct ccw_device *cdev = to_ccwdev(dev);
136 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
137 int i;
138
139 if (!adapter)
140 return -ENODEV;
141
142 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
143 i = sprintf(buf, "1\n");
144 else
145 i = sprintf(buf, "0\n");
146
147 zfcp_ccw_adapter_put(adapter);
148 return i;
149}
150
151static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
152 struct device_attribute *attr,
153 const char *buf, size_t count)
154{
155 struct ccw_device *cdev = to_ccwdev(dev);
156 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
157 unsigned long val;
158 int retval = 0;
159
160 if (!adapter)
161 return -ENODEV;
162
163 if (strict_strtoul(buf, 0, &val) || val != 0) {
164 retval = -EINVAL;
165 goto out;
166 }
167
168 zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
169 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
170 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
171 "syafai2", NULL);
172 zfcp_erp_wait(adapter);
173out:
174 zfcp_ccw_adapter_put(adapter);
175 return retval ? retval : (ssize_t) count;
176}
177static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
178 zfcp_sysfs_adapter_failed_show,
179 zfcp_sysfs_adapter_failed_store);
180
119static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, 181static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
120 struct device_attribute *attr, 182 struct device_attribute *attr,
121 const char *buf, size_t count) 183 const char *buf, size_t count)
122{ 184{
123 struct zfcp_adapter *adapter = dev_get_drvdata(dev); 185 struct ccw_device *cdev = to_ccwdev(dev);
124 int ret; 186 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
125 187
126 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) 188 if (!adapter)
127 return -EBUSY; 189 return -ENODEV;
128 190
129 ret = zfcp_fc_scan_ports(adapter); 191 /* sync the user-space- with the kernel-invocation of scan_work */
130 return ret ? ret : (ssize_t) count; 192 queue_work(adapter->work_queue, &adapter->scan_work);
193 flush_work(&adapter->scan_work);
194 zfcp_ccw_adapter_put(adapter);
195
196 return (ssize_t) count;
131} 197}
132static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, 198static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
133 zfcp_sysfs_port_rescan_store); 199 zfcp_sysfs_port_rescan_store);
@@ -136,44 +202,34 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
136 struct device_attribute *attr, 202 struct device_attribute *attr,
137 const char *buf, size_t count) 203 const char *buf, size_t count)
138{ 204{
139 struct zfcp_adapter *adapter = dev_get_drvdata(dev); 205 struct ccw_device *cdev = to_ccwdev(dev);
206 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
140 struct zfcp_port *port; 207 struct zfcp_port *port;
141 u64 wwpn; 208 u64 wwpn;
142 int retval = 0; 209 int retval = -EINVAL;
143 LIST_HEAD(port_remove_lh);
144 210
145 mutex_lock(&zfcp_data.config_mutex); 211 if (!adapter)
146 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { 212 return -ENODEV;
147 retval = -EBUSY;
148 goto out;
149 }
150 213
151 if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) { 214 if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn))
152 retval = -EINVAL;
153 goto out; 215 goto out;
154 }
155 216
156 write_lock_irq(&zfcp_data.config_lock);
157 port = zfcp_get_port_by_wwpn(adapter, wwpn); 217 port = zfcp_get_port_by_wwpn(adapter, wwpn);
158 if (port && (atomic_read(&port->refcount) == 0)) { 218 if (!port)
159 zfcp_port_get(port);
160 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
161 list_move(&port->list, &port_remove_lh);
162 } else
163 port = NULL;
164 write_unlock_irq(&zfcp_data.config_lock);
165
166 if (!port) {
167 retval = -ENXIO;
168 goto out; 219 goto out;
169 } 220 else
221 retval = 0;
222
223 write_lock_irq(&adapter->port_list_lock);
224 list_del(&port->list);
225 write_unlock_irq(&adapter->port_list_lock);
226
227 put_device(&port->sysfs_device);
170 228
171 zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); 229 zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
172 zfcp_erp_wait(adapter); 230 zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
173 zfcp_port_put(port);
174 zfcp_port_dequeue(port);
175 out: 231 out:
176 mutex_unlock(&zfcp_data.config_mutex); 232 zfcp_ccw_adapter_put(adapter);
177 return retval ? retval : (ssize_t) count; 233 return retval ? retval : (ssize_t) count;
178} 234}
179static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, 235static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
@@ -202,16 +258,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
202 struct device_attribute *attr, 258 struct device_attribute *attr,
203 const char *buf, size_t count) 259 const char *buf, size_t count)
204{ 260{
205 struct zfcp_port *port = dev_get_drvdata(dev); 261 struct zfcp_port *port = container_of(dev, struct zfcp_port,
262 sysfs_device);
206 struct zfcp_unit *unit; 263 struct zfcp_unit *unit;
207 u64 fcp_lun; 264 u64 fcp_lun;
208 int retval = -EINVAL; 265 int retval = -EINVAL;
209 266
210 mutex_lock(&zfcp_data.config_mutex); 267 if (!(port && get_device(&port->sysfs_device)))
211 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { 268 return -EBUSY;
212 retval = -EBUSY;
213 goto out;
214 }
215 269
216 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) 270 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
217 goto out; 271 goto out;
@@ -219,15 +273,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
219 unit = zfcp_unit_enqueue(port, fcp_lun); 273 unit = zfcp_unit_enqueue(port, fcp_lun);
220 if (IS_ERR(unit)) 274 if (IS_ERR(unit))
221 goto out; 275 goto out;
222 276 else
223 retval = 0; 277 retval = 0;
224 278
225 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); 279 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
226 zfcp_erp_wait(unit->port->adapter); 280 zfcp_erp_wait(unit->port->adapter);
227 flush_work(&unit->scsi_work); 281 flush_work(&unit->scsi_work);
228 zfcp_unit_put(unit);
229out: 282out:
230 mutex_unlock(&zfcp_data.config_mutex); 283 put_device(&port->sysfs_device);
231 return retval ? retval : (ssize_t) count; 284 return retval ? retval : (ssize_t) count;
232} 285}
233static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); 286static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -236,54 +289,37 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
236 struct device_attribute *attr, 289 struct device_attribute *attr,
237 const char *buf, size_t count) 290 const char *buf, size_t count)
238{ 291{
239 struct zfcp_port *port = dev_get_drvdata(dev); 292 struct zfcp_port *port = container_of(dev, struct zfcp_port,
293 sysfs_device);
240 struct zfcp_unit *unit; 294 struct zfcp_unit *unit;
241 u64 fcp_lun; 295 u64 fcp_lun;
242 int retval = 0; 296 int retval = -EINVAL;
243 LIST_HEAD(unit_remove_lh);
244 297
245 mutex_lock(&zfcp_data.config_mutex); 298 if (!(port && get_device(&port->sysfs_device)))
246 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { 299 return -EBUSY;
247 retval = -EBUSY;
248 goto out;
249 }
250 300
251 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { 301 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
252 retval = -EINVAL;
253 goto out; 302 goto out;
254 }
255 303
256 write_lock_irq(&zfcp_data.config_lock);
257 unit = zfcp_get_unit_by_lun(port, fcp_lun); 304 unit = zfcp_get_unit_by_lun(port, fcp_lun);
258 if (unit) { 305 if (!unit)
259 write_unlock_irq(&zfcp_data.config_lock); 306 goto out;
260 /* wait for possible timeout during SCSI probe */ 307 else
261 flush_work(&unit->scsi_work); 308 retval = 0;
262 write_lock_irq(&zfcp_data.config_lock);
263
264 if (atomic_read(&unit->refcount) == 0) {
265 zfcp_unit_get(unit);
266 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
267 &unit->status);
268 list_move(&unit->list, &unit_remove_lh);
269 } else {
270 unit = NULL;
271 }
272 }
273 309
274 write_unlock_irq(&zfcp_data.config_lock); 310 /* wait for possible timeout during SCSI probe */
311 flush_work(&unit->scsi_work);
275 312
276 if (!unit) { 313 write_lock_irq(&port->unit_list_lock);
277 retval = -ENXIO; 314 list_del(&unit->list);
278 goto out; 315 write_unlock_irq(&port->unit_list_lock);
279 } 316
317 put_device(&unit->sysfs_device);
280 318
281 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); 319 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
282 zfcp_erp_wait(unit->port->adapter); 320 zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
283 zfcp_unit_put(unit);
284 zfcp_unit_dequeue(unit);
285out: 321out:
286 mutex_unlock(&zfcp_data.config_mutex); 322 put_device(&port->sysfs_device);
287 return retval ? retval : (ssize_t) count; 323 return retval ? retval : (ssize_t) count;
288} 324}
289static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); 325static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);