mac80211: Add antenna configuration
authorBruno Randolf <br1@einfach.org>
Wed, 10 Nov 2010 03:50:56 +0000 (12:50 +0900)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 16 Nov 2010 21:37:05 +0000 (16:37 -0500)
Allow antenna configuration by calling driver's function for it.

We disallow antenna configuration if the wiphy is already running, mainly to
make life easier for 802.11n drivers which need to recalculate HT capabilites.

Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/driver-ops.h
net/mac80211/driver-trace.h

index 6122e8a3297ec7f5ff9085322753f8b32c926115..a7323eca08d1be98644dc889e64d92a90d375874 100644 (file)
@@ -1799,6 +1799,8 @@ struct ieee80211_ops {
        void (*channel_switch)(struct ieee80211_hw *hw,
                               struct ieee80211_channel_switch *ch_switch);
        int (*napi_poll)(struct ieee80211_hw *hw, int budget);
+       int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+       int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
 };
 
 /**
index 3df12f7d0cfe862117738ffb750eeb5cff163ff9..0c544074479e22efda3a89cbf73fd02d7248a0b5 100644 (file)
@@ -1628,6 +1628,23 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
        ieee80211_queue_work(&local->hw, &local->reconfig_filter);
 }
 
+static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+
+       if (local->started)
+               return -EOPNOTSUPP;
+
+       return drv_set_antenna(local, tx_ant, rx_ant);
+}
+
+static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+
+       return drv_get_antenna(local, tx_ant, rx_ant);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -1680,4 +1697,6 @@ struct cfg80211_ops mac80211_config_ops = {
        .mgmt_tx = ieee80211_mgmt_tx,
        .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
        .mgmt_frame_register = ieee80211_mgmt_frame_register,
+       .set_antenna = ieee80211_set_antenna,
+       .get_antenna = ieee80211_get_antenna,
 };
index 79019f94f621852c6f6c9474d791a9b6bb49b75f..4244554d218af687b7ddb236c2edfc91a4d10b8d 100644 (file)
@@ -442,4 +442,27 @@ static inline void drv_channel_switch(struct ieee80211_local *local,
        trace_drv_return_void(local);
 }
 
+
+static inline int drv_set_antenna(struct ieee80211_local *local,
+                                 u32 tx_ant, u32 rx_ant)
+{
+       int ret = -EOPNOTSUPP;
+       might_sleep();
+       if (local->ops->set_antenna)
+               ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant);
+       trace_drv_set_antenna(local, tx_ant, rx_ant, ret);
+       return ret;
+}
+
+static inline int drv_get_antenna(struct ieee80211_local *local,
+                                 u32 *tx_ant, u32 *rx_ant)
+{
+       int ret = -EOPNOTSUPP;
+       might_sleep();
+       if (local->ops->get_antenna)
+               ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant);
+       trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret);
+       return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
index 431d65500d6ae685e52911a74f5d20bc0c478921..c2772f23ac9cc534f8f6091c7c1961dc12bf209c 100644 (file)
@@ -883,6 +883,56 @@ TRACE_EVENT(drv_channel_switch,
        )
 );
 
+TRACE_EVENT(drv_set_antenna,
+       TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
+
+       TP_ARGS(local, tx_ant, rx_ant, ret),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               __field(u32, tx_ant)
+               __field(u32, rx_ant)
+               __field(int, ret)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               __entry->tx_ant = tx_ant;
+               __entry->rx_ant = rx_ant;
+               __entry->ret = ret;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
+               LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+       )
+);
+
+TRACE_EVENT(drv_get_antenna,
+       TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
+
+       TP_ARGS(local, tx_ant, rx_ant, ret),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               __field(u32, tx_ant)
+               __field(u32, rx_ant)
+               __field(int, ret)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               __entry->tx_ant = tx_ant;
+               __entry->rx_ant = rx_ant;
+               __entry->ret = ret;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
+               LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+       )
+);
+
 /*
  * Tracing for API calls that drivers call.
  */