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