blob: 901cc9a6ed207840b44b33f86a46fc1e753c0c1a [file] [log] [blame]
Swen Schillig60221922008-07-02 10:56:38 +02001/*
2 * zfcp device driver
3 *
4 * sysfs attributes.
5 *
Swen Schilligf3450c72009-11-24 16:53:59 +01006 * Copyright IBM Corporation 2008, 2009
Swen Schillig60221922008-07-02 10:56:38 +02007 */
8
Christof Schmittecf39d42008-12-25 13:39:53 +01009#define KMSG_COMPONENT "zfcp"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
Swen Schillig60221922008-07-02 10:56:38 +020012#include "zfcp_ext.h"
13
14#define ZFCP_DEV_ATTR(_feat, _name, _mode, _show, _store) \
15struct device_attribute dev_attr_##_feat##_##_name = __ATTR(_name, _mode,\
16 _show, _store)
17#define ZFCP_DEFINE_ATTR(_feat_def, _feat, _name, _format, _value) \
18static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \
19 struct device_attribute *at,\
20 char *buf) \
21{ \
Christof Schmitt25458eb2009-11-24 16:54:02 +010022 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
23 sysfs_device); \
Swen Schillig60221922008-07-02 10:56:38 +020024 \
25 return sprintf(buf, _format, _value); \
26} \
27static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
28 zfcp_sysfs_##_feat##_##_name##_show, NULL);
29
Swen Schilligde3dc572009-11-24 16:54:00 +010030#define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \
31static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
32 struct device_attribute *at,\
33 char *buf) \
34{ \
35 struct ccw_device *cdev = to_ccwdev(dev); \
36 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); \
37 int i; \
38 \
39 if (!adapter) \
40 return -ENODEV; \
41 \
42 i = sprintf(buf, _format, _value); \
43 zfcp_ccw_adapter_put(adapter); \
44 return i; \
45} \
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);
Swen Schillig60221922008-07-02 10:56:38 +020060
61ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
62 atomic_read(&port->status));
63ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
64 (atomic_read(&port->status) &
65 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
66ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
67 (atomic_read(&port->status) &
68 ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
69
70ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
71 atomic_read(&unit->status));
72ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
73 (atomic_read(&unit->status) &
74 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
75ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
76 (atomic_read(&unit->status) &
77 ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
78ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
79 (atomic_read(&unit->status) &
80 ZFCP_STATUS_UNIT_SHARED) != 0);
81ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
82 (atomic_read(&unit->status) &
83 ZFCP_STATUS_UNIT_READONLY) != 0);
84
85#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id) \
86static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \
87 struct device_attribute *attr, \
88 char *buf) \
89{ \
Christof Schmitt25458eb2009-11-24 16:54:02 +010090 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
91 sysfs_device); \
Swen Schillig60221922008-07-02 10:56:38 +020092 \
93 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \
94 return sprintf(buf, "1\n"); \
95 else \
96 return sprintf(buf, "0\n"); \
97} \
98static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
99 struct device_attribute *attr,\
100 const char *buf, size_t count)\
101{ \
Christof Schmitt25458eb2009-11-24 16:54:02 +0100102 struct _feat_def *_feat = container_of(dev, struct _feat_def, \
103 sysfs_device); \
Swen Schillig60221922008-07-02 10:56:38 +0200104 unsigned long val; \
105 int retval = 0; \
106 \
Swen Schillig60221922008-07-02 10:56:38 +0200107 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \
108 retval = -EBUSY; \
109 goto out; \
110 } \
111 \
112 if (strict_strtoul(buf, 0, &val) || val != 0) { \
113 retval = -EINVAL; \
114 goto out; \
115 } \
116 \
117 zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL, \
118 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
119 zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED, \
120 _reopen_id, NULL); \
121 zfcp_erp_wait(_adapter); \
122out: \
Swen Schillig60221922008-07-02 10:56:38 +0200123 return retval ? retval : (ssize_t) count; \
124} \
125static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
126 zfcp_sysfs_##_feat##_failed_show, \
127 zfcp_sysfs_##_feat##_failed_store);
128
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100129ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
130ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
Swen Schillig60221922008-07-02 10:56:38 +0200131
Swen Schilligde3dc572009-11-24 16:54:00 +0100132static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
133 struct device_attribute *attr,
134 char *buf)
135{
136 struct ccw_device *cdev = to_ccwdev(dev);
137 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
138 int i;
139
140 if (!adapter)
141 return -ENODEV;
142
143 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
144 i = sprintf(buf, "1\n");
145 else
146 i = sprintf(buf, "0\n");
147
148 zfcp_ccw_adapter_put(adapter);
149 return i;
150}
151
152static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
153 struct device_attribute *attr,
154 const char *buf, size_t count)
155{
156 struct ccw_device *cdev = to_ccwdev(dev);
157 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
158 unsigned long val;
159 int retval = 0;
160
161 if (!adapter)
162 return -ENODEV;
163
164 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
165 retval = -EBUSY;
166 goto out;
167 }
168
169 if (strict_strtoul(buf, 0, &val) || val != 0) {
170 retval = -EINVAL;
171 goto out;
172 }
173
174 zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
175 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
176 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
177 "syafai2", NULL);
178 zfcp_erp_wait(adapter);
179out:
180 zfcp_ccw_adapter_put(adapter);
181 return retval ? retval : (ssize_t) count;
182}
183static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
184 zfcp_sysfs_adapter_failed_show,
185 zfcp_sysfs_adapter_failed_store);
186
Swen Schillig60221922008-07-02 10:56:38 +0200187static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
188 struct device_attribute *attr,
189 const char *buf, size_t count)
190{
Swen Schilligde3dc572009-11-24 16:54:00 +0100191 struct ccw_device *cdev = to_ccwdev(dev);
192 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Swen Schillig60221922008-07-02 10:56:38 +0200193 int ret;
194
Swen Schilligde3dc572009-11-24 16:54:00 +0100195 if (!adapter)
196 return -ENODEV;
197
198 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
199 ret = -EBUSY;
200 goto out;
201 }
Swen Schillig60221922008-07-02 10:56:38 +0200202
Swen Schillig6f53a2d2009-08-18 15:43:23 +0200203 ret = zfcp_fc_scan_ports(adapter);
Swen Schilligde3dc572009-11-24 16:54:00 +0100204out:
205 zfcp_ccw_adapter_put(adapter);
Swen Schillig60221922008-07-02 10:56:38 +0200206 return ret ? ret : (ssize_t) count;
207}
208static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
209 zfcp_sysfs_port_rescan_store);
210
211static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
212 struct device_attribute *attr,
213 const char *buf, size_t count)
214{
Swen Schilligde3dc572009-11-24 16:54:00 +0100215 struct ccw_device *cdev = to_ccwdev(dev);
216 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Swen Schillig60221922008-07-02 10:56:38 +0200217 struct zfcp_port *port;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200218 u64 wwpn;
Swen Schillig60221922008-07-02 10:56:38 +0200219 int retval = 0;
220
Swen Schilligde3dc572009-11-24 16:54:00 +0100221 if (!adapter)
222 return -ENODEV;
223
Swen Schillig60221922008-07-02 10:56:38 +0200224 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
225 retval = -EBUSY;
226 goto out;
227 }
228
Swen Schillig7ba58c92008-10-01 12:42:18 +0200229 if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) {
Swen Schillig60221922008-07-02 10:56:38 +0200230 retval = -EINVAL;
231 goto out;
232 }
233
Swen Schillig60221922008-07-02 10:56:38 +0200234 port = zfcp_get_port_by_wwpn(adapter, wwpn);
Swen Schillig60221922008-07-02 10:56:38 +0200235 if (!port) {
236 retval = -ENXIO;
237 goto out;
238 }
239
Swen Schilligf3450c72009-11-24 16:53:59 +0100240 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
241
242 write_lock_irq(&adapter->port_list_lock);
243 list_del(&port->list);
244 write_unlock_irq(&adapter->port_list_lock);
245
246 put_device(&port->sysfs_device);
247
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100248 zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
Swen Schilligf3450c72009-11-24 16:53:59 +0100249 zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
Swen Schillig60221922008-07-02 10:56:38 +0200250 out:
Swen Schilligde3dc572009-11-24 16:54:00 +0100251 zfcp_ccw_adapter_put(adapter);
Swen Schillig60221922008-07-02 10:56:38 +0200252 return retval ? retval : (ssize_t) count;
253}
254static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
255 zfcp_sysfs_port_remove_store);
256
257static struct attribute *zfcp_adapter_attrs[] = {
258 &dev_attr_adapter_failed.attr,
259 &dev_attr_adapter_in_recovery.attr,
260 &dev_attr_adapter_port_remove.attr,
261 &dev_attr_adapter_port_rescan.attr,
262 &dev_attr_adapter_peer_wwnn.attr,
263 &dev_attr_adapter_peer_wwpn.attr,
264 &dev_attr_adapter_peer_d_id.attr,
265 &dev_attr_adapter_card_version.attr,
266 &dev_attr_adapter_lic_version.attr,
267 &dev_attr_adapter_status.attr,
268 &dev_attr_adapter_hardware_version.attr,
269 NULL
270};
271
272struct attribute_group zfcp_sysfs_adapter_attrs = {
273 .attrs = zfcp_adapter_attrs,
274};
275
276static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
277 struct device_attribute *attr,
278 const char *buf, size_t count)
279{
Christof Schmitt25458eb2009-11-24 16:54:02 +0100280 struct zfcp_port *port = container_of(dev, struct zfcp_port,
281 sysfs_device);
Swen Schillig60221922008-07-02 10:56:38 +0200282 struct zfcp_unit *unit;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200283 u64 fcp_lun;
Swen Schillig60221922008-07-02 10:56:38 +0200284 int retval = -EINVAL;
285
Swen Schillig60221922008-07-02 10:56:38 +0200286 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
287 retval = -EBUSY;
288 goto out;
289 }
290
Swen Schillig7ba58c92008-10-01 12:42:18 +0200291 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
Swen Schillig60221922008-07-02 10:56:38 +0200292 goto out;
293
294 unit = zfcp_unit_enqueue(port, fcp_lun);
295 if (IS_ERR(unit))
296 goto out;
297
298 retval = 0;
299
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100300 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
Swen Schillig60221922008-07-02 10:56:38 +0200301 zfcp_erp_wait(unit->port->adapter);
Christof Schmitt9e820af2009-10-13 10:44:11 +0200302 flush_work(&unit->scsi_work);
Swen Schillig60221922008-07-02 10:56:38 +0200303out:
Swen Schillig60221922008-07-02 10:56:38 +0200304 return retval ? retval : (ssize_t) count;
305}
306static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
307
308static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
309 struct device_attribute *attr,
310 const char *buf, size_t count)
311{
Christof Schmitt25458eb2009-11-24 16:54:02 +0100312 struct zfcp_port *port = container_of(dev, struct zfcp_port,
313 sysfs_device);
Swen Schillig60221922008-07-02 10:56:38 +0200314 struct zfcp_unit *unit;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200315 u64 fcp_lun;
Swen Schillig60221922008-07-02 10:56:38 +0200316 int retval = 0;
317
Swen Schillig60221922008-07-02 10:56:38 +0200318 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
319 retval = -EBUSY;
320 goto out;
321 }
322
Swen Schillig7ba58c92008-10-01 12:42:18 +0200323 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
Swen Schillig60221922008-07-02 10:56:38 +0200324 retval = -EINVAL;
325 goto out;
326 }
327
Swen Schillig60221922008-07-02 10:56:38 +0200328 unit = zfcp_get_unit_by_lun(port, fcp_lun);
Swen Schillig60221922008-07-02 10:56:38 +0200329 if (!unit) {
Swen Schilligecf0c772009-11-24 16:53:58 +0100330 retval = -EINVAL;
Swen Schillig60221922008-07-02 10:56:38 +0200331 goto out;
332 }
333
Swen Schilligecf0c772009-11-24 16:53:58 +0100334 /* wait for possible timeout during SCSI probe */
335 flush_work(&unit->scsi_work);
336
Swen Schilligf3450c72009-11-24 16:53:59 +0100337 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
Swen Schilligecf0c772009-11-24 16:53:58 +0100338
Swen Schilligf3450c72009-11-24 16:53:59 +0100339 write_lock_irq(&port->unit_list_lock);
340 list_del(&unit->list);
341 write_unlock_irq(&port->unit_list_lock);
Swen Schilligecf0c772009-11-24 16:53:58 +0100342
Swen Schilligf3450c72009-11-24 16:53:59 +0100343 put_device(&unit->sysfs_device);
344
345 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
346 zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
Swen Schillig60221922008-07-02 10:56:38 +0200347out:
Swen Schillig60221922008-07-02 10:56:38 +0200348 return retval ? retval : (ssize_t) count;
349}
350static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
351
Swen Schillig5ab944f2008-10-01 12:42:17 +0200352static struct attribute *zfcp_port_attrs[] = {
Swen Schillig60221922008-07-02 10:56:38 +0200353 &dev_attr_unit_add.attr,
354 &dev_attr_unit_remove.attr,
355 &dev_attr_port_failed.attr,
356 &dev_attr_port_in_recovery.attr,
357 &dev_attr_port_status.attr,
358 &dev_attr_port_access_denied.attr,
359 NULL
360};
361
362/**
363 * zfcp_sysfs_port_attrs - sysfs attributes for all other ports
364 */
365struct attribute_group zfcp_sysfs_port_attrs = {
Swen Schillig5ab944f2008-10-01 12:42:17 +0200366 .attrs = zfcp_port_attrs,
Swen Schillig60221922008-07-02 10:56:38 +0200367};
368
369static struct attribute *zfcp_unit_attrs[] = {
370 &dev_attr_unit_failed.attr,
371 &dev_attr_unit_in_recovery.attr,
372 &dev_attr_unit_status.attr,
373 &dev_attr_unit_access_denied.attr,
374 &dev_attr_unit_access_shared.attr,
375 &dev_attr_unit_access_readonly.attr,
376 NULL
377};
378
379struct attribute_group zfcp_sysfs_unit_attrs = {
380 .attrs = zfcp_unit_attrs,
381};
382
383#define ZFCP_DEFINE_LATENCY_ATTR(_name) \
384static ssize_t \
385zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \
386 struct device_attribute *attr, \
387 char *buf) { \
388 struct scsi_device *sdev = to_scsi_device(dev); \
389 struct zfcp_unit *unit = sdev->hostdata; \
390 struct zfcp_latencies *lat = &unit->latencies; \
391 struct zfcp_adapter *adapter = unit->port->adapter; \
Swen Schillig60221922008-07-02 10:56:38 +0200392 unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \
393 \
Christof Schmitt49f0f012009-03-02 13:08:57 +0100394 spin_lock_bh(&lat->lock); \
Swen Schillig60221922008-07-02 10:56:38 +0200395 fsum = lat->_name.fabric.sum * adapter->timer_ticks; \
396 fmin = lat->_name.fabric.min * adapter->timer_ticks; \
397 fmax = lat->_name.fabric.max * adapter->timer_ticks; \
398 csum = lat->_name.channel.sum * adapter->timer_ticks; \
399 cmin = lat->_name.channel.min * adapter->timer_ticks; \
400 cmax = lat->_name.channel.max * adapter->timer_ticks; \
401 cc = lat->_name.counter; \
Christof Schmitt49f0f012009-03-02 13:08:57 +0100402 spin_unlock_bh(&lat->lock); \
Swen Schillig60221922008-07-02 10:56:38 +0200403 \
404 do_div(fsum, 1000); \
405 do_div(fmin, 1000); \
406 do_div(fmax, 1000); \
407 do_div(csum, 1000); \
408 do_div(cmin, 1000); \
409 do_div(cmax, 1000); \
410 \
411 return sprintf(buf, "%llu %llu %llu %llu %llu %llu %llu\n", \
412 fmin, fmax, fsum, cmin, cmax, csum, cc); \
413} \
414static ssize_t \
415zfcp_sysfs_unit_##_name##_latency_store(struct device *dev, \
416 struct device_attribute *attr, \
417 const char *buf, size_t count) \
418{ \
419 struct scsi_device *sdev = to_scsi_device(dev); \
420 struct zfcp_unit *unit = sdev->hostdata; \
421 struct zfcp_latencies *lat = &unit->latencies; \
422 unsigned long flags; \
423 \
424 spin_lock_irqsave(&lat->lock, flags); \
425 lat->_name.fabric.sum = 0; \
426 lat->_name.fabric.min = 0xFFFFFFFF; \
427 lat->_name.fabric.max = 0; \
428 lat->_name.channel.sum = 0; \
429 lat->_name.channel.min = 0xFFFFFFFF; \
430 lat->_name.channel.max = 0; \
431 lat->_name.counter = 0; \
432 spin_unlock_irqrestore(&lat->lock, flags); \
433 \
434 return (ssize_t) count; \
435} \
436static DEVICE_ATTR(_name##_latency, S_IWUSR | S_IRUGO, \
437 zfcp_sysfs_unit_##_name##_latency_show, \
438 zfcp_sysfs_unit_##_name##_latency_store);
439
440ZFCP_DEFINE_LATENCY_ATTR(read);
441ZFCP_DEFINE_LATENCY_ATTR(write);
442ZFCP_DEFINE_LATENCY_ATTR(cmd);
443
444#define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value) \
445static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
446 struct device_attribute *attr,\
447 char *buf) \
448{ \
449 struct scsi_device *sdev = to_scsi_device(dev); \
450 struct zfcp_unit *unit = sdev->hostdata; \
451 \
452 return sprintf(buf, _format, _value); \
453} \
454static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
455
456ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
Cornelia Huckb9d3aed2008-10-10 21:33:11 +0200457 dev_name(&unit->port->adapter->ccw_device->dev));
Swen Schillig7ba58c92008-10-01 12:42:18 +0200458ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
459 (unsigned long long) unit->port->wwpn);
460ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
461 (unsigned long long) unit->fcp_lun);
Swen Schillig60221922008-07-02 10:56:38 +0200462
463struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
464 &dev_attr_fcp_lun,
465 &dev_attr_wwpn,
466 &dev_attr_hba_id,
467 &dev_attr_read_latency,
468 &dev_attr_write_latency,
469 &dev_attr_cmd_latency,
470 NULL
471};
472
473static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
474 struct device_attribute *attr,
475 char *buf)
476{
477 struct Scsi_Host *scsi_host = dev_to_shost(dev);
478 struct fsf_qtcb_bottom_port *qtcb_port;
479 struct zfcp_adapter *adapter;
480 int retval;
481
482 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
483 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
484 return -EOPNOTSUPP;
485
486 qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
487 if (!qtcb_port)
488 return -ENOMEM;
489
Swen Schillig564e1c82009-08-18 15:43:19 +0200490 retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
Swen Schillig60221922008-07-02 10:56:38 +0200491 if (!retval)
492 retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
493 qtcb_port->cb_util, qtcb_port->a_util);
494 kfree(qtcb_port);
495 return retval;
496}
497static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
498
499static int zfcp_sysfs_adapter_ex_config(struct device *dev,
500 struct fsf_statistics_info *stat_inf)
501{
502 struct Scsi_Host *scsi_host = dev_to_shost(dev);
503 struct fsf_qtcb_bottom_config *qtcb_config;
504 struct zfcp_adapter *adapter;
505 int retval;
506
507 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
508 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
509 return -EOPNOTSUPP;
510
511 qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
512 GFP_KERNEL);
513 if (!qtcb_config)
514 return -ENOMEM;
515
Swen Schillig564e1c82009-08-18 15:43:19 +0200516 retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
Swen Schillig60221922008-07-02 10:56:38 +0200517 if (!retval)
518 *stat_inf = qtcb_config->stat_info;
519
520 kfree(qtcb_config);
521 return retval;
522}
523
524#define ZFCP_SHOST_ATTR(_name, _format, _arg...) \
525static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
526 struct device_attribute *attr,\
527 char *buf) \
528{ \
529 struct fsf_statistics_info stat_info; \
530 int retval; \
531 \
532 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info); \
533 if (retval) \
534 return retval; \
535 \
536 return sprintf(buf, _format, ## _arg); \
537} \
538static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL);
539
540ZFCP_SHOST_ATTR(requests, "%llu %llu %llu\n",
541 (unsigned long long) stat_info.input_req,
542 (unsigned long long) stat_info.output_req,
543 (unsigned long long) stat_info.control_req);
544
545ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n",
546 (unsigned long long) stat_info.input_mb,
547 (unsigned long long) stat_info.output_mb);
548
549ZFCP_SHOST_ATTR(seconds_active, "%llu\n",
550 (unsigned long long) stat_info.seconds_act);
551
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200552static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
553 struct device_attribute *attr,
554 char *buf)
555{
556 struct Scsi_Host *scsi_host = class_to_shost(dev);
Swen Schillig564e1c82009-08-18 15:43:19 +0200557 struct zfcp_qdio *qdio =
558 ((struct zfcp_adapter *) scsi_host->hostdata[0])->qdio;
Christof Schmittacf7b862009-07-13 15:06:03 +0200559 u64 util;
560
Swen Schillig564e1c82009-08-18 15:43:19 +0200561 spin_lock_bh(&qdio->stat_lock);
562 util = qdio->req_q_util;
563 spin_unlock_bh(&qdio->stat_lock);
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200564
Swen Schillig564e1c82009-08-18 15:43:19 +0200565 return sprintf(buf, "%d %llu\n", atomic_read(&qdio->req_q_full),
Christof Schmittacf7b862009-07-13 15:06:03 +0200566 (unsigned long long)util);
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200567}
568static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
569
Swen Schillig60221922008-07-02 10:56:38 +0200570struct device_attribute *zfcp_sysfs_shost_attrs[] = {
571 &dev_attr_utilization,
572 &dev_attr_requests,
573 &dev_attr_megabytes,
574 &dev_attr_seconds_active,
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200575 &dev_attr_queue_full,
Swen Schillig60221922008-07-02 10:56:38 +0200576 NULL
577};