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 if (ret) 801 pr_err("failed to create boot_opts_group.\n"); 802 803 ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); 804 if (ret) 805 pr_err("failed to create mesh_ie_group.\n"); 806 } 807 808 static void lbs_persist_config_remove(struct net_device *dev) 809 { 810 sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); 811 sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); 812 } 813 814 815 /*************************************************************************** 816 * Initializing and starting, stopping mesh 817 */ 818 819 /* 820 * Check mesh FW version and appropriately send the mesh start 821 * command 822 */ 823 int lbs_init_mesh(struct lbs_private *priv) 824 { 825 int ret = 0; 826 827 /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ 828 /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ 829 /* 5.110.22 have mesh command with 0xa3 command id */ 830 /* 10.0.0.p0 FW brings in mesh config command with different id */ 831 /* Check FW version MSB and initialize mesh_fw_ver */ 832 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { 833 /* Enable mesh, if supported, and work out which TLV it uses. 834 0x100 + 291 is an unofficial value used in 5.110.20.pXX 835 0x100 + 37 is the official value used in 5.110.21.pXX 836 but we check them in that order because 20.pXX doesn't 837 give an error -- it just silently fails. */ 838 839 /* 5.110.20.pXX firmware will fail the command if the channel 840 doesn't match the existing channel. But only if the TLV 841 is correct. If the channel is wrong, _BOTH_ versions will 842 give an error to 0x100+291, and allow 0x100+37 to succeed. 843 It's just that 5.110.20.pXX will not have done anything 844 useful */ 845 846 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; 847 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) { 848 priv->mesh_tlv = TLV_TYPE_MESH_ID; 849 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) 850 priv->mesh_tlv = 0; 851 } 852 } else 853 if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && 854 (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { 855 /* 10.0.0.pXX new firmwares should succeed with TLV 856 * 0x100+37; Do not invoke command with old TLV. 857 */ 858 priv->mesh_tlv = TLV_TYPE_MESH_ID; 859 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) 860 priv->mesh_tlv = 0; 861 } 862 863 /* Stop meshing until interface is brought up */ 864 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1); 865 866 if (priv->mesh_tlv) { 867 sprintf(priv->mesh_ssid, "mesh"); 868 priv->mesh_ssid_len = 4; 869 ret = 1; 870 } 871 872 return ret; 873 } 874 875 void lbs_start_mesh(struct lbs_private *priv) 876 { 877 lbs_add_mesh(priv); 878 879 if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh)) 880 netdev_err(priv->dev, "cannot register lbs_mesh attribute\n"); 881 } 882 883 int lbs_deinit_mesh(struct lbs_private *priv) 884 { 885 struct net_device *dev = priv->dev; 886 int ret = 0; 887 888 if (priv->mesh_tlv) { 889 device_remove_file(&dev->dev, &dev_attr_lbs_mesh); 890 ret = 1; 891 } 892 893 return ret; 894 } 895 896 897 /** 898 * lbs_mesh_stop - close the mshX interface 899 * 900 * @dev: A pointer to &net_device structure 901 * returns: 0 902 */ 903 static int lbs_mesh_stop(struct net_device *dev) 904 { 905 struct lbs_private *priv = dev->ml_priv; 906 907 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 908 lbs_mesh_get_channel(priv)); 909 910 spin_lock_irq(&priv->driver_lock); 911 912 netif_stop_queue(dev); 913 netif_carrier_off(dev); 914 915 spin_unlock_irq(&priv->driver_lock); 916 917 lbs_update_mcast(priv); 918 if (!lbs_iface_active(priv)) 919 lbs_stop_iface(priv); 920 921 return 0; 922 } 923 924 /** 925 * lbs_mesh_dev_open - open the mshX interface 926 * 927 * @dev: A pointer to &net_device structure 928 * returns: 0 or -EBUSY if monitor mode active 929 */ 930 static int lbs_mesh_dev_open(struct net_device *dev) 931 { 932 struct lbs_private *priv = dev->ml_priv; 933 int ret = 0; 934 935 if (!priv->iface_running) { 936 ret = lbs_start_iface(priv); 937 if (ret) 938 goto out; 939 } 940 941 spin_lock_irq(&priv->driver_lock); 942 943 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { 944 ret = -EBUSY; 945 spin_unlock_irq(&priv->driver_lock); 946 goto out; 947 } 948 949 netif_carrier_on(dev); 950 951 if (!priv->tx_pending_len) 952 netif_wake_queue(dev); 953 954 spin_unlock_irq(&priv->driver_lock); 955 956 ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 957 lbs_mesh_get_channel(priv)); 958 959 out: 960 return ret; 961 } 962 963 static const struct net_device_ops mesh_netdev_ops = { 964 .ndo_open = lbs_mesh_dev_open, 965 .ndo_stop = lbs_mesh_stop, 966 .ndo_start_xmit = lbs_hard_start_xmit, 967 .ndo_set_mac_address = lbs_set_mac_address, 968 .ndo_set_rx_mode = lbs_set_multicast_list, 969 }; 970 971 /** 972 * lbs_add_mesh - add mshX interface 973 * 974 * @priv: A pointer to the &struct lbs_private structure 975 * returns: 0 if successful, -X otherwise 976 */ 977 static int lbs_add_mesh(struct lbs_private *priv) 978 { 979 struct net_device *mesh_dev = NULL; 980 struct wireless_dev *mesh_wdev; 981 int ret = 0; 982 983 /* Allocate a virtual mesh device */ 984 mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); 985 if (!mesh_wdev) { 986 lbs_deb_mesh("init mshX wireless device failed\n"); 987 ret = -ENOMEM; 988 goto done; 989 } 990 991 mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup); 992 if (!mesh_dev) { 993 lbs_deb_mesh("init mshX device failed\n"); 994 ret = -ENOMEM; 995 goto err_free_wdev; 996 } 997 998 mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT; 999 mesh_wdev->wiphy = priv->wdev->wiphy; 1000 mesh_wdev->netdev = mesh_dev; 1001 1002 mesh_dev->ml_priv = priv; 1003 mesh_dev->ieee80211_ptr = mesh_wdev; 1004 priv->mesh_dev = mesh_dev; 1005 1006 mesh_dev->netdev_ops = &mesh_netdev_ops; 1007 mesh_dev->ethtool_ops = &lbs_ethtool_ops; 1008 eth_hw_addr_inherit(mesh_dev, priv->dev); 1009 1010 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); 1011 1012 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 1013 /* Register virtual mesh interface */ 1014 ret = register_netdev(mesh_dev); 1015 if (ret) { 1016 pr_err("cannot register mshX virtual interface\n"); 1017 goto err_free_netdev; 1018 } 1019 1020 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); 1021 if (ret) 1022 goto err_unregister; 1023 1024 lbs_persist_config_init(mesh_dev); 1025 1026 /* Everything successful */ 1027 ret = 0; 1028 goto done; 1029 1030 err_unregister: 1031 unregister_netdev(mesh_dev); 1032 1033 err_free_netdev: 1034 free_netdev(mesh_dev); 1035 1036 err_free_wdev: 1037 kfree(mesh_wdev); 1038 1039 done: 1040 return ret; 1041 } 1042 1043 void lbs_remove_mesh(struct lbs_private *priv) 1044 { 1045 struct net_device *mesh_dev; 1046 1047 mesh_dev = priv->mesh_dev; 1048 if (!mesh_dev) 1049 return; 1050 1051 netif_stop_queue(mesh_dev); 1052 netif_carrier_off(mesh_dev); 1053 sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); 1054 lbs_persist_config_remove(mesh_dev); 1055 unregister_netdev(mesh_dev); 1056 priv->mesh_dev = NULL; 1057 kfree(mesh_dev->ieee80211_ptr); 1058 free_netdev(mesh_dev); 1059 } 1060 1061 1062 /*************************************************************************** 1063 * Sending and receiving 1064 */ 1065 struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, 1066 struct net_device *dev, struct rxpd *rxpd) 1067 { 1068 if (priv->mesh_dev) { 1069 if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { 1070 if (rxpd->rx_control & RxPD_MESH_FRAME) 1071 dev = priv->mesh_dev; 1072 } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { 1073 if (rxpd->u.bss.bss_num == MESH_IFACE_ID) 1074 dev = priv->mesh_dev; 1075 } 1076 } 1077 return dev; 1078 } 1079 1080 1081 void lbs_mesh_set_txpd(struct lbs_private *priv, 1082 struct net_device *dev, struct txpd *txpd) 1083 { 1084 if (dev == priv->mesh_dev) { 1085 if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) 1086 txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); 1087 else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) 1088 txpd->u.bss.bss_num = MESH_IFACE_ID; 1089 } 1090 } 1091 1092 1093 /*************************************************************************** 1094 * Ethtool related 1095 */ 1096 1097 static const char mesh_stat_strings[MESH_STATS_NUM][ETH_GSTRING_LEN] = { 1098 "drop_duplicate_bcast", 1099 "drop_ttl_zero", 1100 "drop_no_fwd_route", 1101 "drop_no_buffers", 1102 "fwded_unicast_cnt", 1103 "fwded_bcast_cnt", 1104 "drop_blind_table", 1105 "tx_failed_cnt" 1106 }; 1107 1108 void lbs_mesh_ethtool_get_stats(struct net_device *dev, 1109 struct ethtool_stats *stats, uint64_t *data) 1110 { 1111 struct lbs_private *priv = dev->ml_priv; 1112 struct cmd_ds_mesh_access mesh_access; 1113 int ret; 1114 1115 /* Get Mesh Statistics */ 1116 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); 1117 1118 if (ret) { 1119 memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); 1120 return; 1121 } 1122 1123 priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); 1124 priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); 1125 priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); 1126 priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); 1127 priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); 1128 priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); 1129 priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); 1130 priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); 1131 1132 data[0] = priv->mstats.fwd_drop_rbt; 1133 data[1] = priv->mstats.fwd_drop_ttl; 1134 data[2] = priv->mstats.fwd_drop_noroute; 1135 data[3] = priv->mstats.fwd_drop_nobuf; 1136 data[4] = priv->mstats.fwd_unicast_cnt; 1137 data[5] = priv->mstats.fwd_bcast_cnt; 1138 data[6] = priv->mstats.drop_blind; 1139 data[7] = priv->mstats.tx_failed_cnt; 1140 } 1141 1142 int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset) 1143 { 1144 struct lbs_private *priv = dev->ml_priv; 1145 1146 if (sset == ETH_SS_STATS && dev == priv->mesh_dev) 1147 return MESH_STATS_NUM; 1148 1149 return -EOPNOTSUPP; 1150 } 1151 1152 void lbs_mesh_ethtool_get_strings(struct net_device *dev, 1153 uint32_t stringset, uint8_t *s) 1154 { 1155 switch (stringset) { 1156 case ETH_SS_STATS: 1157 memcpy(s, mesh_stat_strings, sizeof(mesh_stat_strings)); 1158 break; 1159 } 1160 } 1161