qeth_l2_sys.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright IBM Corp. 2013
  3. * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
  4. */
  5. #include <linux/slab.h>
  6. #include <asm/ebcdic.h>
  7. #include "qeth_core.h"
  8. #include "qeth_l2.h"
  9. #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  10. struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  11. static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
  12. struct device_attribute *attr, char *buf,
  13. int show_state)
  14. {
  15. struct qeth_card *card = dev_get_drvdata(dev);
  16. enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
  17. int rc = 0;
  18. char *word;
  19. if (!card)
  20. return -EINVAL;
  21. mutex_lock(&card->conf_mutex);
  22. if (qeth_card_hw_is_reachable(card) &&
  23. card->options.sbp.supported_funcs)
  24. rc = qeth_bridgeport_query_ports(card,
  25. &card->options.sbp.role, &state);
  26. if (!rc) {
  27. if (show_state)
  28. switch (state) {
  29. case QETH_SBP_STATE_INACTIVE:
  30. word = "inactive"; break;
  31. case QETH_SBP_STATE_STANDBY:
  32. word = "standby"; break;
  33. case QETH_SBP_STATE_ACTIVE:
  34. word = "active"; break;
  35. default:
  36. rc = -EIO;
  37. }
  38. else
  39. switch (card->options.sbp.role) {
  40. case QETH_SBP_ROLE_NONE:
  41. word = "none"; break;
  42. case QETH_SBP_ROLE_PRIMARY:
  43. word = "primary"; break;
  44. case QETH_SBP_ROLE_SECONDARY:
  45. word = "secondary"; break;
  46. default:
  47. rc = -EIO;
  48. }
  49. if (rc)
  50. QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
  51. card->options.sbp.role, state);
  52. else
  53. rc = sprintf(buf, "%s\n", word);
  54. }
  55. mutex_unlock(&card->conf_mutex);
  56. return rc;
  57. }
  58. static ssize_t qeth_bridge_port_role_show(struct device *dev,
  59. struct device_attribute *attr, char *buf)
  60. {
  61. return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
  62. }
  63. static ssize_t qeth_bridge_port_role_store(struct device *dev,
  64. struct device_attribute *attr, const char *buf, size_t count)
  65. {
  66. struct qeth_card *card = dev_get_drvdata(dev);
  67. int rc = 0;
  68. enum qeth_sbp_roles role;
  69. if (!card)
  70. return -EINVAL;
  71. if (sysfs_streq(buf, "primary"))
  72. role = QETH_SBP_ROLE_PRIMARY;
  73. else if (sysfs_streq(buf, "secondary"))
  74. role = QETH_SBP_ROLE_SECONDARY;
  75. else if (sysfs_streq(buf, "none"))
  76. role = QETH_SBP_ROLE_NONE;
  77. else
  78. return -EINVAL;
  79. mutex_lock(&card->conf_mutex);
  80. if (qeth_card_hw_is_reachable(card)) {
  81. rc = qeth_bridgeport_setrole(card, role);
  82. if (!rc)
  83. card->options.sbp.role = role;
  84. } else
  85. card->options.sbp.role = role;
  86. mutex_unlock(&card->conf_mutex);
  87. return rc ? rc : count;
  88. }
  89. static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
  90. qeth_bridge_port_role_store);
  91. static ssize_t qeth_bridge_port_state_show(struct device *dev,
  92. struct device_attribute *attr, char *buf)
  93. {
  94. return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
  95. }
  96. static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
  97. NULL);
  98. static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
  99. struct device_attribute *attr, char *buf)
  100. {
  101. struct qeth_card *card = dev_get_drvdata(dev);
  102. int enabled;
  103. if (!card)
  104. return -EINVAL;
  105. mutex_lock(&card->conf_mutex);
  106. enabled = card->options.sbp.hostnotification;
  107. mutex_unlock(&card->conf_mutex);
  108. return sprintf(buf, "%d\n", enabled);
  109. }
  110. static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
  111. struct device_attribute *attr, const char *buf, size_t count)
  112. {
  113. struct qeth_card *card = dev_get_drvdata(dev);
  114. int rc = 0;
  115. int enable;
  116. if (!card)
  117. return -EINVAL;
  118. if (sysfs_streq(buf, "0"))
  119. enable = 0;
  120. else if (sysfs_streq(buf, "1"))
  121. enable = 1;
  122. else
  123. return -EINVAL;
  124. mutex_lock(&card->conf_mutex);
  125. if (qeth_card_hw_is_reachable(card)) {
  126. rc = qeth_bridgeport_an_set(card, enable);
  127. if (!rc)
  128. card->options.sbp.hostnotification = enable;
  129. } else
  130. card->options.sbp.hostnotification = enable;
  131. mutex_unlock(&card->conf_mutex);
  132. return rc ? rc : count;
  133. }
  134. static DEVICE_ATTR(bridge_hostnotify, 0644,
  135. qeth_bridgeport_hostnotification_show,
  136. qeth_bridgeport_hostnotification_store);
  137. static struct attribute *qeth_l2_bridgeport_attrs[] = {
  138. &dev_attr_bridge_role.attr,
  139. &dev_attr_bridge_state.attr,
  140. &dev_attr_bridge_hostnotify.attr,
  141. NULL,
  142. };
  143. static struct attribute_group qeth_l2_bridgeport_attr_group = {
  144. .attrs = qeth_l2_bridgeport_attrs,
  145. };
  146. int qeth_l2_create_device_attributes(struct device *dev)
  147. {
  148. return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
  149. }
  150. void qeth_l2_remove_device_attributes(struct device *dev)
  151. {
  152. sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
  153. }
  154. /**
  155. * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
  156. * @card: qeth_card structure pointer
  157. *
  158. * Note: this function is called with conf_mutex held by the caller
  159. */
  160. void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
  161. {
  162. int rc;
  163. if (!card)
  164. return;
  165. if (!card->options.sbp.supported_funcs)
  166. return;
  167. if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
  168. /* Conditional to avoid spurious error messages */
  169. qeth_bridgeport_setrole(card, card->options.sbp.role);
  170. /* Let the callback function refresh the stored role value. */
  171. qeth_bridgeport_query_ports(card,
  172. &card->options.sbp.role, NULL);
  173. }
  174. if (card->options.sbp.hostnotification) {
  175. rc = qeth_bridgeport_an_set(card, 1);
  176. if (rc)
  177. card->options.sbp.hostnotification = 0;
  178. } else
  179. qeth_bridgeport_an_set(card, 0);
  180. }