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