diff options
Diffstat (limited to 'drivers/net/wireless/libertas/mesh.c')
-rw-r--r-- | drivers/net/wireless/libertas/mesh.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 3e12060a6470..2f91c9b808af 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -441,6 +441,181 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
441 | 441 | ||
442 | 442 | ||
443 | /*************************************************************************** | 443 | /*************************************************************************** |
444 | * Mesh command handling | ||
445 | */ | ||
446 | |||
447 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | ||
448 | u16 cmd_action, void *pdata_buf) | ||
449 | { | ||
450 | struct cmd_ds_bt_access *bt_access = &cmd->params.bt; | ||
451 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
452 | |||
453 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | ||
454 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + | ||
455 | sizeof(struct cmd_header)); | ||
456 | cmd->result = 0; | ||
457 | bt_access->action = cpu_to_le16(cmd_action); | ||
458 | |||
459 | switch (cmd_action) { | ||
460 | case CMD_ACT_BT_ACCESS_ADD: | ||
461 | memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); | ||
462 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", | ||
463 | bt_access->addr1, 6); | ||
464 | break; | ||
465 | case CMD_ACT_BT_ACCESS_DEL: | ||
466 | memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); | ||
467 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", | ||
468 | bt_access->addr1, 6); | ||
469 | break; | ||
470 | case CMD_ACT_BT_ACCESS_LIST: | ||
471 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
472 | break; | ||
473 | case CMD_ACT_BT_ACCESS_RESET: | ||
474 | break; | ||
475 | case CMD_ACT_BT_ACCESS_SET_INVERT: | ||
476 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
477 | break; | ||
478 | case CMD_ACT_BT_ACCESS_GET_INVERT: | ||
479 | break; | ||
480 | default: | ||
481 | break; | ||
482 | } | ||
483 | lbs_deb_leave(LBS_DEB_CMD); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | ||
488 | u16 cmd_action, void *pdata_buf) | ||
489 | { | ||
490 | struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; | ||
491 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
492 | |||
493 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | ||
494 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + | ||
495 | sizeof(struct cmd_header)); | ||
496 | cmd->result = 0; | ||
497 | |||
498 | if (pdata_buf) | ||
499 | memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); | ||
500 | else | ||
501 | memset(fwt_access, 0, sizeof(*fwt_access)); | ||
502 | |||
503 | fwt_access->action = cpu_to_le16(cmd_action); | ||
504 | |||
505 | lbs_deb_leave(LBS_DEB_CMD); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
510 | struct cmd_ds_mesh_access *cmd) | ||
511 | { | ||
512 | int ret; | ||
513 | |||
514 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
515 | |||
516 | cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); | ||
517 | cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); | ||
518 | cmd->hdr.result = 0; | ||
519 | |||
520 | cmd->action = cpu_to_le16(cmd_action); | ||
521 | |||
522 | ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); | ||
523 | |||
524 | lbs_deb_leave(LBS_DEB_CMD); | ||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static int __lbs_mesh_config_send(struct lbs_private *priv, | ||
529 | struct cmd_ds_mesh_config *cmd, | ||
530 | uint16_t action, uint16_t type) | ||
531 | { | ||
532 | int ret; | ||
533 | u16 command = CMD_MESH_CONFIG_OLD; | ||
534 | |||
535 | lbs_deb_enter(LBS_DEB_CMD); | ||
536 | |||
537 | /* | ||
538 | * Command id is 0xac for v10 FW along with mesh interface | ||
539 | * id in bits 14-13-12. | ||
540 | */ | ||
541 | if (priv->mesh_fw_ver == MESH_FW_NEW) | ||
542 | command = CMD_MESH_CONFIG | | ||
543 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | ||
544 | |||
545 | cmd->hdr.command = cpu_to_le16(command); | ||
546 | cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); | ||
547 | cmd->hdr.result = 0; | ||
548 | |||
549 | cmd->type = cpu_to_le16(type); | ||
550 | cmd->action = cpu_to_le16(action); | ||
551 | |||
552 | ret = lbs_cmd_with_response(priv, command, cmd); | ||
553 | |||
554 | lbs_deb_leave(LBS_DEB_CMD); | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
559 | struct cmd_ds_mesh_config *cmd, | ||
560 | uint16_t action, uint16_t type) | ||
561 | { | ||
562 | int ret; | ||
563 | |||
564 | if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) | ||
565 | return -EOPNOTSUPP; | ||
566 | |||
567 | ret = __lbs_mesh_config_send(priv, cmd, action, type); | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | /* This function is the CMD_MESH_CONFIG legacy function. It only handles the | ||
572 | * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG | ||
573 | * are all handled by preparing a struct cmd_ds_mesh_config and passing it to | ||
574 | * lbs_mesh_config_send. | ||
575 | */ | ||
576 | int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | ||
577 | { | ||
578 | struct cmd_ds_mesh_config cmd; | ||
579 | struct mrvl_meshie *ie; | ||
580 | DECLARE_SSID_BUF(ssid); | ||
581 | |||
582 | memset(&cmd, 0, sizeof(cmd)); | ||
583 | cmd.channel = cpu_to_le16(chan); | ||
584 | ie = (struct mrvl_meshie *)cmd.data; | ||
585 | |||
586 | switch (action) { | ||
587 | case CMD_ACT_MESH_CONFIG_START: | ||
588 | ie->id = WLAN_EID_GENERIC; | ||
589 | ie->val.oui[0] = 0x00; | ||
590 | ie->val.oui[1] = 0x50; | ||
591 | ie->val.oui[2] = 0x43; | ||
592 | ie->val.type = MARVELL_MESH_IE_TYPE; | ||
593 | ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; | ||
594 | ie->val.version = MARVELL_MESH_IE_VERSION; | ||
595 | ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; | ||
596 | ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; | ||
597 | ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; | ||
598 | ie->val.mesh_id_len = priv->mesh_ssid_len; | ||
599 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); | ||
600 | ie->len = sizeof(struct mrvl_meshie_val) - | ||
601 | IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; | ||
602 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); | ||
603 | break; | ||
604 | case CMD_ACT_MESH_CONFIG_STOP: | ||
605 | break; | ||
606 | default: | ||
607 | return -1; | ||
608 | } | ||
609 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", | ||
610 | action, priv->mesh_tlv, chan, | ||
611 | print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); | ||
612 | |||
613 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | ||
614 | } | ||
615 | |||
616 | |||
617 | |||
618 | /*************************************************************************** | ||
444 | * Persistent configuration support | 619 | * Persistent configuration support |
445 | */ | 620 | */ |
446 | 621 | ||