qeth_l2_sys.c 5.3 KB

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