qeth_l3_sys.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /*
  2. * drivers/s390/net/qeth_l3_sys.c
  3. *
  4. * Copyright IBM Corp. 2007
  5. * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  6. * Frank Pavlic <fpavlic@de.ibm.com>,
  7. * Thomas Spatzier <tspat@de.ibm.com>,
  8. * Frank Blaschka <frank.blaschka@de.ibm.com>
  9. */
  10. #include "qeth_l3.h"
  11. #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  12. struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  13. static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
  14. {
  15. if (card->options.checksum_type == SW_CHECKSUMMING)
  16. return "sw";
  17. else if (card->options.checksum_type == HW_CHECKSUMMING)
  18. return "hw";
  19. else
  20. return "no";
  21. }
  22. static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
  23. struct qeth_routing_info *route, char *buf)
  24. {
  25. switch (route->type) {
  26. case PRIMARY_ROUTER:
  27. return sprintf(buf, "%s\n", "primary router");
  28. case SECONDARY_ROUTER:
  29. return sprintf(buf, "%s\n", "secondary router");
  30. case MULTICAST_ROUTER:
  31. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  32. return sprintf(buf, "%s\n", "multicast router+");
  33. else
  34. return sprintf(buf, "%s\n", "multicast router");
  35. case PRIMARY_CONNECTOR:
  36. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  37. return sprintf(buf, "%s\n", "primary connector+");
  38. else
  39. return sprintf(buf, "%s\n", "primary connector");
  40. case SECONDARY_CONNECTOR:
  41. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  42. return sprintf(buf, "%s\n", "secondary connector+");
  43. else
  44. return sprintf(buf, "%s\n", "secondary connector");
  45. default:
  46. return sprintf(buf, "%s\n", "no");
  47. }
  48. }
  49. static ssize_t qeth_l3_dev_route4_show(struct device *dev,
  50. struct device_attribute *attr, char *buf)
  51. {
  52. struct qeth_card *card = dev_get_drvdata(dev);
  53. if (!card)
  54. return -EINVAL;
  55. return qeth_l3_dev_route_show(card, &card->options.route4, buf);
  56. }
  57. static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
  58. struct qeth_routing_info *route, enum qeth_prot_versions prot,
  59. const char *buf, size_t count)
  60. {
  61. enum qeth_routing_types old_route_type = route->type;
  62. char *tmp;
  63. int rc;
  64. tmp = strsep((char **) &buf, "\n");
  65. if (!strcmp(tmp, "no_router")) {
  66. route->type = NO_ROUTER;
  67. } else if (!strcmp(tmp, "primary_connector")) {
  68. route->type = PRIMARY_CONNECTOR;
  69. } else if (!strcmp(tmp, "secondary_connector")) {
  70. route->type = SECONDARY_CONNECTOR;
  71. } else if (!strcmp(tmp, "primary_router")) {
  72. route->type = PRIMARY_ROUTER;
  73. } else if (!strcmp(tmp, "secondary_router")) {
  74. route->type = SECONDARY_ROUTER;
  75. } else if (!strcmp(tmp, "multicast_router")) {
  76. route->type = MULTICAST_ROUTER;
  77. } else {
  78. return -EINVAL;
  79. }
  80. if (((card->state == CARD_STATE_SOFTSETUP) ||
  81. (card->state == CARD_STATE_UP)) &&
  82. (old_route_type != route->type)) {
  83. if (prot == QETH_PROT_IPV4)
  84. rc = qeth_l3_setrouting_v4(card);
  85. else if (prot == QETH_PROT_IPV6)
  86. rc = qeth_l3_setrouting_v6(card);
  87. }
  88. return count;
  89. }
  90. static ssize_t qeth_l3_dev_route4_store(struct device *dev,
  91. struct device_attribute *attr, const char *buf, size_t count)
  92. {
  93. struct qeth_card *card = dev_get_drvdata(dev);
  94. if (!card)
  95. return -EINVAL;
  96. return qeth_l3_dev_route_store(card, &card->options.route4,
  97. QETH_PROT_IPV4, buf, count);
  98. }
  99. static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
  100. qeth_l3_dev_route4_store);
  101. static ssize_t qeth_l3_dev_route6_show(struct device *dev,
  102. struct device_attribute *attr, char *buf)
  103. {
  104. struct qeth_card *card = dev_get_drvdata(dev);
  105. if (!card)
  106. return -EINVAL;
  107. return qeth_l3_dev_route_show(card, &card->options.route6, buf);
  108. }
  109. static ssize_t qeth_l3_dev_route6_store(struct device *dev,
  110. struct device_attribute *attr, const char *buf, size_t count)
  111. {
  112. struct qeth_card *card = dev_get_drvdata(dev);
  113. if (!card)
  114. return -EINVAL;
  115. return qeth_l3_dev_route_store(card, &card->options.route6,
  116. QETH_PROT_IPV6, buf, count);
  117. }
  118. static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
  119. qeth_l3_dev_route6_store);
  120. static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
  121. struct device_attribute *attr, char *buf)
  122. {
  123. struct qeth_card *card = dev_get_drvdata(dev);
  124. if (!card)
  125. return -EINVAL;
  126. return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
  127. }
  128. static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
  129. struct device_attribute *attr, const char *buf, size_t count)
  130. {
  131. struct qeth_card *card = dev_get_drvdata(dev);
  132. char *tmp;
  133. int i;
  134. if (!card)
  135. return -EINVAL;
  136. if ((card->state != CARD_STATE_DOWN) &&
  137. (card->state != CARD_STATE_RECOVER))
  138. return -EPERM;
  139. i = simple_strtoul(buf, &tmp, 16);
  140. if ((i == 0) || (i == 1))
  141. card->options.fake_broadcast = i;
  142. else {
  143. return -EINVAL;
  144. }
  145. return count;
  146. }
  147. static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
  148. qeth_l3_dev_fake_broadcast_store);
  149. static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
  150. struct device_attribute *attr, char *buf)
  151. {
  152. struct qeth_card *card = dev_get_drvdata(dev);
  153. if (!card)
  154. return -EINVAL;
  155. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  156. (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
  157. return sprintf(buf, "n/a\n");
  158. return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
  159. QETH_TR_BROADCAST_ALLRINGS)?
  160. "all rings":"local");
  161. }
  162. static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
  163. struct device_attribute *attr, const char *buf, size_t count)
  164. {
  165. struct qeth_card *card = dev_get_drvdata(dev);
  166. char *tmp;
  167. if (!card)
  168. return -EINVAL;
  169. if ((card->state != CARD_STATE_DOWN) &&
  170. (card->state != CARD_STATE_RECOVER))
  171. return -EPERM;
  172. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  173. (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
  174. return -EINVAL;
  175. }
  176. tmp = strsep((char **) &buf, "\n");
  177. if (!strcmp(tmp, "local")) {
  178. card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
  179. return count;
  180. } else if (!strcmp(tmp, "all_rings")) {
  181. card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
  182. return count;
  183. } else {
  184. return -EINVAL;
  185. }
  186. return count;
  187. }
  188. static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
  189. qeth_l3_dev_broadcast_mode_store);
  190. static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
  191. struct device_attribute *attr, char *buf)
  192. {
  193. struct qeth_card *card = dev_get_drvdata(dev);
  194. if (!card)
  195. return -EINVAL;
  196. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  197. (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
  198. return sprintf(buf, "n/a\n");
  199. return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
  200. QETH_TR_MACADDR_CANONICAL)? 1:0);
  201. }
  202. static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
  203. struct device_attribute *attr, const char *buf, size_t count)
  204. {
  205. struct qeth_card *card = dev_get_drvdata(dev);
  206. char *tmp;
  207. int i;
  208. if (!card)
  209. return -EINVAL;
  210. if ((card->state != CARD_STATE_DOWN) &&
  211. (card->state != CARD_STATE_RECOVER))
  212. return -EPERM;
  213. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  214. (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
  215. return -EINVAL;
  216. }
  217. i = simple_strtoul(buf, &tmp, 16);
  218. if ((i == 0) || (i == 1))
  219. card->options.macaddr_mode = i?
  220. QETH_TR_MACADDR_CANONICAL :
  221. QETH_TR_MACADDR_NONCANONICAL;
  222. else {
  223. return -EINVAL;
  224. }
  225. return count;
  226. }
  227. static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
  228. qeth_l3_dev_canonical_macaddr_store);
  229. static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
  230. struct device_attribute *attr, char *buf)
  231. {
  232. struct qeth_card *card = dev_get_drvdata(dev);
  233. if (!card)
  234. return -EINVAL;
  235. return sprintf(buf, "%s checksumming\n",
  236. qeth_l3_get_checksum_str(card));
  237. }
  238. static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
  239. struct device_attribute *attr, const char *buf, size_t count)
  240. {
  241. struct qeth_card *card = dev_get_drvdata(dev);
  242. enum qeth_checksum_types csum_type;
  243. char *tmp;
  244. int rc;
  245. if (!card)
  246. return -EINVAL;
  247. tmp = strsep((char **) &buf, "\n");
  248. if (!strcmp(tmp, "sw_checksumming"))
  249. csum_type = SW_CHECKSUMMING;
  250. else if (!strcmp(tmp, "hw_checksumming"))
  251. csum_type = HW_CHECKSUMMING;
  252. else if (!strcmp(tmp, "no_checksumming"))
  253. csum_type = NO_CHECKSUMMING;
  254. else
  255. return -EINVAL;
  256. rc = qeth_l3_set_rx_csum(card, csum_type);
  257. if (rc)
  258. return rc;
  259. return count;
  260. }
  261. static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
  262. qeth_l3_dev_checksum_store);
  263. static ssize_t qeth_l3_dev_large_send_show(struct device *dev,
  264. struct device_attribute *attr, char *buf)
  265. {
  266. struct qeth_card *card = dev_get_drvdata(dev);
  267. if (!card)
  268. return -EINVAL;
  269. switch (card->options.large_send) {
  270. case QETH_LARGE_SEND_NO:
  271. return sprintf(buf, "%s\n", "no");
  272. case QETH_LARGE_SEND_TSO:
  273. return sprintf(buf, "%s\n", "TSO");
  274. default:
  275. return sprintf(buf, "%s\n", "N/A");
  276. }
  277. }
  278. static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
  279. struct device_attribute *attr, const char *buf, size_t count)
  280. {
  281. struct qeth_card *card = dev_get_drvdata(dev);
  282. enum qeth_large_send_types type;
  283. int rc = 0;
  284. char *tmp;
  285. if (!card)
  286. return -EINVAL;
  287. tmp = strsep((char **) &buf, "\n");
  288. if (!strcmp(tmp, "no"))
  289. type = QETH_LARGE_SEND_NO;
  290. else if (!strcmp(tmp, "TSO"))
  291. type = QETH_LARGE_SEND_TSO;
  292. else
  293. return -EINVAL;
  294. if (card->options.large_send == type)
  295. return count;
  296. rc = qeth_l3_set_large_send(card, type);
  297. if (rc)
  298. return rc;
  299. return count;
  300. }
  301. static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
  302. qeth_l3_dev_large_send_store);
  303. static struct attribute *qeth_l3_device_attrs[] = {
  304. &dev_attr_route4.attr,
  305. &dev_attr_route6.attr,
  306. &dev_attr_fake_broadcast.attr,
  307. &dev_attr_broadcast_mode.attr,
  308. &dev_attr_canonical_macaddr.attr,
  309. &dev_attr_checksumming.attr,
  310. &dev_attr_large_send.attr,
  311. NULL,
  312. };
  313. static struct attribute_group qeth_l3_device_attr_group = {
  314. .attrs = qeth_l3_device_attrs,
  315. };
  316. static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
  317. struct device_attribute *attr, char *buf)
  318. {
  319. struct qeth_card *card = dev_get_drvdata(dev);
  320. if (!card)
  321. return -EINVAL;
  322. return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
  323. }
  324. static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
  325. struct device_attribute *attr, const char *buf, size_t count)
  326. {
  327. struct qeth_card *card = dev_get_drvdata(dev);
  328. char *tmp;
  329. if (!card)
  330. return -EINVAL;
  331. if ((card->state != CARD_STATE_DOWN) &&
  332. (card->state != CARD_STATE_RECOVER))
  333. return -EPERM;
  334. tmp = strsep((char **) &buf, "\n");
  335. if (!strcmp(tmp, "toggle")) {
  336. card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
  337. } else if (!strcmp(tmp, "1")) {
  338. card->ipato.enabled = 1;
  339. } else if (!strcmp(tmp, "0")) {
  340. card->ipato.enabled = 0;
  341. } else {
  342. return -EINVAL;
  343. }
  344. return count;
  345. }
  346. static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
  347. qeth_l3_dev_ipato_enable_show,
  348. qeth_l3_dev_ipato_enable_store);
  349. static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
  350. struct device_attribute *attr, char *buf)
  351. {
  352. struct qeth_card *card = dev_get_drvdata(dev);
  353. if (!card)
  354. return -EINVAL;
  355. return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
  356. }
  357. static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
  358. struct device_attribute *attr,
  359. const char *buf, size_t count)
  360. {
  361. struct qeth_card *card = dev_get_drvdata(dev);
  362. char *tmp;
  363. if (!card)
  364. return -EINVAL;
  365. tmp = strsep((char **) &buf, "\n");
  366. if (!strcmp(tmp, "toggle")) {
  367. card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
  368. } else if (!strcmp(tmp, "1")) {
  369. card->ipato.invert4 = 1;
  370. } else if (!strcmp(tmp, "0")) {
  371. card->ipato.invert4 = 0;
  372. } else {
  373. return -EINVAL;
  374. }
  375. return count;
  376. }
  377. static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
  378. qeth_l3_dev_ipato_invert4_show,
  379. qeth_l3_dev_ipato_invert4_store);
  380. static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
  381. enum qeth_prot_versions proto)
  382. {
  383. struct qeth_ipato_entry *ipatoe;
  384. unsigned long flags;
  385. char addr_str[40];
  386. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  387. int i = 0;
  388. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  389. /* add strlen for "/<mask>\n" */
  390. entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
  391. spin_lock_irqsave(&card->ip_lock, flags);
  392. list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
  393. if (ipatoe->proto != proto)
  394. continue;
  395. /* String must not be longer than PAGE_SIZE. So we check if
  396. * string length gets near PAGE_SIZE. Then we can savely display
  397. * the next IPv6 address (worst case, compared to IPv4) */
  398. if ((PAGE_SIZE - i) <= entry_len)
  399. break;
  400. qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
  401. i += snprintf(buf + i, PAGE_SIZE - i,
  402. "%s/%i\n", addr_str, ipatoe->mask_bits);
  403. }
  404. spin_unlock_irqrestore(&card->ip_lock, flags);
  405. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  406. return i;
  407. }
  408. static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
  409. struct device_attribute *attr, char *buf)
  410. {
  411. struct qeth_card *card = dev_get_drvdata(dev);
  412. if (!card)
  413. return -EINVAL;
  414. return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
  415. }
  416. static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
  417. u8 *addr, int *mask_bits)
  418. {
  419. const char *start, *end;
  420. char *tmp;
  421. char buffer[40] = {0, };
  422. start = buf;
  423. /* get address string */
  424. end = strchr(start, '/');
  425. if (!end || (end - start >= 40)) {
  426. return -EINVAL;
  427. }
  428. strncpy(buffer, start, end - start);
  429. if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
  430. return -EINVAL;
  431. }
  432. start = end + 1;
  433. *mask_bits = simple_strtoul(start, &tmp, 10);
  434. if (!strlen(start) ||
  435. (tmp == start) ||
  436. (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
  437. return -EINVAL;
  438. }
  439. return 0;
  440. }
  441. static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
  442. struct qeth_card *card, enum qeth_prot_versions proto)
  443. {
  444. struct qeth_ipato_entry *ipatoe;
  445. u8 addr[16];
  446. int mask_bits;
  447. int rc;
  448. rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
  449. if (rc)
  450. return rc;
  451. ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
  452. if (!ipatoe) {
  453. return -ENOMEM;
  454. }
  455. ipatoe->proto = proto;
  456. memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
  457. ipatoe->mask_bits = mask_bits;
  458. rc = qeth_l3_add_ipato_entry(card, ipatoe);
  459. if (rc) {
  460. kfree(ipatoe);
  461. return rc;
  462. }
  463. return count;
  464. }
  465. static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
  466. struct device_attribute *attr, const char *buf, size_t count)
  467. {
  468. struct qeth_card *card = dev_get_drvdata(dev);
  469. if (!card)
  470. return -EINVAL;
  471. return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
  472. }
  473. static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
  474. qeth_l3_dev_ipato_add4_show,
  475. qeth_l3_dev_ipato_add4_store);
  476. static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
  477. struct qeth_card *card, enum qeth_prot_versions proto)
  478. {
  479. u8 addr[16];
  480. int mask_bits;
  481. int rc;
  482. rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
  483. if (rc)
  484. return rc;
  485. qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
  486. return count;
  487. }
  488. static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
  489. struct device_attribute *attr, const char *buf, size_t count)
  490. {
  491. struct qeth_card *card = dev_get_drvdata(dev);
  492. if (!card)
  493. return -EINVAL;
  494. return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
  495. }
  496. static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
  497. qeth_l3_dev_ipato_del4_store);
  498. static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
  499. struct device_attribute *attr, char *buf)
  500. {
  501. struct qeth_card *card = dev_get_drvdata(dev);
  502. if (!card)
  503. return -EINVAL;
  504. return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
  505. }
  506. static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
  507. struct device_attribute *attr, const char *buf, size_t count)
  508. {
  509. struct qeth_card *card = dev_get_drvdata(dev);
  510. char *tmp;
  511. if (!card)
  512. return -EINVAL;
  513. tmp = strsep((char **) &buf, "\n");
  514. if (!strcmp(tmp, "toggle")) {
  515. card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
  516. } else if (!strcmp(tmp, "1")) {
  517. card->ipato.invert6 = 1;
  518. } else if (!strcmp(tmp, "0")) {
  519. card->ipato.invert6 = 0;
  520. } else {
  521. return -EINVAL;
  522. }
  523. return count;
  524. }
  525. static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
  526. qeth_l3_dev_ipato_invert6_show,
  527. qeth_l3_dev_ipato_invert6_store);
  528. static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
  529. struct device_attribute *attr, char *buf)
  530. {
  531. struct qeth_card *card = dev_get_drvdata(dev);
  532. if (!card)
  533. return -EINVAL;
  534. return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
  535. }
  536. static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
  537. struct device_attribute *attr, const char *buf, size_t count)
  538. {
  539. struct qeth_card *card = dev_get_drvdata(dev);
  540. if (!card)
  541. return -EINVAL;
  542. return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
  543. }
  544. static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
  545. qeth_l3_dev_ipato_add6_show,
  546. qeth_l3_dev_ipato_add6_store);
  547. static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
  548. struct device_attribute *attr, const char *buf, size_t count)
  549. {
  550. struct qeth_card *card = dev_get_drvdata(dev);
  551. if (!card)
  552. return -EINVAL;
  553. return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
  554. }
  555. static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
  556. qeth_l3_dev_ipato_del6_store);
  557. static struct attribute *qeth_ipato_device_attrs[] = {
  558. &dev_attr_ipato_enable.attr,
  559. &dev_attr_ipato_invert4.attr,
  560. &dev_attr_ipato_add4.attr,
  561. &dev_attr_ipato_del4.attr,
  562. &dev_attr_ipato_invert6.attr,
  563. &dev_attr_ipato_add6.attr,
  564. &dev_attr_ipato_del6.attr,
  565. NULL,
  566. };
  567. static struct attribute_group qeth_device_ipato_group = {
  568. .name = "ipa_takeover",
  569. .attrs = qeth_ipato_device_attrs,
  570. };
  571. static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
  572. enum qeth_prot_versions proto)
  573. {
  574. struct qeth_ipaddr *ipaddr;
  575. char addr_str[40];
  576. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  577. unsigned long flags;
  578. int i = 0;
  579. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  580. entry_len += 2; /* \n + terminator */
  581. spin_lock_irqsave(&card->ip_lock, flags);
  582. list_for_each_entry(ipaddr, &card->ip_list, entry) {
  583. if (ipaddr->proto != proto)
  584. continue;
  585. if (ipaddr->type != QETH_IP_TYPE_VIPA)
  586. continue;
  587. /* String must not be longer than PAGE_SIZE. So we check if
  588. * string length gets near PAGE_SIZE. Then we can savely display
  589. * the next IPv6 address (worst case, compared to IPv4) */
  590. if ((PAGE_SIZE - i) <= entry_len)
  591. break;
  592. qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
  593. addr_str);
  594. i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
  595. }
  596. spin_unlock_irqrestore(&card->ip_lock, flags);
  597. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  598. return i;
  599. }
  600. static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
  601. struct device_attribute *attr, char *buf)
  602. {
  603. struct qeth_card *card = dev_get_drvdata(dev);
  604. if (!card)
  605. return -EINVAL;
  606. return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
  607. }
  608. static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
  609. u8 *addr)
  610. {
  611. if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
  612. return -EINVAL;
  613. }
  614. return 0;
  615. }
  616. static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
  617. struct qeth_card *card, enum qeth_prot_versions proto)
  618. {
  619. u8 addr[16] = {0, };
  620. int rc;
  621. rc = qeth_l3_parse_vipae(buf, proto, addr);
  622. if (rc)
  623. return rc;
  624. rc = qeth_l3_add_vipa(card, proto, addr);
  625. if (rc)
  626. return rc;
  627. return count;
  628. }
  629. static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
  630. struct device_attribute *attr, const char *buf, size_t count)
  631. {
  632. struct qeth_card *card = dev_get_drvdata(dev);
  633. if (!card)
  634. return -EINVAL;
  635. return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
  636. }
  637. static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
  638. qeth_l3_dev_vipa_add4_show,
  639. qeth_l3_dev_vipa_add4_store);
  640. static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
  641. struct qeth_card *card, enum qeth_prot_versions proto)
  642. {
  643. u8 addr[16];
  644. int rc;
  645. rc = qeth_l3_parse_vipae(buf, proto, addr);
  646. if (rc)
  647. return rc;
  648. qeth_l3_del_vipa(card, proto, addr);
  649. return count;
  650. }
  651. static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
  652. struct device_attribute *attr, const char *buf, size_t count)
  653. {
  654. struct qeth_card *card = dev_get_drvdata(dev);
  655. if (!card)
  656. return -EINVAL;
  657. return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
  658. }
  659. static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
  660. qeth_l3_dev_vipa_del4_store);
  661. static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
  662. struct device_attribute *attr, char *buf)
  663. {
  664. struct qeth_card *card = dev_get_drvdata(dev);
  665. if (!card)
  666. return -EINVAL;
  667. return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
  668. }
  669. static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
  670. struct device_attribute *attr, const char *buf, size_t count)
  671. {
  672. struct qeth_card *card = dev_get_drvdata(dev);
  673. if (!card)
  674. return -EINVAL;
  675. return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
  676. }
  677. static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
  678. qeth_l3_dev_vipa_add6_show,
  679. qeth_l3_dev_vipa_add6_store);
  680. static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
  681. struct device_attribute *attr, const char *buf, size_t count)
  682. {
  683. struct qeth_card *card = dev_get_drvdata(dev);
  684. if (!card)
  685. return -EINVAL;
  686. return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
  687. }
  688. static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
  689. qeth_l3_dev_vipa_del6_store);
  690. static struct attribute *qeth_vipa_device_attrs[] = {
  691. &dev_attr_vipa_add4.attr,
  692. &dev_attr_vipa_del4.attr,
  693. &dev_attr_vipa_add6.attr,
  694. &dev_attr_vipa_del6.attr,
  695. NULL,
  696. };
  697. static struct attribute_group qeth_device_vipa_group = {
  698. .name = "vipa",
  699. .attrs = qeth_vipa_device_attrs,
  700. };
  701. static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
  702. enum qeth_prot_versions proto)
  703. {
  704. struct qeth_ipaddr *ipaddr;
  705. char addr_str[40];
  706. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  707. unsigned long flags;
  708. int i = 0;
  709. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  710. entry_len += 2; /* \n + terminator */
  711. spin_lock_irqsave(&card->ip_lock, flags);
  712. list_for_each_entry(ipaddr, &card->ip_list, entry) {
  713. if (ipaddr->proto != proto)
  714. continue;
  715. if (ipaddr->type != QETH_IP_TYPE_RXIP)
  716. continue;
  717. /* String must not be longer than PAGE_SIZE. So we check if
  718. * string length gets near PAGE_SIZE. Then we can savely display
  719. * the next IPv6 address (worst case, compared to IPv4) */
  720. if ((PAGE_SIZE - i) <= entry_len)
  721. break;
  722. qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
  723. addr_str);
  724. i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
  725. }
  726. spin_unlock_irqrestore(&card->ip_lock, flags);
  727. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  728. return i;
  729. }
  730. static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
  731. struct device_attribute *attr, char *buf)
  732. {
  733. struct qeth_card *card = dev_get_drvdata(dev);
  734. if (!card)
  735. return -EINVAL;
  736. return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
  737. }
  738. static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
  739. u8 *addr)
  740. {
  741. if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
  742. return -EINVAL;
  743. }
  744. return 0;
  745. }
  746. static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
  747. struct qeth_card *card, enum qeth_prot_versions proto)
  748. {
  749. u8 addr[16] = {0, };
  750. int rc;
  751. rc = qeth_l3_parse_rxipe(buf, proto, addr);
  752. if (rc)
  753. return rc;
  754. rc = qeth_l3_add_rxip(card, proto, addr);
  755. if (rc)
  756. return rc;
  757. return count;
  758. }
  759. static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
  760. struct device_attribute *attr, const char *buf, size_t count)
  761. {
  762. struct qeth_card *card = dev_get_drvdata(dev);
  763. if (!card)
  764. return -EINVAL;
  765. return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
  766. }
  767. static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
  768. qeth_l3_dev_rxip_add4_show,
  769. qeth_l3_dev_rxip_add4_store);
  770. static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
  771. struct qeth_card *card, enum qeth_prot_versions proto)
  772. {
  773. u8 addr[16];
  774. int rc;
  775. rc = qeth_l3_parse_rxipe(buf, proto, addr);
  776. if (rc)
  777. return rc;
  778. qeth_l3_del_rxip(card, proto, addr);
  779. return count;
  780. }
  781. static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
  782. struct device_attribute *attr, const char *buf, size_t count)
  783. {
  784. struct qeth_card *card = dev_get_drvdata(dev);
  785. if (!card)
  786. return -EINVAL;
  787. return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
  788. }
  789. static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
  790. qeth_l3_dev_rxip_del4_store);
  791. static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
  792. struct device_attribute *attr, char *buf)
  793. {
  794. struct qeth_card *card = dev_get_drvdata(dev);
  795. if (!card)
  796. return -EINVAL;
  797. return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
  798. }
  799. static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
  800. struct device_attribute *attr, const char *buf, size_t count)
  801. {
  802. struct qeth_card *card = dev_get_drvdata(dev);
  803. if (!card)
  804. return -EINVAL;
  805. return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
  806. }
  807. static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
  808. qeth_l3_dev_rxip_add6_show,
  809. qeth_l3_dev_rxip_add6_store);
  810. static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
  811. struct device_attribute *attr, const char *buf, size_t count)
  812. {
  813. struct qeth_card *card = dev_get_drvdata(dev);
  814. if (!card)
  815. return -EINVAL;
  816. return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
  817. }
  818. static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
  819. qeth_l3_dev_rxip_del6_store);
  820. static struct attribute *qeth_rxip_device_attrs[] = {
  821. &dev_attr_rxip_add4.attr,
  822. &dev_attr_rxip_del4.attr,
  823. &dev_attr_rxip_add6.attr,
  824. &dev_attr_rxip_del6.attr,
  825. NULL,
  826. };
  827. static struct attribute_group qeth_device_rxip_group = {
  828. .name = "rxip",
  829. .attrs = qeth_rxip_device_attrs,
  830. };
  831. int qeth_l3_create_device_attributes(struct device *dev)
  832. {
  833. int ret;
  834. ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
  835. if (ret)
  836. return ret;
  837. ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
  838. if (ret) {
  839. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  840. return ret;
  841. }
  842. ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
  843. if (ret) {
  844. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  845. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  846. return ret;
  847. }
  848. ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
  849. if (ret) {
  850. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  851. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  852. sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
  853. return ret;
  854. }
  855. return 0;
  856. }
  857. void qeth_l3_remove_device_attributes(struct device *dev)
  858. {
  859. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  860. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  861. sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
  862. sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
  863. }