diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2005-08-31 21:29:20 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-31 22:42:46 -0400 |
commit | 76812d81238cda5c5c4060da27517a08287620fc (patch) | |
tree | 461d70f89c14cfc4586729ad082c92cee3306f4e | |
parent | db5e8718eac0b8166d6fd05b1ed7f8114c243988 (diff) |
[PATCH] iseries_veth: Add sysfs support for connection structs
To aid in field debugging, add sysfs support for iseries_veth's connection
structures. At the moment this is all read-only, however we could think about
adding write support for some attributes in future.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/net/iseries_veth.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index b945bf02d257..25481ea67474 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -182,10 +182,6 @@ static void veth_release_connection(struct kobject *kobject); | |||
182 | static void veth_timed_ack(unsigned long ptr); | 182 | static void veth_timed_ack(unsigned long ptr); |
183 | static void veth_timed_reset(unsigned long ptr); | 183 | static void veth_timed_reset(unsigned long ptr); |
184 | 184 | ||
185 | static struct kobj_type veth_lpar_connection_ktype = { | ||
186 | .release = veth_release_connection | ||
187 | }; | ||
188 | |||
189 | /* | 185 | /* |
190 | * Utility functions | 186 | * Utility functions |
191 | */ | 187 | */ |
@@ -280,6 +276,81 @@ static int veth_allocate_events(HvLpIndex rlp, int number) | |||
280 | } | 276 | } |
281 | 277 | ||
282 | /* | 278 | /* |
279 | * sysfs support | ||
280 | */ | ||
281 | |||
282 | struct veth_cnx_attribute { | ||
283 | struct attribute attr; | ||
284 | ssize_t (*show)(struct veth_lpar_connection *, char *buf); | ||
285 | ssize_t (*store)(struct veth_lpar_connection *, const char *buf); | ||
286 | }; | ||
287 | |||
288 | static ssize_t veth_cnx_attribute_show(struct kobject *kobj, | ||
289 | struct attribute *attr, char *buf) | ||
290 | { | ||
291 | struct veth_cnx_attribute *cnx_attr; | ||
292 | struct veth_lpar_connection *cnx; | ||
293 | |||
294 | cnx_attr = container_of(attr, struct veth_cnx_attribute, attr); | ||
295 | cnx = container_of(kobj, struct veth_lpar_connection, kobject); | ||
296 | |||
297 | if (!cnx_attr->show) | ||
298 | return -EIO; | ||
299 | |||
300 | return cnx_attr->show(cnx, buf); | ||
301 | } | ||
302 | |||
303 | #define CUSTOM_CNX_ATTR(_name, _format, _expression) \ | ||
304 | static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\ | ||
305 | { \ | ||
306 | return sprintf(buf, _format, _expression); \ | ||
307 | } \ | ||
308 | struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name) | ||
309 | |||
310 | #define SIMPLE_CNX_ATTR(_name) \ | ||
311 | CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name) | ||
312 | |||
313 | SIMPLE_CNX_ATTR(outstanding_tx); | ||
314 | SIMPLE_CNX_ATTR(remote_lp); | ||
315 | SIMPLE_CNX_ATTR(num_events); | ||
316 | SIMPLE_CNX_ATTR(src_inst); | ||
317 | SIMPLE_CNX_ATTR(dst_inst); | ||
318 | SIMPLE_CNX_ATTR(num_pending_acks); | ||
319 | SIMPLE_CNX_ATTR(num_ack_events); | ||
320 | CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout)); | ||
321 | CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout)); | ||
322 | CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state); | ||
323 | CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ? | ||
324 | jiffies_to_msecs(jiffies - cnx->last_contact) : 0); | ||
325 | |||
326 | #define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr) | ||
327 | |||
328 | static struct attribute *veth_cnx_default_attrs[] = { | ||
329 | GET_CNX_ATTR(outstanding_tx), | ||
330 | GET_CNX_ATTR(remote_lp), | ||
331 | GET_CNX_ATTR(num_events), | ||
332 | GET_CNX_ATTR(reset_timeout), | ||
333 | GET_CNX_ATTR(last_contact), | ||
334 | GET_CNX_ATTR(state), | ||
335 | GET_CNX_ATTR(src_inst), | ||
336 | GET_CNX_ATTR(dst_inst), | ||
337 | GET_CNX_ATTR(num_pending_acks), | ||
338 | GET_CNX_ATTR(num_ack_events), | ||
339 | GET_CNX_ATTR(ack_timeout), | ||
340 | NULL | ||
341 | }; | ||
342 | |||
343 | static struct sysfs_ops veth_cnx_sysfs_ops = { | ||
344 | .show = veth_cnx_attribute_show | ||
345 | }; | ||
346 | |||
347 | static struct kobj_type veth_lpar_connection_ktype = { | ||
348 | .release = veth_release_connection, | ||
349 | .sysfs_ops = &veth_cnx_sysfs_ops, | ||
350 | .default_attrs = veth_cnx_default_attrs | ||
351 | }; | ||
352 | |||
353 | /* | ||
283 | * LPAR connection code | 354 | * LPAR connection code |
284 | */ | 355 | */ |
285 | 356 | ||
@@ -1493,6 +1564,8 @@ void __exit veth_module_cleanup(void) | |||
1493 | if (!cnx) | 1564 | if (!cnx) |
1494 | continue; | 1565 | continue; |
1495 | 1566 | ||
1567 | /* Remove the connection from sysfs */ | ||
1568 | kobject_del(&cnx->kobject); | ||
1496 | /* Drop the driver's reference to the connection */ | 1569 | /* Drop the driver's reference to the connection */ |
1497 | kobject_put(&cnx->kobject); | 1570 | kobject_put(&cnx->kobject); |
1498 | } | 1571 | } |
@@ -1523,6 +1596,19 @@ int __init veth_module_init(void) | |||
1523 | if (rc != 0) | 1596 | if (rc != 0) |
1524 | goto error; | 1597 | goto error; |
1525 | 1598 | ||
1599 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { | ||
1600 | struct kobject *kobj; | ||
1601 | |||
1602 | if (!veth_cnx[i]) | ||
1603 | continue; | ||
1604 | |||
1605 | kobj = &veth_cnx[i]->kobject; | ||
1606 | kobj->parent = &veth_driver.driver.kobj; | ||
1607 | /* If the add failes, complain but otherwise continue */ | ||
1608 | if (0 != kobject_add(kobj)) | ||
1609 | veth_error("cnx %d: Failed adding to sysfs.\n", i); | ||
1610 | } | ||
1611 | |||
1526 | return 0; | 1612 | return 0; |
1527 | 1613 | ||
1528 | error: | 1614 | error: |