summaryrefslogtreecommitdiff
path: root/drivers/staging/cw1200/txrx.c
diff options
context:
space:
mode:
authorAmit Shakya <amit.shakya@stericsson.com>2011-09-21 14:41:58 +0530
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-13 10:18:33 +0200
commitafa3d7b12a74b0583e5c46f8a4d889a2086691ff (patch)
treef55225b1c4766938e15962684b760fa5fa0a5cb4 /drivers/staging/cw1200/txrx.c
parentb4fc8cc9749880779001b76c43fc8b90ca71a6b1 (diff)
cw1200: Add BT Coexistence support
BT Coexistence support required setting priority to frames for PTA arbitration FW, parsing SDD file for getting the listen interval and using the same in assoc request, modifying Tx rate for PSPOLL and NULL templates (plumbing them) ST-Ericsson ID: 357776 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-10091 Change-Id: I14f05cbcc2f02b85f72dbe820893cef9c3775df7 Signed-off-by: Amit Shakya <amit.shakya@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31602 Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33528 Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com> Tested-by: Dmitry TARNYAGIN <dmitry.tarnyagin@stericsson.com>
Diffstat (limited to 'drivers/staging/cw1200/txrx.c')
-rw-r--r--drivers/staging/cw1200/txrx.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/drivers/staging/cw1200/txrx.c b/drivers/staging/cw1200/txrx.c
index 1742af0ac8e..3e8b84fa43c 100644
--- a/drivers/staging/cw1200/txrx.c
+++ b/drivers/staging/cw1200/txrx.c
@@ -371,12 +371,13 @@ cw1200_get_tx_rate(const struct cw1200_common *priv,
/* NOTE: cw1200_skb_to_wsm executes in atomic context. */
int cw1200_skb_to_wsm(struct cw1200_common *priv, struct sk_buff *skb,
- struct wsm_tx *wsm)
+ struct wsm_tx *wsm, struct tx_info *txinfo)
{
bool tx_policy_renew = false;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
const struct ieee80211_rate *rate = cw1200_get_tx_rate(priv,
&tx_info->control.rates[0]);
+ u8 priority = 0;
memset(wsm, 0, sizeof(*wsm));
wsm->hdr.len = __cpu_to_le16(skb->len);
@@ -409,6 +410,32 @@ int cw1200_skb_to_wsm(struct cw1200_common *priv, struct sk_buff *skb,
}
wsm->queueId = wsm_queue_id_to_wsm(skb_get_queue_mapping(skb));
+
+ /* BT Coex specific handling */
+ if (priv->is_BT_Present) {
+ struct ieee80211_hdr *hdr =
+ (struct ieee80211_hdr *)(skb->data + sizeof(struct wsm_tx));
+
+ if (cpu_to_be16(txinfo->ethertype) == ETH_P_PAE)
+ priority = WSM_EPTA_PRIORITY_EAPOL;
+ else if (ieee80211_is_action(hdr->frame_control))
+ priority = WSM_EPTA_PRIORITY_ACTION;
+ else if (ieee80211_is_mgmt(hdr->frame_control))
+ priority = WSM_EPTA_PRIORITY_MGT;
+ else if ((wsm->queueId == WSM_QUEUE_VOICE))
+ priority = WSM_EPTA_PRIORITY_VOICE;
+ else if ((wsm->queueId == WSM_QUEUE_VIDEO))
+ priority = WSM_EPTA_PRIORITY_VIDEO;
+ else
+ priority = WSM_EPTA_PRIORITY_DATA;
+
+ txrx_printk(KERN_DEBUG "[TX] EPTA priority %x.\n",
+ ((priority) & 0x7));
+
+ /* Set EPTA priority */
+ wsm->flags |= (((priority) & 0x7) << 1);
+ }
+
return 0;
}
@@ -427,6 +454,7 @@ void cw1200_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
int link_id;
int ret;
int i;
+ struct tx_info txinfo;
if (likely(tx_info->control.sta && sta_priv->link_id))
link_id = sta_priv->link_id;
@@ -465,6 +493,39 @@ void cw1200_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
spin_unlock_bh(&priv->buffered_multicasts_lock);
}
+ /* BT Coex support related configuration */
+ if (priv->is_BT_Present) {
+ txinfo.ethertype = 0;
+
+ if (ieee80211_is_data_qos(hdr->frame_control) ||
+ ieee80211_is_data(hdr->frame_control)) {
+ unsigned int headerlen =
+ ieee80211_get_hdrlen_from_skb(skb);
+
+ /* Skip LLC SNAP header (+6) */
+ if (headerlen > 0)
+ txinfo.ethertype =
+ *((u16 *)(skb->data + headerlen + 6));
+ }
+ else if (ieee80211_is_assoc_req(hdr->frame_control) ||
+ ieee80211_is_reassoc_req(hdr->frame_control)) {
+ struct ieee80211_mgmt *mgt_frame =
+ (struct ieee80211_mgmt *)skb->data;
+
+ if (mgt_frame->u.assoc_req.listen_interval <
+ priv->listen_interval) {
+ txrx_printk(KERN_DEBUG
+ "Modified Listen Interval to %x from %x\n",
+ priv->listen_interval,
+ mgt_frame->u.assoc_req.listen_interval);
+ /* Replace listen interval derieved from
+ the one read from SDD */
+ mgt_frame->u.assoc_req.listen_interval =
+ priv->listen_interval;
+ }
+ }
+ }
+
/* IV/ICV injection. */
/* TODO: Quite unoptimal. It's better co modify mac80211
* to reserve space for IV */
@@ -543,8 +604,10 @@ void cw1200_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
queue_work(priv->workqueue,
&priv->multicast_start_work);
}
+
+ txinfo.link_id = link_id;
ret = cw1200_queue_put(&priv->tx_queue[queue], priv, skb,
- link_id);
+ &txinfo);
spin_unlock_bh(&priv->buffered_multicasts_lock);
if (!WARN_ON(ret))