1 // SPDX-License-Identifier: GPL-2.0 2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3 4 #include <linux/delay.h> 5 #include <linux/etherdevice.h> 6 #include <linux/hardirq.h> 7 #include <linux/netdevice.h> 8 #include <linux/if_ether.h> 9 #include <linux/if_arp.h> 10 #include <linux/kthread.h> 11 #include <linux/kfifo.h> 12 #include <net/cfg80211.h> 13 14 #include "mesh.h" 15 #include "decl.h" 16 #include "cmd.h" 17 18 19 static int lbs_add_mesh(struct lbs_private *priv); 20 21 /*************************************************************************** 22 * Mesh command handling 23 */ 24 25 static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, 26 struct cmd_ds_mesh_access *cmd) 27 { 28 int ret; 29 30 cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); 31 cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); 32 cmd->hdr.result = 0; 33 34 cmd->action = cpu_to_le16(cmd_action); 35 36 ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); 37 38 return ret; 39 } 40 41 static int __lbs_mesh_config_send(struct lbs_private *priv, 42 struct cmd_ds_mesh_config *cmd, 43 uint16_t action, uint16_t type) 44 { 45 int ret; 46 u16 command = CMD_MESH_CONFIG_OLD; 47 48 /* 49 * Command id is 0xac for v10 FW along with mesh interface 50 * id in bits 14-13-12. 51 */ 52 if (priv->mesh_tlv == TLV_TYPE_MESH_ID) 53 command = CMD_MESH_CONFIG | 54 (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); 55 56 cmd->hdr.command = cpu_to_le16(command); 57 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); 58 cmd->hdr.result = 0; 59 60 cmd->type = cpu_to_le16(type); 61 cmd->action = cpu_to_le16(action); 62 63 ret = lbs_cmd_with_response(priv, command, cmd); 64 65 return ret; 66 } 67 68 static int lbs_mesh_config_send(struct lbs_private *priv, 69 struct cmd_ds_mesh_config *cmd, 70 uint16_t action, uint16_t type) 71 { 72 int ret; 73 74 if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) 75 return -EOPNOTSUPP; 76 77 ret = __lbs_mesh_config_send(priv, cmd, action, type); 78 return ret; 79 } 80 81 /* This function is the CMD_MESH_CONFIG legacy function. It only handles the 82 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG 83 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to 84 * lbs_mesh_config_send. 85 */ 86 static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, 87 uint16_t chan) 88 { 89 struct cmd_ds_mesh_config cmd; 90 struct mrvl_meshie *ie; 91 92 memset(&cmd, 0, sizeof(cmd)); 93 cmd.channel = cpu_to_le16(chan); 94 ie = (struct mrvl_meshie *)cmd.data; 95 96 switch (action) { 97 case CMD_ACT_MESH_CONFIG_START: 98 ie->id = WLAN_EID_VENDOR_SPECIFIC; 99 ie->val.oui[0] = 0x00; 100 ie->val.oui[1] = 0x50; 101 ie->val.oui[2] = 0x43; 102 ie->val.type = MARVELL_MESH_IE_TYPE; 103 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; 104 ie->val.version = MARVELL_MESH_IE_VERSION; 105 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; 106 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; 107 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; 108 ie->val.mesh_id_len = priv->mesh_ssid_len; 109 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); 110 ie->len = sizeof(struct mrvl_meshie_val) - 111 IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; 112 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); 113 break; 114 case CMD_ACT_MESH_CONFIG_STOP: 115 break; 116 default: 117 return -1; 118 } 119 lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n", 120 action, priv->mesh_tlv, chan, priv->mesh_ssid_len, 121 priv->mesh_ssid); 122 123 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); 124 } 125 126 int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel) 127 { 128 priv->mesh_channel = channel; 129 return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel); 130 } 131 132 static uint16_t lbs_mesh_get_channel(struct lbs_private *priv) 133 { 134 return priv->mesh_channel ?: 1; 135 } 136 137 /*************************************************************************** 138 * Mesh sysfs support 139 */ 140 141 /* 142 * Attributes exported through sysfs 143 */ 144 145 /** 146 * lbs_anycast_get - Get function for sysfs attribute anycast_mask 147 * @dev: the &struct device 148 * @attr: device attributes 149 * @buf: buffer where data will be returned 150 */ 151 static ssize_t lbs_anycast_get(struct device *dev, 152 struct device_attribute *attr, char * buf) 153 { 154 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 155 struct cmd_ds_mesh_access mesh_access; 156 int ret; 157 158 memset(&mesh_access, 0, sizeof(mesh_access)); 159 160 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access); 161 if (ret) 162 return ret; 163 164 return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); 165 } 166 167 /** 168 * lbs_anycast_set - Set function for sysfs attribute anycast_mask 169 * @dev: the &struct device 170 * @attr: device attributes 171 * @buf: buffer that contains new attribute value 172 * @count: size of buffer 173 */ 174 static ssize_t lbs_anycast_set(struct device *dev, 175 struct device_attribute *attr, const char * buf, size_t count) 176 { 177 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 178 struct cmd_ds_mesh_access mesh_access; 179 uint32_t datum; 180 int ret; 181 182 memset(&mesh_access, 0, sizeof(mesh_access)); 183 sscanf(buf, "%x", &datum); 184 mesh_access.data[0] = cpu_to_le32(datum); 185 186 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); 187 if (ret) 188 return ret; 189 190 return strlen(buf); 191 } 192 193 /** 194 * lbs_prb_rsp_limit_get - Get function for sysfs attribute prb_rsp_limit 195 * @dev: the &struct device 196 * @attr: device attributes 197 * @buf: buffer where data will be returned 198 */ 199 static ssize_t lbs_prb_rsp_limit_get(struct device *dev, 200 struct device_attribute *attr, char *buf) 201 { 202 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 203 struct cmd_ds_mesh_access mesh_access; 204 int ret; 205 u32 retry_limit; 206 207 memset(&mesh_access, 0, sizeof(mesh_access)); 208 mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET); 209 210 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, 211 &mesh_access); 212 if (ret) 213 return ret; 214 215 retry_limit = le32_to_cpu(mesh_access.data[1]); 216 return snprintf(buf, 10, "%d\n", retry_limit); 217 } 218 219 /** 220 * lbs_prb_rsp_limit_set - Set function for sysfs attribute prb_rsp_limit 221 * @dev: the &struct device 222 * @attr: device attributes 223 * @buf: buffer that contains new attribute value 224 * @count: size of buffer 225 */ 226 static ssize_t lbs_prb_rsp_limit_set(struct device *dev, 227 struct device_attribute *attr, const char *buf, size_t count) 228 { 229 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 230 struct cmd_ds_mesh_access mesh_access; 231 int ret; 232 unsigned long retry_limit; 233 234 memset(&mesh_access, 0, sizeof(mesh_access)); 235 mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); 236 237 ret = kstrtoul(buf, 10, &retry_limit); 238 if (ret) 239 return ret; 240 if (retry_limit > 15) 241 return -ENOTSUPP; 242 243 mesh_access.data[1] = cpu_to_le32(retry_limit); 244 245 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, 246 &mesh_access); 247 if (ret) 248 return ret; 249 250 return strlen(buf); 251 } 252 253 /** 254 * lbs_mesh_get - Get function for sysfs attribute mesh 255 * @dev: the &struct device 256 * @attr: device attributes 257 * @buf: buffer where data will be returned 258 */ 259 static ssize_t lbs_mesh_get(struct device *dev, 260 struct device_attribute *attr, char * buf) 261 { 262 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 263 return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); 264 } 265 266 /** 267 * lbs_mesh_set - Set function for sysfs attribute mesh 268 * @dev: the &struct device 269 * @attr: device attributes 270 * @buf: buffer that contains new attribute value 271 * @count: size of buffer 272 */ 273 static ssize_t lbs_mesh_set(struct device *dev, 274 struct device_attribute *attr, const char * buf, size_t count) 275 { 276 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 277 int enable; 278 279 sscanf(buf, "%x", &enable); 280 enable = !!enable; 281 if (enable == !!priv->mesh_dev) 282 return count; 283 284 if (enable) 285 lbs_add_mesh(priv); 286 else 287 lbs_remove_mesh(priv); 288 289 return count; 290 } 291 292 /* 293 * lbs_mesh attribute to be exported per ethX interface 294 * through sysfs (/sys/class/net/ethX/lbs_mesh) 295 */ 296 static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); 297 298 /* 299 * anycast_mask attribute to be exported per mshX interface 300 * through sysfs (/sys/class/net/mshX/anycast_mask) 301 */ 302 static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); 303 304 /* 305 * prb_rsp_limit attribute to be exported per mshX interface 306 * through sysfs (/sys/class/net/mshX/prb_rsp_limit) 307 */ 308 static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get, 309 lbs_prb_rsp_limit_set); 310 311 static struct attribute *lbs_mesh_sysfs_entries[] = { 312 &dev_attr_anycast_mask.attr, 313 &dev_attr_prb_rsp_limit.attr, 314 NULL, 315 }; 316 317 static const struct attribute_group lbs_mesh_attr_group = { 318 .attrs = lbs_mesh_sysfs_entries, 319 }; 320 321 322 /*************************************************************************** 323 * Persistent configuration support 324 */ 325 326 static int mesh_get_default_parameters(struct device *dev, 327 struct mrvl_mesh_defaults *defs) 328 { 329 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 330 struct cmd_ds_mesh_config cmd; 331 int ret; 332 333 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); 334 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET, 335 CMD_TYPE_MESH_GET_DEFAULTS); 336 337 if (ret) 338 return -EOPNOTSUPP; 339 340 memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults)); 341 342 return 0; 343 } 344 345 /** 346 * bootflag_get - Get function for sysfs attribute bootflag 347 * @dev: the &struct device 348 * @attr: device attributes 349 * @buf: buffer where data will be returned 350 */ 351 static ssize_t bootflag_get(struct device *dev, 352 struct device_attribute *attr, char *buf) 353 { 354 struct mrvl_mesh_defaults defs; 355 int ret; 356 357 ret = mesh_get_default_parameters(dev, &defs); 358 359 if (ret) 360 return ret; 361 362 return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); 363 } 364 365 /** 366 * bootflag_set - Set function for sysfs attribute bootflag 367 * @dev: the &struct device 368 * @attr: device attributes 369 * @buf: buffer that contains new attribute value 370 * @count: size of buffer 371 */ 372 static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, 373 const char *buf, size_t count) 374 { 375 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 376 struct cmd_ds_mesh_config cmd; 377 uint32_t datum; 378 int ret; 379 380 memset(&cmd, 0, sizeof(cmd)); 381 ret = sscanf(buf, "%d", &datum); 382 if ((ret != 1) || (datum > 1)) 383 return -EINVAL; 384 385 *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); 386 cmd.length = cpu_to_le16(sizeof(uint32_t)); 387 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 388 CMD_TYPE_MESH_SET_BOOTFLAG); 389 if (ret) 390 return ret; 391 392 return strlen(buf); 393 } 394 395 /** 396 * boottime_get - Get function for sysfs attribute boottime 397 * @dev: the &struct device 398 * @attr: device attributes 399 * @buf: buffer where data will be returned 400 */ 401 static ssize_t boottime_get(struct device *dev, 402 struct device_attribute *attr, char *buf) 403 { 404 struct mrvl_mesh_defaults defs; 405 int ret; 406 407 ret = mesh_get_default_parameters(dev, &defs); 408 409 if (ret) 410 return ret; 411 412 return snprintf(buf, 12, "%d\n", defs.boottime); 413 } 414 415 /** 416 * boottime_set - Set function for sysfs attribute boottime 417 * @dev: the &struct device 418 * @attr: device attributes 419 * @buf: buffer that contains new attribute value 420 * @count: size of buffer 421 */ 422 static ssize_t boottime_set(struct device *dev, 423 struct device_attribute *attr, const char *buf, size_t count) 424 { 425 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 426 struct cmd_ds_mesh_config cmd; 427 uint32_t datum; 428 int ret; 429 430 memset(&cmd, 0, sizeof(cmd)); 431 ret = sscanf(buf, "%d", &datum); 432 if ((ret != 1) || (datum > 255)) 433 return -EINVAL; 434 435 /* A too small boot time will result in the device booting into 436 * standalone (no-host) mode before the host can take control of it, 437 * so the change will be hard to revert. This may be a desired 438 * feature (e.g to configure a very fast boot time for devices that 439 * will not be attached to a host), but dangerous. So I'm enforcing a 440 * lower limit of 20 seconds: remove and recompile the driver if this 441 * does not work for you. 442 */ 443 datum = (datum < 20) ? 20 : datum; 444 cmd.data[0] = datum; 445 cmd.length = cpu_to_le16(sizeof(uint8_t)); 446 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 447 CMD_TYPE_MESH_SET_BOOTTIME); 448 if (ret) 449 return ret; 450 451 return strlen(buf); 452 } 453 454 /** 455 * channel_get - Get function for sysfs attribute channel 456 * @dev: the &struct device 457 * @attr: device attributes 458 * @buf: buffer where data will be returned 459 */ 460 static ssize_t channel_get(struct device *dev, 461 struct device_attribute *attr, char *buf) 462 { 463 struct mrvl_mesh_defaults defs; 464 int ret; 465 466 ret = mesh_get_default_parameters(dev, &defs); 467 468 if (ret) 469 return ret; 470 471 return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); 472 } 473 474 /** 475 * channel_set - Set function for sysfs attribute channel 476 * @dev: the &struct device 477 * @attr: device attributes 478 * @buf: buffer that contains new attribute value 479 * @count: size of buffer 480 */ 481 static ssize_t channel_set(struct device *dev, struct device_attribute *attr, 482 const char *buf, size_t count) 483 { 484 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 485 struct cmd_ds_mesh_config cmd; 486 uint32_t datum; 487 int ret; 488 489 memset(&cmd, 0, sizeof(cmd)); 490 ret = sscanf(buf, "%d", &datum); 491 if (ret != 1 || datum < 1 || datum > 11) 492 return -EINVAL; 493 494 *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); 495 cmd.length = cpu_to_le16(sizeof(uint16_t)); 496 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 497 CMD_TYPE_MESH_SET_DEF_CHANNEL); 498 if (ret) 499 return ret; 500 501 return strlen(buf); 502 } 503 504 /** 505 * mesh_id_get - Get function for sysfs attribute mesh_id 506 * @dev: the &struct device 507 * @attr: device attributes 508 * @buf: buffer where data will be returned 509 */ 510 static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, 511 char *buf) 512 { 513 struct mrvl_mesh_defaults defs; 514 int ret; 515 516 ret = mesh_get_default_parameters(dev, &defs); 517 518 if (ret) 519 return ret; 520 521 if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { 522 dev_err(dev, "inconsistent mesh ID length\n"); 523 defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; 524 } 525 526 memcpy(buf, defs.meshie.val.mesh_id, defs.meshie.val.mesh_id_len); 527 buf[defs.meshie.val.mesh_id_len] = '\n'; 528 buf[defs.meshie.val.mesh_id_len + 1] = '\0'; 529 530 return defs.meshie.val.mesh_id_len + 1; 531 } 532 533 /** 534 * mesh_id_set - Set function for sysfs attribute mesh_id 535 * @dev: the &struct device 536 * @attr: device attributes 537 * @buf: buffer that contains new attribute value 538 * @count: size of buffer 539 */ 540 static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, 541 const char *buf, size_t count) 542 { 543 struct cmd_ds_mesh_config cmd; 544 struct mrvl_mesh_defaults defs; 545 struct mrvl_meshie *ie; 546 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 547 int len; 548 int ret; 549 550 if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1) 551 return -EINVAL; 552 553 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); 554 ie = (struct mrvl_meshie *) &cmd.data[0]; 555 556 /* fetch all other Information Element parameters */ 557 ret = mesh_get_default_parameters(dev, &defs); 558 559 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); 560 561 /* transfer IE elements */ 562 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); 563 564 len = count - 1; 565 memcpy(ie->val.mesh_id, buf, len); 566 /* SSID len */ 567 ie->val.mesh_id_len = len; 568 /* IE len */ 569 ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len; 570 571 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 572 CMD_TYPE_MESH_SET_MESH_IE); 573 if (ret) 574 return ret; 575 576 return strlen(buf); 577 } 578 579 /** 580 * protocol_id_get - Get function for sysfs attribute protocol_id 581 * @dev: the &struct device 582 * @attr: device attributes 583 * @buf: buffer where data will be returned 584 */ 585 static ssize_t protocol_id_get(struct device *dev, 586 struct device_attribute *attr, char *buf) 587 { 588 struct mrvl_mesh_defaults defs; 589 int ret; 590 591 ret = mesh_get_default_parameters(dev, &defs); 592 593 if (ret) 594 return ret; 595 596 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); 597 } 598 599 /** 600 * protocol_id_set - Set function for sysfs attribute protocol_id 601 * @dev: the &struct device 602 * @attr: device attributes 603 * @buf: buffer that contains new attribute value 604 * @count: size of buffer 605 */ 606 static ssize_t protocol_id_set(struct device *dev, 607 struct device_attribute *attr, const char *buf, size_t count) 608 { 609 struct cmd_ds_mesh_config cmd; 610 struct mrvl_mesh_defaults defs; 611 struct mrvl_meshie *ie; 612 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 613 uint32_t datum; 614 int ret; 615 616 memset(&cmd, 0, sizeof(cmd)); 617 ret = sscanf(buf, "%d", &datum); 618 if ((ret != 1) || (datum > 255)) 619 return -EINVAL; 620 621 /* fetch all other Information Element parameters */ 622 ret = mesh_get_default_parameters(dev, &defs); 623 624 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); 625 626 /* transfer IE elements */ 627 ie = (struct mrvl_meshie *) &cmd.data[0]; 628 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); 629 /* update protocol id */ 630 ie->val.active_protocol_id = datum; 631 632 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 633 CMD_TYPE_MESH_SET_MESH_IE); 634 if (ret) 635 return ret; 636 637 return strlen(buf); 638 } 639 640 /** 641 * metric_id_get - Get function for sysfs attribute metric_id 642 * @dev: the &struct device 643 * @attr: device attributes 644 * @buf: buffer where data will be returned 645 */ 646 static ssize_t metric_id_get(struct device *dev, 647 struct device_attribute *attr, char *buf) 648 { 649 struct mrvl_mesh_defaults defs; 650 int ret; 651 652 ret = mesh_get_default_parameters(dev, &defs); 653 654 if (ret) 655 return ret; 656 657 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); 658 } 659 660 /** 661 * metric_id_set - Set function for sysfs attribute metric_id 662 * @dev: the &struct device 663 * @attr: device attributes 664 * @buf: buffer that contains new attribute value 665 * @count: size of buffer 666 */ 667 static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, 668 const char *buf, size_t count) 669 { 670 struct cmd_ds_mesh_config cmd; 671 struct mrvl_mesh_defaults defs; 672 struct mrvl_meshie *ie; 673 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 674 uint32_t datum; 675 int ret; 676 677 memset(&cmd, 0, sizeof(cmd)); 678 ret = sscanf(buf, "%d", &datum); 679 if ((ret != 1) || (datum > 255)) 680 return -EINVAL; 681 682 /* fetch all other Information Element parameters */ 683 ret = mesh_get_default_parameters(dev, &defs); 684 685 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); 686 687 /* transfer IE elements */ 688 ie = (struct mrvl_meshie *) &cmd.data[0]; 689 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); 690 /* update metric id */ 691 ie->val.active_metric_id = datum; 692 693 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 694 CMD_TYPE_MESH_SET_MESH_IE); 695 if (ret) 696 return ret; 697 698 return strlen(buf); 699 } 700 701 /** 702 * capability_get - Get function for sysfs attribute capability 703 * @dev: the &struct device 704 * @attr: device attributes 705 * @buf: buffer where data will be returned 706 */ 707 static ssize_t capability_get(struct device *dev, 708 struct device_attribute *attr, char *buf) 709 { 710 struct mrvl_mesh_defaults defs; 711 int ret; 712 713 ret = mesh_get_default_parameters(dev, &defs); 714 715 if (ret) 716 return ret; 717 718 return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); 719 } 720 721 /** 722 * capability_set - Set function for sysfs attribute capability 723 * @dev: the &struct device 724 * @attr: device attributes 725 * @buf: buffer that contains new attribute value 726 * @count: size of buffer 727 */ 728 static ssize_t capability_set(struct device *dev, struct device_attribute *attr, 729 const char *buf, size_t count) 730 { 731 struct cmd_ds_mesh_config cmd; 732 struct mrvl_mesh_defaults defs; 733 struct mrvl_meshie *ie; 734 struct lbs_private *priv = to_net_dev(dev)->ml_priv; 735 uint32_t datum; 736 int ret; 737 738 memset(&cmd, 0, sizeof(cmd)); 739 ret = sscanf(buf, "%d", &datum); 740 if ((ret != 1) || (datum > 255)) 741 return -EINVAL; 742 743 /* fetch all other Information Element parameters */ 744 ret = mesh_get_default_parameters(dev, &defs); 745 746 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); 747 748 /* transfer IE elements */ 749 ie = (struct mrvl_meshie *) &cmd.data[0]; 750 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); 751 /* update value */ 752 ie->val.mesh_capability = datum; 753 754 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, 755 CMD_TYPE_MESH_SET_MESH_IE); 756 if (ret) 757 return ret; 758 759 return strlen(buf); 760 } 761 762 763 static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set); 764 static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set); 765 static DEVICE_ATTR(channel, 0644, channel_get, channel_set); 766 static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set); 767 static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set); 768 static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set); 769 static DEVICE_ATTR(capability, 0644, capability_get, capability_set); 770 771 static struct attribute *boot_opts_attrs[] = { 772 &dev_attr_bootflag.attr, 773 &dev_attr_boottime.attr, 774 &dev_attr_channel.attr, 775 NULL 776 }; 777 778 static const struct attribute_group boot_opts_group = { 779 .name = "boot_options", 780 .attrs = boot_opts_attrs, 781 }; 782 783 static struct attribute *mesh_ie_attrs[] = { 784 &dev_attr_mesh_id.attr, 785 &dev_attr_protocol_id.attr, 786 &dev_attr_metric_id.attr, 787 &dev_attr_capability.attr, 788 NULL 789 }; 790 791 static const struct attribute_group mesh_ie_group = { 792 .name = "mesh_ie", 793 .attrs = mesh_ie_attrs, 794 }; 795 796 static void lbs_persist_config_init(struct net_device *dev) 797 { 798 int ret; 799 ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); 800 ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); 801 } 802 803 static void lbs_persist_config_remove(struct net_device *dev) 804 { 805 sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); 806 sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); 807 } 808 809 810 /*************************************************************************** 811 * Initializing and starting, stopping mesh 812 */ 813 814 /* 815 * Check mesh FW version and appropriately send the mesh start 816 * command 817 */ 818 int lbs_init_mesh(struct lbs_private *priv) 819 { 820 int ret = 0; 821 822 /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ 823 /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ 824 /* 5.110.22 have mesh command with 0xa3 command id */ 825 /* 10.0.0.p0 FW brings in mesh config command with different id */ 826 /* Check FW version MSB and initialize mesh_fw_ver */ 827 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { 828 /* Enable mesh, if supported, and work out which TLV it uses. 829 0x100 + 291 is an unofficial value used in 5.110.20.pXX 830 0x100 + 37 is the official value used in 5.110.21.pXX 831 but we check them in that order because 20.pXX doesn't 832 give an error -- it just silently fails. */ 833 834 /* 5.110.20.pXX firmware will fail the command if the channel 835 doesn't match the existing channel. But only if the TLV 836 is correct. If the channel is wrong, _BOTH_ versions will 837 give an error to 0x100+291, and allow 0x100+37 to succeed. 838 It's just that 5.110.20.pXX will not have done anything 839 useful */ 840 841 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; 842 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) { 843 priv->mesh_tlv = TLV_TYPE_MESH_ID; 844 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) 845 priv->mesh_tlv = 0; 846 } 847 } else 848 if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && 849 (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { 850 /* 10.0.0.pXX new firmwares should succeed with TLV 851 * 0x100+37; Do not invoke command with old TLV. 852 */ 853 priv->mesh_tlv = TLV_TYPE_MESH_ID; 854 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) 855 priv->mesh_tlv = 0; 856 } 857 858 /* Stop meshing until interface is brought up */ 859 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1); 860 861 if (priv->mesh_tlv) { 862 sprintf(priv->mesh_ssid, "mesh"); 863 priv->mesh_ssid_len = 4; 864 ret = 1; 865 } 866 867 return ret; 868 } 869 870 void lbs_start_mesh(struct lbs_private *priv) 871 { 872 lbs_add_mesh(priv); 873 874 if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh)) 875 netdev_err(priv->dev, "cannot register lbs_mesh attribute\n"); 876 } 877 878 int lbs_deinit_mesh(struct lbs_private *priv) 879 { 880 struct net_device *dev = priv->dev; 881 int ret = 0; 882 883 if (priv->mesh_tlv) { 884 device_remove_file(&dev->dev, &dev_attr_lbs_mesh); 885 ret = 1; 886 } 887 888 return ret; 889 } 890 891 892 /** 893 * lbs_mesh_stop - close the mshX interface 894 * 895 * @dev: A pointer to &net_device structure 896 * returns: 0 897 */ 898 static int lbs_mesh_stop(struct net_device *dev) 899 { 900 struct lbs_private *priv = dev->ml_priv; 901 902 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 903 lbs_mesh_get_channel(priv)); 904 905 spin_lock_irq(&priv->driver_lock); 906 907 netif_stop_queue(dev); 908 netif_carrier_off(dev); 909 910 spin_unlock_irq(&priv->driver_lock); 911 912 lbs_update_mcast(priv); 913 if (!lbs_iface_active(priv)) 914 lbs_stop_iface(priv); 915 916 return 0; 917 } 918 919 /** 920 * lbs_mesh_dev_open - open the mshX interface 921 * 922 * @dev: A pointer to &net_device structure 923 * returns: 0 or -EBUSY if monitor mode active 924 */ 925 static int lbs_mesh_dev_open(struct net_device *dev) 926 { 927 struct lbs_private *priv = dev->ml_priv; 928 int ret = 0; 929 930 if (!priv->iface_running) { 931 ret = lbs_start_iface(priv); 932 if (ret) 933 goto out; 934 } 935 936 spin_lock_irq(&priv->driver_lock); 937 938 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { 939 ret = -EBUSY; 940 spin_unlock_irq(&priv->driver_lock); 941 goto out; 942 } 943 944 netif_carrier_on(dev); 945 946 if (!priv->tx_pending_len) 947 netif_wake_queue(dev); 948 949 spin_unlock_irq(&priv->driver_lock); 950 951 ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 952 lbs_mesh_get_channel(priv)); 953 954 out: 955 return ret; 956 } 957 958 static const struct net_device_ops mesh_netdev_ops = { 959 .ndo_open = lbs_mesh_dev_open, 960 .ndo_stop = lbs_mesh_stop, 961 .ndo_start_xmit = lbs_hard_start_xmit, 962 .ndo_set_mac_address = lbs_set_mac_address, 963 .ndo_set_rx_mode = lbs_set_multicast_list, 964 }; 965 966 /** 967 * lbs_add_mesh - add mshX interface 968 * 969 * @priv: A pointer to the &struct lbs_private structure 970 * returns: 0 if successful, -X otherwise 971 */ 972 static int lbs_add_mesh(struct lbs_private *priv) 973 { 974 struct net_device *mesh_dev = NULL; 975 struct wireless_dev *mesh_wdev; 976 int ret = 0; 977 978 /* Allocate a virtual mesh device */ 979 mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); 980 if (!mesh_wdev) { 981 lbs_deb_mesh("init mshX wireless device failed\n"); 982 ret = -ENOMEM; 983 goto done; 984 } 985 986 mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup); 987 if (!mesh_dev) { 988 lbs_deb_mesh("init mshX device failed\n"); 989 ret = -ENOMEM; 990 goto err_free_wdev; 991 } 992 993 mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT; 994 mesh_wdev->wiphy = priv->wdev->wiphy; 995 mesh_wdev->netdev = mesh_dev; 996 997 mesh_dev->ml_priv = priv; 998 mesh_dev->ieee80211_ptr = mesh_wdev; 999 priv->mesh_dev = mesh_dev; 1000 1001 mesh_dev->netdev_ops = &mesh_netdev_ops; 1002 mesh_dev->ethtool_ops = &lbs_ethtool_ops; 1003 eth_hw_addr_inherit(mesh_dev, priv->dev); 1004 1005 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); 1006 1007 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 1008 /* Register virtual mesh interface */ 1009 ret = register_netdev(mesh_dev); 1010 if (ret) { 1011 pr_err("cannot register mshX virtual interface\n"); 1012 goto err_free_netdev; 1013 } 1014 1015 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); 1016 if (ret) 1017 goto err_unregister; 1018 1019 lbs_persist_config_init(mesh_dev); 1020 1021 /* Everything successful */ 1022 ret = 0; 1023 goto done; 1024 1025 err_unregister: 1026 unregister_netdev(mesh_dev); 1027 1028 err_free_netdev: 1029 free_netdev(mesh_dev); 1030 1031 err_free_wdev: 1032 kfree(mesh_wdev); 1033 1034 done: 1035 return ret; 1036 } 1037 1038 void lbs_remove_mesh(struct lbs_private *priv) 1039 { 1040 struct net_device *mesh_dev; 1041 1042 mesh_dev = priv->mesh_dev; 1043 if (!mesh_dev) 1044 return; 1045 1046 netif_stop_queue(mesh_dev); 1047 netif_carrier_off(mesh_dev); 1048 sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); 1049 lbs_persist_config_remove(mesh_dev); 1050 unregister_netdev(mesh_dev); 1051 priv->mesh_dev = NULL; 1052 kfree(mesh_dev->ieee80211_ptr); 1053 free_netdev(mesh_dev); 1054 } 1055 1056 1057 /*************************************************************************** 1058 * Sending and receiving 1059 */ 1060 struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, 1061 struct net_device *dev, struct rxpd *rxpd) 1062 { 1063 if (priv->mesh_dev) { 1064 if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { 1065 if (rxpd->rx_control & RxPD_MESH_FRAME) 1066 dev = priv->mesh_dev; 1067 } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { 1068 if (rxpd->u.bss.bss_num == MESH_IFACE_ID) 1069 dev = priv->mesh_dev; 1070 } 1071 } 1072 return dev; 1073 } 1074 1075 1076 void lbs_mesh_set_txpd(struct lbs_private *priv, 1077 struct net_device *dev, struct txpd *txpd) 1078 { 1079 if (dev == priv->mesh_dev) { 1080 if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) 1081 txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); 1082 else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) 1083 txpd->u.bss.bss_num = MESH_IFACE_ID; 1084 } 1085 } 1086 1087 1088 /*************************************************************************** 1089 * Ethtool related 1090 */ 1091 1092 static const char mesh_stat_strings[MESH_STATS_NUM][ETH_GSTRING_LEN] = { 1093 "drop_duplicate_bcast", 1094 "drop_ttl_zero", 1095 "drop_no_fwd_route", 1096 "drop_no_buffers", 1097 "fwded_unicast_cnt", 1098 "fwded_bcast_cnt", 1099 "drop_blind_table", 1100 "tx_failed_cnt" 1101 }; 1102 1103 void lbs_mesh_ethtool_get_stats(struct net_device *dev, 1104 struct ethtool_stats *stats, uint64_t *data) 1105 { 1106 struct lbs_private *priv = dev->ml_priv; 1107 struct cmd_ds_mesh_access mesh_access; 1108 int ret; 1109 1110 /* Get Mesh Statistics */ 1111 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); 1112 1113 if (ret) { 1114 memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); 1115 return; 1116 } 1117 1118 priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); 1119 priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); 1120 priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); 1121 priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); 1122 priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); 1123 priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); 1124 priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); 1125 priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); 1126 1127 data[0] = priv->mstats.fwd_drop_rbt; 1128 data[1] = priv->mstats.fwd_drop_ttl; 1129 data[2] = priv->mstats.fwd_drop_noroute; 1130 data[3] = priv->mstats.fwd_drop_nobuf; 1131 data[4] = priv->mstats.fwd_unicast_cnt; 1132 data[5] = priv->mstats.fwd_bcast_cnt; 1133 data[6] = priv->mstats.drop_blind; 1134 data[7] = priv->mstats.tx_failed_cnt; 1135 } 1136 1137 int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset) 1138 { 1139 struct lbs_private *priv = dev->ml_priv; 1140 1141 if (sset == ETH_SS_STATS && dev == priv->mesh_dev) 1142 return MESH_STATS_NUM; 1143 1144 return -EOPNOTSUPP; 1145 } 1146 1147 void lbs_mesh_ethtool_get_strings(struct net_device *dev, 1148 uint32_t stringset, uint8_t *s) 1149 { 1150 switch (stringset) { 1151 case ETH_SS_STATS: 1152 memcpy(s, mesh_stat_strings, sizeof(mesh_stat_strings)); 1153 break; 1154 } 1155 } 1156