aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>2014-02-27 09:20:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-28 14:33:27 -0500
commit1647f12f1b511c2629b9b8d23061aa54ad8a9795 (patch)
tree07753b3fa605dd542f6081c3f558f9bc5d5fcca2 /drivers
parentc98db0bec72ac7ef127119c1ed962d6f56802b12 (diff)
wil6210: Tx management frame
Implement management frame passing. In order to receive frame on the other side, remain_on_channel() should be implemented as well Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c72
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h1
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c32
3 files changed, 105 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 5b340769d5bb..204c7c82b1b5 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -352,6 +352,40 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
352 return rc; 352 return rc;
353} 353}
354 354
355static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
356 struct wireless_dev *wdev,
357 struct cfg80211_mgmt_tx_params *params,
358 u64 *cookie)
359{
360 const u8 *buf = params->buf;
361 size_t len = params->len;
362 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
363 int rc;
364 struct ieee80211_mgmt *mgmt_frame = (void *)buf;
365 struct wmi_sw_tx_req_cmd *cmd;
366 struct {
367 struct wil6210_mbox_hdr_wmi wmi;
368 struct wmi_sw_tx_complete_event evt;
369 } __packed evt;
370
371 cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
372 if (!cmd)
373 return -ENOMEM;
374
375 memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
376 cmd->len = cpu_to_le16(len);
377 memcpy(cmd->payload, buf, len);
378
379 rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
380 WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
381 if (rc == 0)
382 rc = evt.evt.status;
383
384 kfree(cmd);
385
386 return rc;
387}
388
355static int wil_cfg80211_set_channel(struct wiphy *wiphy, 389static int wil_cfg80211_set_channel(struct wiphy *wiphy,
356 struct cfg80211_chan_def *chandef) 390 struct cfg80211_chan_def *chandef)
357{ 391{
@@ -402,6 +436,41 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
402 return 0; 436 return 0;
403} 437}
404 438
439static int wil_remain_on_channel(struct wiphy *wiphy,
440 struct wireless_dev *wdev,
441 struct ieee80211_channel *chan,
442 unsigned int duration,
443 u64 *cookie)
444{
445 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
446 int rc;
447
448 /* TODO: handle duration */
449 wil_info(wil, "%s(%d, %d ms)\n", __func__, chan->center_freq, duration);
450
451 rc = wmi_set_channel(wil, chan->hw_value);
452 if (rc)
453 return rc;
454
455 rc = wmi_rxon(wil, true);
456
457 return rc;
458}
459
460static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
461 struct wireless_dev *wdev,
462 u64 cookie)
463{
464 struct wil6210_priv *wil = wiphy_to_wil(wiphy);
465 int rc;
466
467 wil_info(wil, "%s()\n", __func__);
468
469 rc = wmi_rxon(wil, false);
470
471 return rc;
472}
473
405static int wil_fix_bcon(struct wil6210_priv *wil, 474static int wil_fix_bcon(struct wil6210_priv *wil,
406 struct cfg80211_beacon_data *bcon) 475 struct cfg80211_beacon_data *bcon)
407{ 476{
@@ -510,6 +579,9 @@ static struct cfg80211_ops wil_cfg80211_ops = {
510 .disconnect = wil_cfg80211_disconnect, 579 .disconnect = wil_cfg80211_disconnect,
511 .change_virtual_intf = wil_cfg80211_change_iface, 580 .change_virtual_intf = wil_cfg80211_change_iface,
512 .get_station = wil_cfg80211_get_station, 581 .get_station = wil_cfg80211_get_station,
582 .remain_on_channel = wil_remain_on_channel,
583 .cancel_remain_on_channel = wil_cancel_remain_on_channel,
584 .mgmt_tx = wil_cfg80211_mgmt_tx,
513 .set_monitor_channel = wil_cfg80211_set_channel, 585 .set_monitor_channel = wil_cfg80211_set_channel,
514 .add_key = wil_cfg80211_add_key, 586 .add_key = wil_cfg80211_add_key,
515 .del_key = wil_cfg80211_del_key, 587 .del_key = wil_cfg80211_del_key,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 1f91eaf95bbe..0d7fba4f09e2 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -357,6 +357,7 @@ int wmi_echo(struct wil6210_priv *wil);
357int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); 357int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
358int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); 358int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
359int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); 359int wmi_p2p_cfg(struct wil6210_priv *wil, int channel);
360int wmi_rxon(struct wil6210_priv *wil, bool on);
360int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); 361int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
361 362
362int wil6210_init_irq(struct wil6210_priv *wil, int irq); 363int wil6210_init_irq(struct wil6210_priv *wil, int irq);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 063963ee422a..d65da5590c5f 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -893,6 +893,38 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
893 return rc; 893 return rc;
894} 894}
895 895
896/**
897 * wmi_rxon - turn radio on/off
898 * @on: turn on if true, off otherwise
899 *
900 * Only switch radio. Channel should be set separately.
901 * No timeout for rxon - radio turned on forever unless some other call
902 * turns it off
903 */
904int wmi_rxon(struct wil6210_priv *wil, bool on)
905{
906 int rc;
907 struct {
908 struct wil6210_mbox_hdr_wmi wmi;
909 struct wmi_listen_started_event evt;
910 } __packed reply;
911
912 wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off");
913
914 if (on) {
915 rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
916 WMI_LISTEN_STARTED_EVENTID,
917 &reply, sizeof(reply), 100);
918 if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
919 rc = -EINVAL;
920 } else {
921 rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
922 WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
923 }
924
925 return rc;
926}
927
896int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) 928int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
897{ 929{
898 struct wireless_dev *wdev = wil->wdev; 930 struct wireless_dev *wdev = wil->wdev;