[PATCH] W1: w1_netlink: New init/fini netlink callbacks.
[linux-2.6/verdex.git] / drivers / s390 / scsi / zfcp_sysfs_port.c
blobc55e82d91deb103133047d823ce3b122de097271
1 /*
2 * linux/drivers/s390/scsi/zfcp_sysfs_port.c
4 * FCP adapter driver for IBM eServer zSeries
6 * sysfs port related routines
8 * (C) Copyright IBM Corp. 2003, 2004
10 * Authors:
11 * Martin Peschke <mpeschke@de.ibm.com>
12 * Heiko Carstens <heiko.carstens@de.ibm.com>
13 * Andreas Herrmann <aherrman@de.ibm.com>
14 * Volker Sameske <sameske@de.ibm.com>
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $"
33 #include "zfcp_ext.h"
35 #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
37 /**
38 * zfcp_sysfs_port_release - gets called when a struct device port is released
39 * @dev: pointer to belonging device
41 void
42 zfcp_sysfs_port_release(struct device *dev)
44 kfree(dev);
47 /**
48 * ZFCP_DEFINE_PORT_ATTR
49 * @_name: name of show attribute
50 * @_format: format string
51 * @_value: value to print
53 * Generates attributes for a port.
55 #define ZFCP_DEFINE_PORT_ATTR(_name, _format, _value) \
56 static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_attribute *attr, \
57 char *buf) \
58 { \
59 struct zfcp_port *port; \
61 port = dev_get_drvdata(dev); \
62 return sprintf(buf, _format, _value); \
63 } \
65 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
67 ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
68 ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
69 ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
70 ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
71 (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
72 ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
73 (ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status));
75 /**
76 * zfcp_sysfs_unit_add_store - add a unit to sysfs tree
77 * @dev: pointer to belonging device
78 * @buf: pointer to input buffer
79 * @count: number of bytes in buffer
81 * Store function of the "unit_add" attribute of a port.
83 static ssize_t
84 zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
86 fcp_lun_t fcp_lun;
87 char *endp;
88 struct zfcp_port *port;
89 struct zfcp_unit *unit;
90 int retval = -EINVAL;
92 down(&zfcp_data.config_sema);
94 port = dev_get_drvdata(dev);
95 if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) {
96 retval = -EBUSY;
97 goto out;
100 fcp_lun = simple_strtoull(buf, &endp, 0);
101 if ((endp + 1) < (buf + count))
102 goto out;
104 unit = zfcp_unit_enqueue(port, fcp_lun);
105 if (!unit)
106 goto out;
108 retval = 0;
110 zfcp_erp_unit_reopen(unit, 0);
111 zfcp_erp_wait(unit->port->adapter);
112 zfcp_unit_put(unit);
113 out:
114 up(&zfcp_data.config_sema);
115 return retval ? retval : (ssize_t) count;
118 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
121 * zfcp_sysfs_unit_remove_store - remove a unit from sysfs tree
122 * @dev: pointer to belonging device
123 * @buf: pointer to input buffer
124 * @count: number of bytes in buffer
126 static ssize_t
127 zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
129 struct zfcp_port *port;
130 struct zfcp_unit *unit;
131 fcp_lun_t fcp_lun;
132 char *endp;
133 int retval = 0;
135 down(&zfcp_data.config_sema);
137 port = dev_get_drvdata(dev);
138 if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) {
139 retval = -EBUSY;
140 goto out;
143 fcp_lun = simple_strtoull(buf, &endp, 0);
144 if ((endp + 1) < (buf + count)) {
145 retval = -EINVAL;
146 goto out;
149 write_lock_irq(&zfcp_data.config_lock);
150 unit = zfcp_get_unit_by_lun(port, fcp_lun);
151 if (unit && (atomic_read(&unit->refcount) == 0)) {
152 zfcp_unit_get(unit);
153 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
154 list_move(&unit->list, &port->unit_remove_lh);
156 else {
157 unit = NULL;
159 write_unlock_irq(&zfcp_data.config_lock);
161 if (!unit) {
162 retval = -ENXIO;
163 goto out;
166 zfcp_erp_unit_shutdown(unit, 0);
167 zfcp_erp_wait(unit->port->adapter);
168 zfcp_unit_put(unit);
169 zfcp_unit_dequeue(unit);
170 out:
171 up(&zfcp_data.config_sema);
172 return retval ? retval : (ssize_t) count;
175 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
178 * zfcp_sysfs_port_failed_store - failed state of port
179 * @dev: pointer to belonging device
180 * @buf: pointer to input buffer
181 * @count: number of bytes in buffer
183 * Store function of the "failed" attribute of a port.
184 * If a "0" gets written to "failed", error recovery will be
185 * started for the belonging port.
187 static ssize_t
188 zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
190 struct zfcp_port *port;
191 unsigned int val;
192 char *endp;
193 int retval = 0;
195 down(&zfcp_data.config_sema);
197 port = dev_get_drvdata(dev);
198 if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) {
199 retval = -EBUSY;
200 goto out;
203 val = simple_strtoul(buf, &endp, 0);
204 if (((endp + 1) < (buf + count)) || (val != 0)) {
205 retval = -EINVAL;
206 goto out;
209 zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
210 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
211 zfcp_erp_wait(port->adapter);
212 out:
213 up(&zfcp_data.config_sema);
214 return retval ? retval : (ssize_t) count;
218 * zfcp_sysfs_port_failed_show - failed state of port
219 * @dev: pointer to belonging device
220 * @buf: pointer to input buffer
222 * Show function of "failed" attribute of port. Will be
223 * "0" if port is working, otherwise "1".
225 static ssize_t
226 zfcp_sysfs_port_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
228 struct zfcp_port *port;
230 port = dev_get_drvdata(dev);
231 if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status))
232 return sprintf(buf, "1\n");
233 else
234 return sprintf(buf, "0\n");
237 static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show,
238 zfcp_sysfs_port_failed_store);
241 * zfcp_port_common_attrs
242 * sysfs attributes that are common for all kind of fc ports.
244 static struct attribute *zfcp_port_common_attrs[] = {
245 &dev_attr_failed.attr,
246 &dev_attr_in_recovery.attr,
247 &dev_attr_status.attr,
248 &dev_attr_wwnn.attr,
249 &dev_attr_d_id.attr,
250 &dev_attr_access_denied.attr,
251 NULL
254 static struct attribute_group zfcp_port_common_attr_group = {
255 .attrs = zfcp_port_common_attrs,
259 * zfcp_port_no_ns_attrs
260 * sysfs attributes not to be used for nameserver ports.
262 static struct attribute *zfcp_port_no_ns_attrs[] = {
263 &dev_attr_unit_add.attr,
264 &dev_attr_unit_remove.attr,
265 NULL
268 static struct attribute_group zfcp_port_no_ns_attr_group = {
269 .attrs = zfcp_port_no_ns_attrs,
273 * zfcp_sysfs_port_create_files - create sysfs port files
274 * @dev: pointer to belonging device
276 * Create all attributes of the sysfs representation of a port.
279 zfcp_sysfs_port_create_files(struct device *dev, u32 flags)
281 int retval;
283 retval = sysfs_create_group(&dev->kobj, &zfcp_port_common_attr_group);
285 if ((flags & ZFCP_STATUS_PORT_WKA) || retval)
286 return retval;
288 retval = sysfs_create_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
289 if (retval)
290 sysfs_remove_group(&dev->kobj, &zfcp_port_common_attr_group);
292 return retval;
296 * zfcp_sysfs_port_remove_files - remove sysfs port files
297 * @dev: pointer to belonging device
299 * Remove all attributes of the sysfs representation of a port.
301 void
302 zfcp_sysfs_port_remove_files(struct device *dev, u32 flags)
304 sysfs_remove_group(&dev->kobj, &zfcp_port_common_attr_group);
305 if (!(flags & ZFCP_STATUS_PORT_WKA))
306 sysfs_remove_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
309 #undef ZFCP_LOG_AREA