diff options
Diffstat (limited to 'drivers/net/wireless/libertas/mesh.c')
-rw-r--r-- | drivers/net/wireless/libertas/mesh.c | 222 |
1 files changed, 172 insertions, 50 deletions
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index e385af1f4583..194762ab0142 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/if_arp.h> | 5 | #include <linux/if_arp.h> |
6 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
7 | #include <linux/kfifo.h> | 7 | #include <linux/kfifo.h> |
8 | #include <net/cfg80211.h> | ||
8 | 9 | ||
9 | #include "mesh.h" | 10 | #include "mesh.h" |
10 | #include "decl.h" | 11 | #include "decl.h" |
@@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev) | |||
314 | 315 | ||
315 | spin_lock_irq(&priv->driver_lock); | 316 | spin_lock_irq(&priv->driver_lock); |
316 | 317 | ||
317 | if (priv->monitormode) { | 318 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
318 | ret = -EBUSY; | 319 | ret = -EBUSY; |
319 | goto out; | 320 | goto out; |
320 | } | 321 | } |
@@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv) | |||
369 | 370 | ||
370 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); | 371 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); |
371 | 372 | ||
372 | #ifdef WIRELESS_EXT | ||
373 | mesh_dev->wireless_handlers = &mesh_handler_def; | ||
374 | #endif | ||
375 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 373 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
376 | /* Register virtual mesh interface */ | 374 | /* Register virtual mesh interface */ |
377 | ret = register_netdev(mesh_dev); | 375 | ret = register_netdev(mesh_dev); |
@@ -457,65 +455,189 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
457 | * Mesh command handling | 455 | * Mesh command handling |
458 | */ | 456 | */ |
459 | 457 | ||
460 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | 458 | /** |
461 | u16 cmd_action, void *pdata_buf) | 459 | * @brief Add or delete Mesh Blinding Table entries |
460 | * | ||
461 | * @param priv A pointer to struct lbs_private structure | ||
462 | * @param add TRUE to add the entry, FALSE to delete it | ||
463 | * @param addr1 Destination address to blind or unblind | ||
464 | * | ||
465 | * @return 0 on success, error on failure | ||
466 | */ | ||
467 | int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) | ||
462 | { | 468 | { |
463 | struct cmd_ds_bt_access *bt_access = &cmd->params.bt; | 469 | struct cmd_ds_bt_access cmd; |
464 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | 470 | int ret = 0; |
465 | 471 | ||
466 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | 472 | lbs_deb_enter(LBS_DEB_CMD); |
467 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + | ||
468 | sizeof(struct cmd_header)); | ||
469 | cmd->result = 0; | ||
470 | bt_access->action = cpu_to_le16(cmd_action); | ||
471 | 473 | ||
472 | switch (cmd_action) { | 474 | BUG_ON(addr1 == NULL); |
473 | case CMD_ACT_BT_ACCESS_ADD: | 475 | |
474 | memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); | 476 | memset(&cmd, 0, sizeof(cmd)); |
477 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
478 | memcpy(cmd.addr1, addr1, ETH_ALEN); | ||
479 | if (add) { | ||
480 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD); | ||
475 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", | 481 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", |
476 | bt_access->addr1, 6); | 482 | addr1, ETH_ALEN); |
477 | break; | 483 | } else { |
478 | case CMD_ACT_BT_ACCESS_DEL: | 484 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL); |
479 | memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); | ||
480 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", | 485 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", |
481 | bt_access->addr1, 6); | 486 | addr1, ETH_ALEN); |
482 | break; | ||
483 | case CMD_ACT_BT_ACCESS_LIST: | ||
484 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
485 | break; | ||
486 | case CMD_ACT_BT_ACCESS_RESET: | ||
487 | break; | ||
488 | case CMD_ACT_BT_ACCESS_SET_INVERT: | ||
489 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
490 | break; | ||
491 | case CMD_ACT_BT_ACCESS_GET_INVERT: | ||
492 | break; | ||
493 | default: | ||
494 | break; | ||
495 | } | 487 | } |
496 | lbs_deb_leave(LBS_DEB_CMD); | 488 | |
497 | return 0; | 489 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); |
490 | |||
491 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
492 | return ret; | ||
498 | } | 493 | } |
499 | 494 | ||
500 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | 495 | /** |
501 | u16 cmd_action, void *pdata_buf) | 496 | * @brief Reset/clear the mesh blinding table |
497 | * | ||
498 | * @param priv A pointer to struct lbs_private structure | ||
499 | * | ||
500 | * @return 0 on success, error on failure | ||
501 | */ | ||
502 | int lbs_mesh_bt_reset(struct lbs_private *priv) | ||
502 | { | 503 | { |
503 | struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; | 504 | struct cmd_ds_bt_access cmd; |
504 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | 505 | int ret = 0; |
505 | 506 | ||
506 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | 507 | lbs_deb_enter(LBS_DEB_CMD); |
507 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + | ||
508 | sizeof(struct cmd_header)); | ||
509 | cmd->result = 0; | ||
510 | 508 | ||
511 | if (pdata_buf) | 509 | memset(&cmd, 0, sizeof(cmd)); |
512 | memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); | 510 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
513 | else | 511 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET); |
514 | memset(fwt_access, 0, sizeof(*fwt_access)); | ||
515 | 512 | ||
516 | fwt_access->action = cpu_to_le16(cmd_action); | 513 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); |
517 | 514 | ||
518 | lbs_deb_leave(LBS_DEB_CMD); | 515 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
516 | return ret; | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * @brief Gets the inverted status of the mesh blinding table | ||
521 | * | ||
522 | * Normally the firmware "blinds" or ignores traffic from mesh nodes in the | ||
523 | * table, but an inverted table allows *only* traffic from nodes listed in | ||
524 | * the table. | ||
525 | * | ||
526 | * @param priv A pointer to struct lbs_private structure | ||
527 | * @param invert On success, TRUE if the blinding table is inverted, | ||
528 | * FALSE if it is not inverted | ||
529 | * | ||
530 | * @return 0 on success, error on failure | ||
531 | */ | ||
532 | int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) | ||
533 | { | ||
534 | struct cmd_ds_bt_access cmd; | ||
535 | int ret = 0; | ||
536 | |||
537 | lbs_deb_enter(LBS_DEB_CMD); | ||
538 | |||
539 | BUG_ON(inverted == NULL); | ||
540 | |||
541 | memset(&cmd, 0, sizeof(cmd)); | ||
542 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
543 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT); | ||
544 | |||
545 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); | ||
546 | if (ret == 0) | ||
547 | *inverted = !!cmd.id; | ||
548 | |||
549 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | /** | ||
554 | * @brief Sets the inverted status of the mesh blinding table | ||
555 | * | ||
556 | * Normally the firmware "blinds" or ignores traffic from mesh nodes in the | ||
557 | * table, but an inverted table allows *only* traffic from nodes listed in | ||
558 | * the table. | ||
559 | * | ||
560 | * @param priv A pointer to struct lbs_private structure | ||
561 | * @param invert TRUE to invert the blinding table (only traffic from | ||
562 | * listed nodes allowed), FALSE to return it | ||
563 | * to normal state (listed nodes ignored) | ||
564 | * | ||
565 | * @return 0 on success, error on failure | ||
566 | */ | ||
567 | int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) | ||
568 | { | ||
569 | struct cmd_ds_bt_access cmd; | ||
570 | int ret = 0; | ||
571 | |||
572 | lbs_deb_enter(LBS_DEB_CMD); | ||
573 | |||
574 | memset(&cmd, 0, sizeof(cmd)); | ||
575 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
576 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); | ||
577 | cmd.id = !!inverted; | ||
578 | |||
579 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); | ||
580 | |||
581 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | /** | ||
586 | * @brief List an entry in the mesh blinding table | ||
587 | * | ||
588 | * @param priv A pointer to struct lbs_private structure | ||
589 | * @param id The ID of the entry to list | ||
590 | * @param addr1 MAC address associated with the table entry | ||
591 | * | ||
592 | * @return 0 on success, error on failure | ||
593 | */ | ||
594 | int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) | ||
595 | { | ||
596 | struct cmd_ds_bt_access cmd; | ||
597 | int ret = 0; | ||
598 | |||
599 | lbs_deb_enter(LBS_DEB_CMD); | ||
600 | |||
601 | BUG_ON(addr1 == NULL); | ||
602 | |||
603 | memset(&cmd, 0, sizeof(cmd)); | ||
604 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
605 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); | ||
606 | cmd.id = cpu_to_le32(id); | ||
607 | |||
608 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); | ||
609 | if (ret == 0) | ||
610 | memcpy(addr1, cmd.addr1, sizeof(cmd.addr1)); | ||
611 | |||
612 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * @brief Access the mesh forwarding table | ||
618 | * | ||
619 | * @param priv A pointer to struct lbs_private structure | ||
620 | * @param cmd_action The forwarding table action to perform | ||
621 | * @param cmd The pre-filled FWT_ACCESS command | ||
622 | * | ||
623 | * @return 0 on success and 'cmd' will be filled with the | ||
624 | * firmware's response | ||
625 | */ | ||
626 | int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, | ||
627 | struct cmd_ds_fwt_access *cmd) | ||
628 | { | ||
629 | int ret; | ||
630 | |||
631 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
632 | |||
633 | cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS); | ||
634 | cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access)); | ||
635 | cmd->hdr.result = 0; | ||
636 | cmd->action = cpu_to_le16(cmd_action); | ||
637 | |||
638 | ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd); | ||
639 | |||
640 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
519 | return 0; | 641 | return 0; |
520 | } | 642 | } |
521 | 643 | ||