2011-12-16 08:54:45

by Raja Mani

[permalink] [raw]
Subject: [PATCH 1/2] ath6kl: Avoid taking struct as argument in ath6kl_wmi_set_ip_cmd

In this way, caller is free to pass only the value of IP addr
to configure.

In addition to this,
* 'ips' variable data type in struct wmi_set_ip_cmd is changed
from __le32 to __be32 in order to match network byte order.
* ipv4_is_multicast() is used to validate multicast ip addr.
* New argument if_idx is added to supply correct vif index
to ath6kl_wmi_cmd_send().

This will be used in the next patch.

Signed-off-by: Raja Mani <[email protected]>
Signed-off-by: Thirumalai Pachamuthu <[email protected]>
---
drivers/net/wireless/ath/ath6kl/wmi.c | 12 +++++++-----
drivers/net/wireless/ath/ath6kl/wmi.h | 5 +++--
2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index f6f2aa2..1e31c38 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2479,15 +2479,16 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
return ret;
}

-int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
+int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
+ __be32 ips0, __be32 ips1)
{
struct sk_buff *skb;
struct wmi_set_ip_cmd *cmd;
int ret;

/* Multicast address are not valid */
- if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) ||
- (*((u8 *) &ip_cmd->ips[1]) >= 0xE0))
+ if (ipv4_is_multicast(ips0) ||
+ ipv4_is_multicast(ips1))
return -EINVAL;

skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
@@ -2495,9 +2496,10 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
return -ENOMEM;

cmd = (struct wmi_set_ip_cmd *) skb->data;
- memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd));
+ cmd->ips[0] = ips0;
+ cmd->ips[1] = ips1;

- ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID,
+ ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 42ac311..96e3cc1 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1903,7 +1903,7 @@ struct wow_filter {

struct wmi_set_ip_cmd {
/* IP in network byte order */
- __le32 ips[MAX_IP_ADDRS];
+ __be32 ips[MAX_IP_ADDRS];
} __packed;

enum ath6kl_wow_filters {
@@ -2417,7 +2417,8 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);

s32 ath6kl_wmi_get_rate(s8 rate_index);

-int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
+int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
+ __be32 ips0, __be32 ips1);
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode);
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
--
1.7.1



2011-12-23 12:51:36

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath6kl: Avoid taking struct as argument in ath6kl_wmi_set_ip_cmd

On 12/16/2011 10:54 AM, Raja Mani wrote:
> In this way, caller is free to pass only the value of IP addr
> to configure.
>
> In addition to this,
> * 'ips' variable data type in struct wmi_set_ip_cmd is changed
> from __le32 to __be32 in order to match network byte order.
> * ipv4_is_multicast() is used to validate multicast ip addr.
> * New argument if_idx is added to supply correct vif index
> to ath6kl_wmi_cmd_send().
>
> This will be used in the next patch.
>
> Signed-off-by: Raja Mani <[email protected]>
> Signed-off-by: Thirumalai Pachamuthu <[email protected]>

Thanks, both patches applied.

Kalle

2011-12-16 08:54:54

by Raja Mani

[permalink] [raw]
Subject: [PATCH 2/2] ath6kl: Send own IP addr to the firmware during WOW suspend

Firmware ARP module requires own IP addr in order to respond
to the outside world when the target is in WOW suspend state.

At present, firmware ARP module has capability to hold 2 IP addr.
So, WOW mode will be disabled if the total IP addr configured in
net_dev for our device is greater than firmware limit (MAX_IP_ADDRS)
which is 2 at this moment.

Signed-off-by: Raja Mani <[email protected]>
Signed-off-by: Thirumalai Pachamuthu <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 33 +++++++++++++++++++++++++++-
1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 6c59a21..967932b 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -15,6 +15,7 @@
*/

#include <linux/moduleparam.h>
+#include <linux/inetdevice.h>

#include "core.h"
#include "cfg80211.h"
@@ -1730,11 +1731,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)

static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
{
+ struct in_device *in_dev;
+ struct in_ifaddr *ifa;
struct ath6kl_vif *vif;
int ret, pos, left;
u32 filter = 0;
u16 i;
- u8 mask[WOW_MASK_SIZE];
+ u8 mask[WOW_MASK_SIZE], index = 0;
+ __be32 ips[MAX_IP_ADDRS];

vif = ath6kl_vif_first(ar);
if (!vif)
@@ -1781,6 +1785,33 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
return ret;
}

+ /* Setup own IP addr for ARP agent. */
+ in_dev = __in_dev_get_rtnl(vif->ndev);
+ if (!in_dev)
+ goto skip_arp;
+
+ ifa = in_dev->ifa_list;
+ memset(&ips, 0, sizeof(ips));
+
+ /* Configure IP addr only if IP address count < MAX_IP_ADDRS */
+ while (index < MAX_IP_ADDRS && ifa) {
+ ips[index] = ifa->ifa_local;
+ ifa = ifa->ifa_next;
+ index++;
+ }
+
+ if (ifa) {
+ ath6kl_err("total IP addr count is exceeding fw limit\n");
+ return -EINVAL;
+ }
+
+ ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]);
+ if (ret) {
+ ath6kl_err("fail to setup ip for arp agent\n");
+ return ret;
+ }
+
+skip_arp:
if (wow->disconnect)
filter |= WOW_FILTER_OPTION_NWK_DISASSOC;

--
1.7.1