blob: 181bea0f10fb553fe12483dae8f0f7b1265dd00b [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{ \
22 struct _feat_def *_feat = dev_get_drvdata(dev); \
23 \
24 return sprintf(buf, _format, _value); \
25} \
26static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
27 zfcp_sysfs_##_feat##_##_name##_show, NULL);
28
Swen Schilligde3dc572009-11-24 16:54:00 +010029#define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \
30static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
31 struct device_attribute *at,\
32 char *buf) \
33{ \
34 struct ccw_device *cdev = to_ccwdev(dev); \
35 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); \
36 int i; \
37 \
38 if (!adapter) \
39 return -ENODEV; \
40 \
41 i = sprintf(buf, _format, _value); \
42 zfcp_ccw_adapter_put(adapter); \
43 return i; \
44} \
45static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \
46 zfcp_sysfs_adapter_##_name##_show, NULL);
47
48ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
49ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n",
50 (unsigned long long) adapter->peer_wwnn);
51ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n",
52 (unsigned long long) adapter->peer_wwpn);
53ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
54ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
55ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
56ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version);
57ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) &
58 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
Swen Schillig60221922008-07-02 10:56:38 +020059
60ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
61 atomic_read(&port->status));
62ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
63 (atomic_read(&port->status) &
64 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
65ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
66 (atomic_read(&port->status) &
67 ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
68
69ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
70 atomic_read(&unit->status));
71ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
72 (atomic_read(&unit->status) &
73 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
74ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
75 (atomic_read(&unit->status) &
76 ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
77ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
78 (atomic_read(&unit->status) &
79 ZFCP_STATUS_UNIT_SHARED) != 0);
80ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
81 (atomic_read(&unit->status) &
82 ZFCP_STATUS_UNIT_READONLY) != 0);
83
84#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id) \
85static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \
86 struct device_attribute *attr, \
87 char *buf) \
88{ \
89 struct _feat_def *_feat = dev_get_drvdata(dev); \
90 \
91 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \
92 return sprintf(buf, "1\n"); \
93 else \
94 return sprintf(buf, "0\n"); \
95} \
96static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
97 struct device_attribute *attr,\
98 const char *buf, size_t count)\
99{ \
100 struct _feat_def *_feat = dev_get_drvdata(dev); \
101 unsigned long val; \
102 int retval = 0; \
103 \
Swen Schillig60221922008-07-02 10:56:38 +0200104 if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \
105 retval = -EBUSY; \
106 goto out; \
107 } \
108 \
109 if (strict_strtoul(buf, 0, &val) || val != 0) { \
110 retval = -EINVAL; \
111 goto out; \
112 } \
113 \
114 zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL, \
115 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
116 zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED, \
117 _reopen_id, NULL); \
118 zfcp_erp_wait(_adapter); \
119out: \
Swen Schillig60221922008-07-02 10:56:38 +0200120 return retval ? retval : (ssize_t) count; \
121} \
122static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
123 zfcp_sysfs_##_feat##_failed_show, \
124 zfcp_sysfs_##_feat##_failed_store);
125
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100126ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
127ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
Swen Schillig60221922008-07-02 10:56:38 +0200128
Swen Schilligde3dc572009-11-24 16:54:00 +0100129static 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 (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
162 retval = -EBUSY;
163 goto out;
164 }
165
166 if (strict_strtoul(buf, 0, &val) || val != 0) {
167 retval = -EINVAL;
168 goto out;
169 }
170
171 zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
172 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
173 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
174 "syafai2", NULL);
175 zfcp_erp_wait(adapter);
176out:
177 zfcp_ccw_adapter_put(adapter);
178 return retval ? retval : (ssize_t) count;
179}
180static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
181 zfcp_sysfs_adapter_failed_show,
182 zfcp_sysfs_adapter_failed_store);
183
Swen Schillig60221922008-07-02 10:56:38 +0200184static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
185 struct device_attribute *attr,
186 const char *buf, size_t count)
187{
Swen Schilligde3dc572009-11-24 16:54:00 +0100188 struct ccw_device *cdev = to_ccwdev(dev);
189 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Swen Schillig60221922008-07-02 10:56:38 +0200190 int ret;
191
Swen Schilligde3dc572009-11-24 16:54:00 +0100192 if (!adapter)
193 return -ENODEV;
194
195 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
196 ret = -EBUSY;
197 goto out;
198 }
Swen Schillig60221922008-07-02 10:56:38 +0200199
Swen Schillig6f53a2d2009-08-18 15:43:23 +0200200 ret = zfcp_fc_scan_ports(adapter);
Swen Schilligde3dc572009-11-24 16:54:00 +0100201out:
202 zfcp_ccw_adapter_put(adapter);
Swen Schillig60221922008-07-02 10:56:38 +0200203 return ret ? ret : (ssize_t) count;
204}
205static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
206 zfcp_sysfs_port_rescan_store);
207
208static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
209 struct device_attribute *attr,
210 const char *buf, size_t count)
211{
Swen Schilligde3dc572009-11-24 16:54:00 +0100212 struct ccw_device *cdev = to_ccwdev(dev);
213 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Swen Schillig60221922008-07-02 10:56:38 +0200214 struct zfcp_port *port;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200215 u64 wwpn;
Swen Schillig60221922008-07-02 10:56:38 +0200216 int retval = 0;
217
Swen Schilligde3dc572009-11-24 16:54:00 +0100218 if (!adapter)
219 return -ENODEV;
220
Swen Schillig60221922008-07-02 10:56:38 +0200221 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
222 retval = -EBUSY;
223 goto out;
224 }
225
Swen Schillig7ba58c92008-10-01 12:42:18 +0200226 if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) {
Swen Schillig60221922008-07-02 10:56:38 +0200227 retval = -EINVAL;
228 goto out;
229 }
230
Swen Schillig60221922008-07-02 10:56:38 +0200231 port = zfcp_get_port_by_wwpn(adapter, wwpn);
Swen Schillig60221922008-07-02 10:56:38 +0200232 if (!port) {
233 retval = -ENXIO;
234 goto out;
235 }
236
Swen Schilligf3450c72009-11-24 16:53:59 +0100237 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
238
239 write_lock_irq(&adapter->port_list_lock);
240 list_del(&port->list);
241 write_unlock_irq(&adapter->port_list_lock);
242
243 put_device(&port->sysfs_device);
244
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100245 zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
Swen Schilligf3450c72009-11-24 16:53:59 +0100246 zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
Swen Schillig60221922008-07-02 10:56:38 +0200247 out:
Swen Schilligde3dc572009-11-24 16:54:00 +0100248 zfcp_ccw_adapter_put(adapter);
Swen Schillig60221922008-07-02 10:56:38 +0200249 return retval ? retval : (ssize_t) count;
250}
251static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
252 zfcp_sysfs_port_remove_store);
253
254static struct attribute *zfcp_adapter_attrs[] = {
255 &dev_attr_adapter_failed.attr,
256 &dev_attr_adapter_in_recovery.attr,
257 &dev_attr_adapter_port_remove.attr,
258 &dev_attr_adapter_port_rescan.attr,
259 &dev_attr_adapter_peer_wwnn.attr,
260 &dev_attr_adapter_peer_wwpn.attr,
261 &dev_attr_adapter_peer_d_id.attr,
262 &dev_attr_adapter_card_version.attr,
263 &dev_attr_adapter_lic_version.attr,
264 &dev_attr_adapter_status.attr,
265 &dev_attr_adapter_hardware_version.attr,
266 NULL
267};
268
269struct attribute_group zfcp_sysfs_adapter_attrs = {
270 .attrs = zfcp_adapter_attrs,
271};
272
273static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
274 struct device_attribute *attr,
275 const char *buf, size_t count)
276{
277 struct zfcp_port *port = dev_get_drvdata(dev);
278 struct zfcp_unit *unit;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200279 u64 fcp_lun;
Swen Schillig60221922008-07-02 10:56:38 +0200280 int retval = -EINVAL;
281
Swen Schillig60221922008-07-02 10:56:38 +0200282 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
283 retval = -EBUSY;
284 goto out;
285 }
286
Swen Schillig7ba58c92008-10-01 12:42:18 +0200287 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
Swen Schillig60221922008-07-02 10:56:38 +0200288 goto out;
289
290 unit = zfcp_unit_enqueue(port, fcp_lun);
291 if (IS_ERR(unit))
292 goto out;
293
294 retval = 0;
295
Swen Schillig5ffd51a2009-03-02 13:09:04 +0100296 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
Swen Schillig60221922008-07-02 10:56:38 +0200297 zfcp_erp_wait(unit->port->adapter);
Christof Schmitt9e820af2009-10-13 10:44:11 +0200298 flush_work(&unit->scsi_work);
Swen Schillig60221922008-07-02 10:56:38 +0200299out:
Swen Schillig60221922008-07-02 10:56:38 +0200300 return retval ? retval : (ssize_t) count;
301}
302static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
303
304static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
305 struct device_attribute *attr,
306 const char *buf, size_t count)
307{
308 struct zfcp_port *port = dev_get_drvdata(dev);
309 struct zfcp_unit *unit;
Swen Schillig7ba58c92008-10-01 12:42:18 +0200310 u64 fcp_lun;
Swen Schillig60221922008-07-02 10:56:38 +0200311 int retval = 0;
312
Swen Schillig60221922008-07-02 10:56:38 +0200313 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
314 retval = -EBUSY;
315 goto out;
316 }
317
Swen Schillig7ba58c92008-10-01 12:42:18 +0200318 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
Swen Schillig60221922008-07-02 10:56:38 +0200319 retval = -EINVAL;
320 goto out;
321 }
322
Swen Schillig60221922008-07-02 10:56:38 +0200323 unit = zfcp_get_unit_by_lun(port, fcp_lun);
Swen Schillig60221922008-07-02 10:56:38 +0200324 if (!unit) {
Swen Schilligecf0c772009-11-24 16:53:58 +0100325 retval = -EINVAL;
Swen Schillig60221922008-07-02 10:56:38 +0200326 goto out;
327 }
328
Swen Schilligecf0c772009-11-24 16:53:58 +0100329 /* wait for possible timeout during SCSI probe */
330 flush_work(&unit->scsi_work);
331
Swen Schilligf3450c72009-11-24 16:53:59 +0100332 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
Swen Schilligecf0c772009-11-24 16:53:58 +0100333
Swen Schilligf3450c72009-11-24 16:53:59 +0100334 write_lock_irq(&port->unit_list_lock);
335 list_del(&unit->list);
336 write_unlock_irq(&port->unit_list_lock);
Swen Schilligecf0c772009-11-24 16:53:58 +0100337
Swen Schilligf3450c72009-11-24 16:53:59 +0100338 put_device(&unit->sysfs_device);
339
340 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
341 zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
Swen Schillig60221922008-07-02 10:56:38 +0200342out:
Swen Schillig60221922008-07-02 10:56:38 +0200343 return retval ? retval : (ssize_t) count;
344}
345static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
346
Swen Schillig5ab944f2008-10-01 12:42:17 +0200347static struct attribute *zfcp_port_attrs[] = {
Swen Schillig60221922008-07-02 10:56:38 +0200348 &dev_attr_unit_add.attr,
349 &dev_attr_unit_remove.attr,
350 &dev_attr_port_failed.attr,
351 &dev_attr_port_in_recovery.attr,
352 &dev_attr_port_status.attr,
353 &dev_attr_port_access_denied.attr,
354 NULL
355};
356
357/**
358 * zfcp_sysfs_port_attrs - sysfs attributes for all other ports
359 */
360struct attribute_group zfcp_sysfs_port_attrs = {
Swen Schillig5ab944f2008-10-01 12:42:17 +0200361 .attrs = zfcp_port_attrs,
Swen Schillig60221922008-07-02 10:56:38 +0200362};
363
364static struct attribute *zfcp_unit_attrs[] = {
365 &dev_attr_unit_failed.attr,
366 &dev_attr_unit_in_recovery.attr,
367 &dev_attr_unit_status.attr,
368 &dev_attr_unit_access_denied.attr,
369 &dev_attr_unit_access_shared.attr,
370 &dev_attr_unit_access_readonly.attr,
371 NULL
372};
373
374struct attribute_group zfcp_sysfs_unit_attrs = {
375 .attrs = zfcp_unit_attrs,
376};
377
378#define ZFCP_DEFINE_LATENCY_ATTR(_name) \
379static ssize_t \
380zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \
381 struct device_attribute *attr, \
382 char *buf) { \
383 struct scsi_device *sdev = to_scsi_device(dev); \
384 struct zfcp_unit *unit = sdev->hostdata; \
385 struct zfcp_latencies *lat = &unit->latencies; \
386 struct zfcp_adapter *adapter = unit->port->adapter; \
Swen Schillig60221922008-07-02 10:56:38 +0200387 unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \
388 \
Christof Schmitt49f0f012009-03-02 13:08:57 +0100389 spin_lock_bh(&lat->lock); \
Swen Schillig60221922008-07-02 10:56:38 +0200390 fsum = lat->_name.fabric.sum * adapter->timer_ticks; \
391 fmin = lat->_name.fabric.min * adapter->timer_ticks; \
392 fmax = lat->_name.fabric.max * adapter->timer_ticks; \
393 csum = lat->_name.channel.sum * adapter->timer_ticks; \
394 cmin = lat->_name.channel.min * adapter->timer_ticks; \
395 cmax = lat->_name.channel.max * adapter->timer_ticks; \
396 cc = lat->_name.counter; \
Christof Schmitt49f0f012009-03-02 13:08:57 +0100397 spin_unlock_bh(&lat->lock); \
Swen Schillig60221922008-07-02 10:56:38 +0200398 \
399 do_div(fsum, 1000); \
400 do_div(fmin, 1000); \
401 do_div(fmax, 1000); \
402 do_div(csum, 1000); \
403 do_div(cmin, 1000); \
404 do_div(cmax, 1000); \
405 \
406 return sprintf(buf, "%llu %llu %llu %llu %llu %llu %llu\n", \
407 fmin, fmax, fsum, cmin, cmax, csum, cc); \
408} \
409static ssize_t \
410zfcp_sysfs_unit_##_name##_latency_store(struct device *dev, \
411 struct device_attribute *attr, \
412 const char *buf, size_t count) \
413{ \
414 struct scsi_device *sdev = to_scsi_device(dev); \
415 struct zfcp_unit *unit = sdev->hostdata; \
416 struct zfcp_latencies *lat = &unit->latencies; \
417 unsigned long flags; \
418 \
419 spin_lock_irqsave(&lat->lock, flags); \
420 lat->_name.fabric.sum = 0; \
421 lat->_name.fabric.min = 0xFFFFFFFF; \
422 lat->_name.fabric.max = 0; \
423 lat->_name.channel.sum = 0; \
424 lat->_name.channel.min = 0xFFFFFFFF; \
425 lat->_name.channel.max = 0; \
426 lat->_name.counter = 0; \
427 spin_unlock_irqrestore(&lat->lock, flags); \
428 \
429 return (ssize_t) count; \
430} \
431static DEVICE_ATTR(_name##_latency, S_IWUSR | S_IRUGO, \
432 zfcp_sysfs_unit_##_name##_latency_show, \
433 zfcp_sysfs_unit_##_name##_latency_store);
434
435ZFCP_DEFINE_LATENCY_ATTR(read);
436ZFCP_DEFINE_LATENCY_ATTR(write);
437ZFCP_DEFINE_LATENCY_ATTR(cmd);
438
439#define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value) \
440static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
441 struct device_attribute *attr,\
442 char *buf) \
443{ \
444 struct scsi_device *sdev = to_scsi_device(dev); \
445 struct zfcp_unit *unit = sdev->hostdata; \
446 \
447 return sprintf(buf, _format, _value); \
448} \
449static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
450
451ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
Cornelia Huckb9d3aed2008-10-10 21:33:11 +0200452 dev_name(&unit->port->adapter->ccw_device->dev));
Swen Schillig7ba58c92008-10-01 12:42:18 +0200453ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
454 (unsigned long long) unit->port->wwpn);
455ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
456 (unsigned long long) unit->fcp_lun);
Swen Schillig60221922008-07-02 10:56:38 +0200457
458struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
459 &dev_attr_fcp_lun,
460 &dev_attr_wwpn,
461 &dev_attr_hba_id,
462 &dev_attr_read_latency,
463 &dev_attr_write_latency,
464 &dev_attr_cmd_latency,
465 NULL
466};
467
468static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
469 struct device_attribute *attr,
470 char *buf)
471{
472 struct Scsi_Host *scsi_host = dev_to_shost(dev);
473 struct fsf_qtcb_bottom_port *qtcb_port;
474 struct zfcp_adapter *adapter;
475 int retval;
476
477 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
478 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
479 return -EOPNOTSUPP;
480
481 qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
482 if (!qtcb_port)
483 return -ENOMEM;
484
Swen Schillig564e1c82009-08-18 15:43:19 +0200485 retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
Swen Schillig60221922008-07-02 10:56:38 +0200486 if (!retval)
487 retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
488 qtcb_port->cb_util, qtcb_port->a_util);
489 kfree(qtcb_port);
490 return retval;
491}
492static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
493
494static int zfcp_sysfs_adapter_ex_config(struct device *dev,
495 struct fsf_statistics_info *stat_inf)
496{
497 struct Scsi_Host *scsi_host = dev_to_shost(dev);
498 struct fsf_qtcb_bottom_config *qtcb_config;
499 struct zfcp_adapter *adapter;
500 int retval;
501
502 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
503 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
504 return -EOPNOTSUPP;
505
506 qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
507 GFP_KERNEL);
508 if (!qtcb_config)
509 return -ENOMEM;
510
Swen Schillig564e1c82009-08-18 15:43:19 +0200511 retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
Swen Schillig60221922008-07-02 10:56:38 +0200512 if (!retval)
513 *stat_inf = qtcb_config->stat_info;
514
515 kfree(qtcb_config);
516 return retval;
517}
518
519#define ZFCP_SHOST_ATTR(_name, _format, _arg...) \
520static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
521 struct device_attribute *attr,\
522 char *buf) \
523{ \
524 struct fsf_statistics_info stat_info; \
525 int retval; \
526 \
527 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info); \
528 if (retval) \
529 return retval; \
530 \
531 return sprintf(buf, _format, ## _arg); \
532} \
533static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL);
534
535ZFCP_SHOST_ATTR(requests, "%llu %llu %llu\n",
536 (unsigned long long) stat_info.input_req,
537 (unsigned long long) stat_info.output_req,
538 (unsigned long long) stat_info.control_req);
539
540ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n",
541 (unsigned long long) stat_info.input_mb,
542 (unsigned long long) stat_info.output_mb);
543
544ZFCP_SHOST_ATTR(seconds_active, "%llu\n",
545 (unsigned long long) stat_info.seconds_act);
546
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200547static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
548 struct device_attribute *attr,
549 char *buf)
550{
551 struct Scsi_Host *scsi_host = class_to_shost(dev);
Swen Schillig564e1c82009-08-18 15:43:19 +0200552 struct zfcp_qdio *qdio =
553 ((struct zfcp_adapter *) scsi_host->hostdata[0])->qdio;
Christof Schmittacf7b862009-07-13 15:06:03 +0200554 u64 util;
555
Swen Schillig564e1c82009-08-18 15:43:19 +0200556 spin_lock_bh(&qdio->stat_lock);
557 util = qdio->req_q_util;
558 spin_unlock_bh(&qdio->stat_lock);
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200559
Swen Schillig564e1c82009-08-18 15:43:19 +0200560 return sprintf(buf, "%d %llu\n", atomic_read(&qdio->req_q_full),
Christof Schmittacf7b862009-07-13 15:06:03 +0200561 (unsigned long long)util);
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200562}
563static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
564
Swen Schillig60221922008-07-02 10:56:38 +0200565struct device_attribute *zfcp_sysfs_shost_attrs[] = {
566 &dev_attr_utilization,
567 &dev_attr_requests,
568 &dev_attr_megabytes,
569 &dev_attr_seconds_active,
Stefan Raspl2450d3e2008-10-01 12:42:14 +0200570 &dev_attr_queue_full,
Swen Schillig60221922008-07-02 10:56:38 +0200571 NULL
572};