From 3f1732462c0e45ac9b0c09035751d7b2c1b89cc0 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 19 Jul 2012 11:46:13 -0300 Subject: [PATCH 001/109] Bluetooth: Remove missing code This patch removes the struct adv_entry since it is not used anymore. This struct should have been removed in commit 479453d (Bluetooth: Remove advertising cache). Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 475b8c04ba52..41b26648e79e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -115,12 +115,6 @@ struct oob_data { u8 randomizer[16]; }; -struct adv_entry { - struct list_head list; - bdaddr_t bdaddr; - u8 bdaddr_type; -}; - struct le_scan_params { u8 type; u16 interval; From bb4b2a9ae38ef3bac69627f35e4f916752631fd1 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:40 +0300 Subject: [PATCH 002/109] Bluetooth: mgmt: Managing only BR/EDR HCI controllers Add check that HCI controller is BR/EDR. AMP controller shall not be managed by mgmt interface and consequently user space. Signed-off-by: Andrei Emeltchenko Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 6 ++++-- net/bluetooth/mgmt.c | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 41b26648e79e..5c7a5f819fcf 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1050,7 +1050,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_interleaved_discovery(struct hci_dev *hdev); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); - +bool mgmt_valid_hdev(struct hci_dev *hdev); int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); /* HCI info for socket */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5a..fa974a19d365 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev) hci_dev_hold(hdev); set_bit(HCI_UP, &hdev->flags); hci_notify(hdev, HCI_DEV_UP); - if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { + if (!test_bit(HCI_SETUP, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 1); hci_dev_unlock(hdev); @@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) * and no tasks are scheduled. */ hdev->close(hdev); - if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 0); hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca6..2a0f695e33d4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = { MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ }; +bool mgmt_valid_hdev(struct hci_dev *hdev) +{ + return hdev->dev_type == HCI_BREDR; +} + static u8 mgmt_status(u8 hci_status) { if (hci_status < ARRAY_SIZE(mgmt_status_table)) @@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { struct mgmt_rp_read_index_list *rp; - struct list_head *p; struct hci_dev *d; size_t rp_len; u16 count; @@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, read_lock(&hci_dev_list_lock); count = 0; - list_for_each(p, &hci_dev_list) { + list_for_each_entry(d, &hci_dev_list, list) { + if (!mgmt_valid_hdev(d)) + continue; + count++; } @@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (test_bit(HCI_SETUP, &d->dev_flags)) continue; + if (!mgmt_valid_hdev(d)) + continue; + rp->index[i++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } @@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data) int mgmt_index_added(struct hci_dev *hdev) { + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); } @@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev) { u8 status = MGMT_STATUS_INVALID_INDEX; + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); From 8e8c7e36fb216d2d072116de3bec6130627ad691 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:41 +0300 Subject: [PATCH 003/109] Bluetooth: debug: Fix printing A2MP cmd code format Print A2MP code format according to Bluetooth style. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/a2mp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 4ff0bf3ba9a5..57094c136230 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -316,7 +316,7 @@ send_rsp: static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, struct a2mp_cmd *hdr) { - BT_DBG("ident %d code %d", hdr->ident, hdr->code); + BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code); skb_pull(skb, le16_to_cpu(hdr->len)); return 0; @@ -335,7 +335,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) struct a2mp_cmd *hdr = (void *) skb->data; u16 len = le16_to_cpu(hdr->len); - BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); + BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); skb_pull(skb, sizeof(*hdr)); From 71becf0cea91380200ab9460e5126aeff5d7420b Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:42 +0300 Subject: [PATCH 004/109] Bluetooth: debug: Fix printing refcnt for hci_conn Use the same style for refcnt printing through all Bluetooth code taking the reference the l2cap_chan refcnt printing. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5c7a5f819fcf..03b8b6526400 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -581,8 +581,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { - BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), - atomic_read(&conn->refcnt) + 1); + BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); atomic_inc(&conn->refcnt); cancel_delayed_work(&conn->disc_work); @@ -590,8 +589,7 @@ static inline void hci_conn_hold(struct hci_conn *conn) static inline void hci_conn_put(struct hci_conn *conn) { - BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), - atomic_read(&conn->refcnt) - 1); + BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt)); if (atomic_dec_and_test(&conn->refcnt)) { unsigned long timeo; From b93a68295f3a2b1b66d235ce8f9f5a97553f0d0e Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:44 +0300 Subject: [PATCH 005/109] Bluetooth: trivial: Fix mixing spaces and tabs in smp Change spaces to tabs in smp code Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/smp.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index ca356a734920..50993a531d45 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -108,8 +108,8 @@ struct smp_cmd_security_req { #define SMP_CONFIRM_FAILED 0x04 #define SMP_PAIRING_NOTSUPP 0x05 #define SMP_ENC_KEY_SIZE 0x06 -#define SMP_CMD_NOTSUPP 0x07 -#define SMP_UNSPECIFIED 0x08 +#define SMP_CMD_NOTSUPP 0x07 +#define SMP_UNSPECIFIED 0x08 #define SMP_REPEATED_ATTEMPTS 0x09 #define SMP_MIN_ENC_KEY_SIZE 7 @@ -123,8 +123,8 @@ struct smp_chan { struct l2cap_conn *conn; u8 preq[7]; /* SMP Pairing Request */ u8 prsp[7]; /* SMP Pairing Response */ - u8 prnd[16]; /* SMP Pairing Random (local) */ - u8 rrnd[16]; /* SMP Pairing Random (remote) */ + u8 prnd[16]; /* SMP Pairing Random (local) */ + u8 rrnd[16]; /* SMP Pairing Random (remote) */ u8 pcnf[16]; /* SMP Pairing Confirm */ u8 tk[16]; /* SMP Temporary Key */ u8 enc_key_size; From ab846ec4eaea1156148841b194df808ad745bbe2 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:45 +0300 Subject: [PATCH 006/109] Bluetooth: Define AMP controller statuses AMP status codes copied from Bluez patch sent by Peter Krystad . Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ccd723e0f783..7f1955662455 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -62,6 +62,15 @@ /* First BR/EDR Controller shall have ID = 0 */ #define HCI_BREDR_ID 0 +/* AMP controller status */ +#define AMP_CTRL_POWERED_DOWN 0x00 +#define AMP_CTRL_BLUETOOTH_ONLY 0x01 +#define AMP_CTRL_NO_CAPACITY 0x02 +#define AMP_CTRL_LOW_CAPACITY 0x03 +#define AMP_CTRL_MEDIUM_CAPACITY 0x04 +#define AMP_CTRL_HIGH_CAPACITY 0x05 +#define AMP_CTRL_FULL_CAPACITY 0x06 + /* HCI device quirks */ enum { HCI_QUIRK_RESET_ON_CLOSE, From d9fc1d54f6f8123909cdee4fa98ab1ebf6c8651c Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:46 +0300 Subject: [PATCH 007/109] Bluetooth: Do not shadow hdr variable Fix compile warnings below: ... net/bluetooth/a2mp.c:505:33: warning: symbol 'hdr' shadows an earlier one net/bluetooth/a2mp.c:498:25: originally declared here ... Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/a2mp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 57094c136230..79af661a58dd 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -325,15 +325,17 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, /* Handle A2MP signalling */ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - struct a2mp_cmd *hdr = (void *) skb->data; + struct a2mp_cmd *hdr; struct amp_mgr *mgr = chan->data; int err = 0; amp_mgr_get(mgr); while (skb->len >= sizeof(*hdr)) { - struct a2mp_cmd *hdr = (void *) skb->data; - u16 len = le16_to_cpu(hdr->len); + u16 len; + + hdr = (void *) skb->data; + len = le16_to_cpu(hdr->len); BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); @@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) if (err) { struct a2mp_cmd_rej rej; + rej.reason = __constant_cpu_to_le16(0); + hdr = (void *) skb->data; BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); From 78eb2f985c17eab34a0ef919b3263d6b08064e98 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:47 +0300 Subject: [PATCH 008/109] Bluetooth: Fix processing A2MP chan in security_cfm Do not process A2MP channel in l2cap_security_cfm Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bfb..64d88a603f0a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5404,6 +5404,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, state_to_string(chan->state)); + if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { + l2cap_chan_unlock(chan); + continue; + } + if (chan->scid == L2CAP_CID_LE_DATA) { if (!status && encrypt) { chan->sec_level = hcon->sec_level; From ed3fa31f35896b42c54333edabf0a9e986fa952c Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:46 -0300 Subject: [PATCH 009/109] Bluetooth: Use lmp_bredr_capable where applicable This patch replaces all LMP_NO_BREDR bit checking by the helper macro lmp_bredr_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2a0f695e33d4..990ec6affca5 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -383,7 +383,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (hdev->features[6] & LMP_SIMPLE_PAIR) settings |= MGMT_SETTING_SSP; - if (!(hdev->features[4] & LMP_NO_BREDR)) { + if (lmp_bredr_capable(hdev)) { settings |= MGMT_SETTING_BREDR; settings |= MGMT_SETTING_LINK_SECURITY; } @@ -413,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) settings |= MGMT_SETTING_PAIRABLE; - if (!(hdev->features[4] & LMP_NO_BREDR)) + if (lmp_bredr_capable(hdev)) settings |= MGMT_SETTING_BREDR; if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) From c383ddc481a1774702473b4bb0d2927aab3f2d5a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:47 -0300 Subject: [PATCH 010/109] Bluetooth: Use lmp_le_capable where applicable This patch replaces all LMP_LE bit checking by the helper macro lmp_le_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ++-- net/bluetooth/mgmt.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f9..498d55edcbc3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) * Features Notification */ } - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) events[7] |= 0x20; /* LE Meta-Event */ hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); @@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, break; } - if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) + if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) hci_set_le_support(hdev); done: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 990ec6affca5..0351bf27f2bb 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -391,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (enable_hs) settings |= MGMT_SETTING_HS; - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) settings |= MGMT_SETTING_LE; return settings; @@ -1205,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[4] & LMP_LE)) { + if (!lmp_le_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, MGMT_STATUS_NOT_SUPPORTED); goto unlock; From 9a1a1996d54a92cae2affa1de689cb04ebe7bce1 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:48 -0300 Subject: [PATCH 011/109] Bluetooth: Use lmp_ssp_capable where applicable This patch replaces all LMP_SIMPLE_PAIR bit checking by the helper macro lmp_ssp_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- net/bluetooth/mgmt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 498d55edcbc3..b120388678fd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -528,7 +528,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[7] & LMP_LSTO) events[6] |= 0x80; /* Link Supervision Timeout Changed */ - if (hdev->features[6] & LMP_SIMPLE_PAIR) { + if (lmp_ssp_capable(hdev)) { events[6] |= 0x01; /* IO Capability Request */ events[6] |= 0x02; /* IO Capability Response */ events[6] |= 0x04; /* User Confirmation Request */ diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0351bf27f2bb..a3329cbd3e4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -380,7 +380,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) settings |= MGMT_SETTING_DISCOVERABLE; settings |= MGMT_SETTING_PAIRABLE; - if (hdev->features[6] & LMP_SIMPLE_PAIR) + if (lmp_ssp_capable(hdev)) settings |= MGMT_SETTING_SSP; if (lmp_bredr_capable(hdev)) { @@ -1121,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, MGMT_STATUS_NOT_SUPPORTED); goto failed; @@ -2201,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, goto unlock; } - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, MGMT_STATUS_NOT_SUPPORTED); goto unlock; From 45db810fb71a94926c10f4dbbb5ca7913983f83b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:49 -0300 Subject: [PATCH 012/109] Bluetooth: Use lmp_esco_capable where applicable This patch replaces all LMP_ESCO bit checking by the helper macro lmp_esco_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b120388678fd..5722a388ada1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, hdev->esco_type |= (ESCO_HV3); } - if (hdev->features[3] & LMP_ESCO) + if (lmp_esco_capable(hdev)) hdev->esco_type |= (ESCO_EV3); if (hdev->features[4] & LMP_EV4) From 9f92ebf6c72de444801ab4a922965bd1f90834ae Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:50 -0300 Subject: [PATCH 013/109] Bluetooth: Use lmp_rswitch_capable where applicable This patch replaces all LMP_RSWITCH bit checking by the helper macro lmp_rswitch_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5722a388ada1..5c71c85c87a7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -623,7 +623,7 @@ static void hci_setup_link_policy(struct hci_dev *hdev) struct hci_cp_write_def_link_policy cp; u16 link_policy = 0; - if (hdev->features[0] & LMP_RSWITCH) + if (lmp_rswitch_capable(hdev)) link_policy |= HCI_LP_RSWITCH; if (hdev->features[0] & LMP_HOLD) link_policy |= HCI_LP_HOLD; From 6eded1004abb060fbdf69611abc560c717f2bb8b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:51 -0300 Subject: [PATCH 014/109] Bluetooth: Use lmp_sniff_capable where applicable This patch replaces all LMP_SNIFF bit checking by the helper macro lmp_sniff_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5c71c85c87a7..eb9024a8684c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -627,7 +627,7 @@ static void hci_setup_link_policy(struct hci_dev *hdev) link_policy |= HCI_LP_RSWITCH; if (hdev->features[0] & LMP_HOLD) link_policy |= HCI_LP_HOLD; - if (hdev->features[0] & LMP_SNIFF) + if (lmp_sniff_capable(hdev)) link_policy |= HCI_LP_SNIFF; if (hdev->features[1] & LMP_PARK) link_policy |= HCI_LP_PARK; From 999dcd10a88243ab304966a506b4975ce5f1e3bb Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:52 -0300 Subject: [PATCH 015/109] Bluetooth: Use lmp_sniffsubr_capable where applicable This patch replaces all LMP_SNIFF_SUBR bit checking by the helper macro lmp_sniffsubr_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index eb9024a8684c..060780c40ba1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[3] & LMP_RSSI_INQ) events[4] |= 0x02; /* Inquiry Result with RSSI */ - if (hdev->features[5] & LMP_SNIFF_SUBR) + if (lmp_sniffsubr_capable(hdev)) events[5] |= 0x20; /* Sniff Subrating */ if (hdev->features[5] & LMP_PAUSE_ENC) From c58e810eb0916f9197378435af72136fb7c97f43 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:53 -0300 Subject: [PATCH 016/109] Bluetooth: Use lmp_no_flush_capable where applicable This patch replaces all LMP_NO_FLUSH bit checking by the helper macro lmp_no_flush_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 060780c40ba1..2d8761b8b19c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -522,7 +522,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[6] & LMP_EXT_INQ) events[5] |= 0x40; /* Extended Inquiry Result */ - if (hdev->features[6] & LMP_NO_FLUSH) + if (lmp_no_flush_capable(hdev)) events[7] |= 0x01; /* Enhanced Flush Complete */ if (hdev->features[7] & LMP_LSTO) From 9e66463127ff7238020c3c4e7f84dfbc23e5c2b5 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 24 Jul 2012 16:06:15 +0300 Subject: [PATCH 017/109] Bluetooth: Make connect / disconnect cfm functions return void Return values are never used because callers hci_proto_connect_cfm and hci_proto_disconn_cfm return void. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 8 ++++---- net/bluetooth/l2cap_core.c | 6 ++---- net/bluetooth/sco.c | 7 ++----- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 03b8b6526400..41d943926d2c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -350,16 +350,16 @@ extern rwlock_t hci_cb_list_lock; /* ----- HCI interface to upper protocols ----- */ extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status); +extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); extern int l2cap_disconn_ind(struct hci_conn *hcon); -extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); +extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status); -extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); +extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); +extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); /* ----- Inquiry cache ----- */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 64d88a603f0a..8391e0575494 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5329,7 +5329,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return exact ? lm1 : lm2; } -int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) +void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) { struct l2cap_conn *conn; @@ -5342,7 +5342,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) } else l2cap_conn_del(hcon, bt_to_errno(status)); - return 0; } int l2cap_disconn_ind(struct hci_conn *hcon) @@ -5356,12 +5355,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon) return conn->disc_reason; } -int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) +void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); l2cap_conn_del(hcon, bt_to_errno(reason)); - return 0; } static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff7..0ef5a78a889f 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return lm; } -int sco_connect_cfm(struct hci_conn *hcon, __u8 status) +void sco_connect_cfm(struct hci_conn *hcon, __u8 status) { BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); if (!status) { @@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status) sco_conn_ready(conn); } else sco_conn_del(hcon, bt_to_errno(status)); - - return 0; } -int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) +void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); sco_conn_del(hcon, bt_to_errno(reason)); - return 0; } int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) From ee72d150ada90d33cc6e222fbdd7f980c16d974d Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 23 Jul 2012 18:19:04 -0300 Subject: [PATCH 018/109] Bluetooth: Remove locking in hci_user_passkey_request_evt This patch removes hdev locking in hci_user_passkey_request_evt since it is not needed. mgmt_user_passkey_request simply calls mgmt_event which does not require hdev locking at all. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2d8761b8b19c..0386e1e72275 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3252,12 +3252,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, BT_DBG("%s", hdev->name); - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); - - hci_dev_unlock(hdev); } static void hci_simple_pair_complete_evt(struct hci_dev *hdev, From 3064837289259843310b266a9422aca5f5b4b9c7 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Fri, 13 Jul 2012 18:17:54 +0530 Subject: [PATCH 019/109] Bluetooth: Move l2cap_chan_hold/put to l2cap_core.c Refactor the code in order to use the l2cap_chan_destroy() from l2cap_chan_put() under the refcnt protection. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Reviewed-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/l2cap.h | 16 ++-------------- net/bluetooth/l2cap_core.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index a7679f8913d2..a1eb6786ce54 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -671,20 +671,8 @@ enum { L2CAP_EV_RECV_FRAME, }; -static inline void l2cap_chan_hold(struct l2cap_chan *c) -{ - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - - atomic_inc(&c->refcnt); -} - -static inline void l2cap_chan_put(struct l2cap_chan *c) -{ - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); - - if (atomic_dec_and_test(&c->refcnt)) - kfree(c); -} +void l2cap_chan_hold(struct l2cap_chan *c); +void l2cap_chan_put(struct l2cap_chan *c); static inline void l2cap_chan_lock(struct l2cap_chan *chan) { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8391e0575494..79923d8bbe97 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -425,6 +425,21 @@ void l2cap_chan_destroy(struct l2cap_chan *chan) l2cap_chan_put(chan); } +void l2cap_chan_hold(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + atomic_inc(&c->refcnt); +} + +void l2cap_chan_put(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + if (atomic_dec_and_test(&c->refcnt)) + kfree(c); +} + void l2cap_chan_set_defaults(struct l2cap_chan *chan) { chan->fcs = L2CAP_FCS_CRC16; From 4af66c691f4e5c2db9bb00793669a548e9db1974 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Fri, 13 Jul 2012 18:17:55 +0530 Subject: [PATCH 020/109] Bluetooth: Free the l2cap channel list only when refcount is zero Move the l2cap channel list chan->global_l under the refcnt protection and free it based on the refcnt. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Reviewed-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/a2mp.c | 2 +- net/bluetooth/l2cap_core.c | 8 +++++--- net/bluetooth/l2cap_sock.c | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index a1eb6786ce54..d206296137e2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -759,7 +759,6 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); struct l2cap_chan *l2cap_chan_create(void); void l2cap_chan_close(struct l2cap_chan *chan, int reason); -void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst, u8 dst_type); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 79af661a58dd..0760d1fed6f0 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -416,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) static void a2mp_chan_close_cb(struct l2cap_chan *chan) { - l2cap_chan_destroy(chan); + l2cap_chan_put(chan); } static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 79923d8bbe97..9f8b29ef5b68 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -416,13 +416,15 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -void l2cap_chan_destroy(struct l2cap_chan *chan) +static void l2cap_chan_destroy(struct l2cap_chan *chan) { + BT_DBG("chan %p", chan); + write_lock(&chan_list_lock); list_del(&chan->global_l); write_unlock(&chan_list_lock); - l2cap_chan_put(chan); + kfree(chan); } void l2cap_chan_hold(struct l2cap_chan *c) @@ -437,7 +439,7 @@ void l2cap_chan_put(struct l2cap_chan *c) BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); if (atomic_dec_and_test(&c->refcnt)) - kfree(c); + l2cap_chan_destroy(c); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427e..79350d10087c 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -823,7 +823,7 @@ static void l2cap_sock_kill(struct sock *sk) /* Kill poor orphan */ - l2cap_chan_destroy(l2cap_pi(sk)->chan); + l2cap_chan_put(l2cap_pi(sk)->chan); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); } From 256a06c8a85df676e80263af349daad1283e529e Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:26:32 +0900 Subject: [PATCH 021/109] Bluetooth: /proc/net/ entries for bluetooth protocols lsof command can tell the type of socket processes are using. Internal lsof uses inode numbers on socket fs to resolve the type of sockets. Files under /proc/net/, such as tcp, udp, unix, etc provides such inode information. Unfortunately bluetooth related protocols don't provide such inode information. This patch series introduces /proc/net files for the protocols. This patch against af_bluetooth.c provides facility to the implementation of protocols. This patch extends bt_sock_list and introduces two exported function bt_procfs_init, bt_procfs_cleanup. The type bt_sock_list is already used in some of implementation of protocols. bt_procfs_init prepare seq_operations which converts protocol own bt_sock_list data to protocol own proc entry when the entry is accessed. What I, lsof user, need is just inode number of bluetooth socket. However, people may want more information. The bt_procfs_init takes a function pointer for customizing the show handler of seq_operations. In v4 patch, __acquires and __releases attributes are added to suppress sparse warning. Suggested by Andrei Emeltchenko. In v5 patch, linux/proc_fs.h is included to use PDE. Build error is reported by Fengguang Wu. Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- include/net/bluetooth/bluetooth.h | 10 +++ net/bluetooth/af_bluetooth.c | 141 ++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 565d4bee1e49..ede036977ae8 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -27,6 +27,7 @@ #include #include +#include #ifndef AF_BLUETOOTH #define AF_BLUETOOTH 31 @@ -202,6 +203,10 @@ enum { struct bt_sock_list { struct hlist_head head; rwlock_t lock; +#ifdef CONFIG_PROC_FS + struct file_operations fops; + int (* custom_seq_show)(struct seq_file *, void *); +#endif }; int bt_sock_register(int proto, const struct net_proto_family *ops); @@ -292,6 +297,11 @@ extern void hci_sock_cleanup(void); extern int bt_sysfs_init(void); extern void bt_sysfs_cleanup(void); +extern int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)); +extern void bt_procfs_cleanup(struct net *net, const char *name); + extern struct dentry *bt_debugfs; int l2cap_init(void); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f7db5792ec64..58f9762b339a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -28,6 +28,7 @@ #include #include +#include #define VERSION "2.16" @@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) } EXPORT_SYMBOL(bt_sock_wait_state); +#ifdef CONFIG_PROC_FS +struct bt_seq_state { + struct bt_sock_list *l; +}; + +static void *bt_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_lock(&l->lock); + return seq_hlist_start_head(&l->head, *pos); +} + +static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + return seq_hlist_next(v, &l->head, pos); +} + +static void bt_seq_stop(struct seq_file *seq, void *v) + __releases(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_unlock(&l->lock); +} + +static int bt_seq_show(struct seq_file *seq, void *v) +{ + struct sock *sk; + struct bt_sock *bt; + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + bdaddr_t src_baswapped, dst_baswapped; + + if (v == SEQ_START_TOKEN) { + seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } else { + sk = sk_entry(v); + bt = bt_sk(sk); + baswap(&src_baswapped, &bt->src); + baswap(&dst_baswapped, &bt->dst); + + seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", + sk, + atomic_read(&sk->sk_refcnt), + sk_rmem_alloc_get(sk), + sk_wmem_alloc_get(sk), + sock_i_uid(sk), + sock_i_ino(sk), + &src_baswapped, + &dst_baswapped, + bt->parent? sock_i_ino(bt->parent): 0LU); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } + return 0; +} + +static struct seq_operations bt_seq_ops = { + .start = bt_seq_start, + .next = bt_seq_next, + .stop = bt_seq_stop, + .show = bt_seq_show, +}; + +static int bt_seq_open(struct inode *inode, struct file *file) +{ + struct bt_sock_list *sk_list; + struct bt_seq_state *s; + + sk_list = PDE(inode)->data; + s = __seq_open_private(file, &bt_seq_ops, + sizeof(struct bt_seq_state)); + if (s == NULL) + return -ENOMEM; + + s->l = sk_list; + return 0; +} + +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + struct proc_dir_entry * pde; + + sk_list->custom_seq_show = seq_show; + + sk_list->fops.owner = module; + sk_list->fops.open = bt_seq_open; + sk_list->fops.read = seq_read; + sk_list->fops.llseek = seq_lseek; + sk_list->fops.release = seq_release_private; + + pde = proc_net_fops_create(net, name, 0, &sk_list->fops); + if (pde == NULL) + return -ENOMEM; + + pde->data = sk_list; + + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ + proc_net_remove(net, name); +} +#else +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ +} +#endif +EXPORT_SYMBOL(bt_procfs_init); +EXPORT_SYMBOL(bt_procfs_cleanup); + static struct net_proto_family bt_sock_family_ops = { .owner = THIS_MODULE, .family = PF_BLUETOOTH, From 77cf5585a31fdad48c16ddae9be154f5afe22c1c Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:27:35 +0900 Subject: [PATCH 022/109] Bluetooth: Added /proc/net/bnep via bt_procfs_init() Added /proc/net/bnep via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/bnep/sock.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0b..5b6cc0bf4dec 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -29,6 +29,10 @@ #include "bnep.h" +static struct bt_sock_list bnep_sk_list = { + .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock) +}; + static int bnep_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&bnep_sk_list, sk); + sock_orphan(sk); sock_put(sk); return 0; @@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&bnep_sk_list, sk); return 0; } @@ -222,19 +229,30 @@ int __init bnep_sock_init(void) return err; err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register BNEP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create BNEP proc file"); + bt_sock_unregister(BTPROTO_BNEP); + goto error; + } + + BT_INFO("BNEP socket layer initialized"); return 0; error: - BT_ERR("Can't register BNEP socket"); proto_unregister(&bnep_proto); return err; } void __exit bnep_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "bnep"); if (bt_sock_unregister(BTPROTO_BNEP) < 0) BT_ERR("Can't unregister BNEP socket"); From 8c8de589cedd375934d96e073d2b9077a00f10c2 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:28:07 +0900 Subject: [PATCH 023/109] Bluetooth: Added /proc/net/cmtp via bt_procfs_init() Added /proc/net/cmtp via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/cmtp/sock.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d14571..d5cacef52748 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -42,6 +42,10 @@ #include "cmtp.h" +static struct bt_sock_list cmtp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock) +}; + static int cmtp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&cmtp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&cmtp_sk_list, sk); + return 0; } @@ -232,19 +240,30 @@ int cmtp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register CMTP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create CMTP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("CMTP socket layer initialized"); return 0; error: - BT_ERR("Can't register CMTP socket"); proto_unregister(&cmtp_proto); return err; } void cmtp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "cmtp"); if (bt_sock_unregister(BTPROTO_CMTP) < 0) BT_ERR("Can't unregister CMTP socket"); From f7c8663789038c4bc71b81e3c858a35c999347a8 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:28:36 +0900 Subject: [PATCH 024/109] Bluetooth: Added /proc/net/hci via bt_procfs_init() Added /proc/net/hci via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_sock.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d79..7c3d6c7c6ddb 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1100,21 +1100,30 @@ int __init hci_sock_init(void) return err; err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("HCI socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HCI proc file"); + bt_sock_unregister(BTPROTO_HCI); + goto error; + } BT_INFO("HCI socket layer initialized"); return 0; error: - BT_ERR("HCI socket registration failed"); proto_unregister(&hci_sk_proto); return err; } void hci_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "hci"); if (bt_sock_unregister(BTPROTO_HCI) < 0) BT_ERR("HCI socket unregistration failed"); From 5c6ad8eee0a8c5fb4ba8b741008490da9eb66af6 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:00 +0900 Subject: [PATCH 025/109] Bluetooth: Added /proc/net/hidp via bt_procfs_init() Added /proc/net/hidp via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/hidp/sock.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a36..eca3889371c4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -25,6 +25,10 @@ #include "hidp.h" +static struct bt_sock_list hidp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) +}; + static int hidp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&hidp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&hidp_sk_list, sk); + return 0; } @@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register HIDP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HIDP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("HIDP socket layer initialized"); return 0; @@ -284,6 +303,7 @@ error: void __exit hidp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "hidp"); if (bt_sock_unregister(BTPROTO_HIDP) < 0) BT_ERR("Can't unregister HIDP socket"); From 5b28d95c13e876037d2c692e61862bb3e98249af Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:25 +0900 Subject: [PATCH 026/109] Bluetooth: Added /proc/net/l2cap via bt_procfs_init() Added /proc/net/l2cap via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_sock.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 79350d10087c..13f6a9816feb 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -34,6 +34,10 @@ #include #include +static struct bt_sock_list l2cap_sk_list = { + .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) +}; + static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); @@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&l2cap_sk_list, sk); + err = l2cap_sock_shutdown(sock, 2); sock_orphan(sk); @@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, return -ENOMEM; l2cap_sock_init(sk, NULL); + bt_sock_link(&l2cap_sk_list, sk); return 0; } @@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void) return err; err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("L2CAP socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create L2CAP proc file"); + bt_sock_unregister(BTPROTO_L2CAP); + goto error; + } BT_INFO("L2CAP socket layer initialized"); return 0; error: - BT_ERR("L2CAP socket registration failed"); proto_unregister(&l2cap_proto); return err; } void l2cap_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "l2cap"); if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); From c6f5df16a2710e64090078dfbaa86c54a27c0874 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:49 +0900 Subject: [PATCH 027/109] Bluetooth: Added /proc/net/rfcomm via bt_procfs_init() Added /proc/net/rfcomm via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/rfcomm/sock.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c05..260821a2d6e7 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void) return err; err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("RFCOMM socket layer registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create RFCOMM proc file"); + bt_sock_unregister(BTPROTO_RFCOMM); + goto error; + } if (bt_debugfs) { rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, @@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void) return 0; error: - BT_ERR("RFCOMM socket layer registration failed"); proto_unregister(&rfcomm_proto); return err; } void __exit rfcomm_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "rfcomm"); + debugfs_remove(rfcomm_sock_debugfs); if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) From de9b9212c7fd3e87608194f1c73fc06cd6cc7dfb Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:30:12 +0900 Subject: [PATCH 028/109] Bluetooth: Added /proc/net/sco via bt_procfs_init() Added /proc/net/sco via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/sco.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 0ef5a78a889f..caa109df6452 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1023,6 +1023,13 @@ int __init sco_init(void) goto error; } + err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create SCO proc file"); + bt_sock_unregister(BTPROTO_SCO); + goto error; + } + if (bt_debugfs) { sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, NULL, &sco_debugfs_fops); @@ -1041,6 +1048,8 @@ error: void __exit sco_exit(void) { + bt_procfs_cleanup(&init_net, "sco"); + debugfs_remove(sco_debugfs); if (bt_sock_unregister(BTPROTO_SCO) < 0) From 9357cc60789cfdcbbeeff85d9c423a91d621ae1f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:31 +0530 Subject: [PATCH 029/109] Bluetooth: Use devm_kzalloc in bcm203x.c file. devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/bcm203x.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 37ae175162f3..364f82b34d03 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate memory for data structure"); return -ENOMEM; @@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id data->urb = usb_alloc_urb(0, GFP_KERNEL); if (!data->urb) { BT_ERR("Can't allocate URB"); - kfree(data); return -ENOMEM; } if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { BT_ERR("Mini driver request failed"); usb_free_urb(data->urb); - kfree(data); return -EIO; } @@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id BT_ERR("Can't allocate memory for mini driver"); release_firmware(firmware); usb_free_urb(data->urb); - kfree(data); return -ENOMEM; } @@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id BT_ERR("Firmware request failed"); usb_free_urb(data->urb); kfree(data->buffer); - kfree(data); return -EIO; } @@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); usb_free_urb(data->urb); kfree(data->buffer); - kfree(data); return -ENOMEM; } @@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf) usb_free_urb(data->urb); kfree(data->fw_data); kfree(data->buffer); - kfree(data); } static struct usb_driver bcm203x_driver = { From 0213cd8d5ed9cee1d7ffd95566319af1bb36a604 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:32 +0530 Subject: [PATCH 030/109] Bluetooth: Use devm_kzalloc in bfusb.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/bfusb.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 32e825144fe9..995aee9cba22 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i } /* Initialize control structure and load firmware */ - data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate memory for control structure"); goto done; @@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { BT_ERR("Firmware request failed"); - goto error; + goto done; } BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); @@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can't allocate HCI device"); - goto error; + goto done; } data->hdev = hdev; @@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); - goto error; + goto done; } usb_set_intfdata(intf, data); @@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i release: release_firmware(firmware); -error: - kfree(data); - done: return -EIO; } @@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(data); } static struct usb_driver bfusb_driver = { From 1a31c602c3f6de9383eaae28e25859b6304fc3c2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:33 +0530 Subject: [PATCH 031/109] Bluetooth: Use devm_kzalloc in bluecard_cs.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/bluecard_cs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 66c3a6770c41..0c0838d9b56c 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link) bluecard_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link) static void bluecard_detach(struct pcmcia_device *link) { - bluecard_info_t *info = link->priv; - bluecard_release(link); - kfree(info); } From 704687ce17bf00f557f300e5bcf6c3bdd1f78226 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:34 +0530 Subject: [PATCH 032/109] Bluetooth: Use devm_kzalloc in bpa10x.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/bpa10x.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 29caaed2d715..2fe4a8031348 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * init_usb_anchor(&data->rx_anchor); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); @@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf) hci_free_dev(data->hdev); kfree_skb(data->rx_skb[0]); kfree_skb(data->rx_skb[1]); - kfree(data); } static struct usb_driver bpa10x_driver = { From 4f61cb184fd5d16d591303aacf8dd1e623d2137d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:35 +0530 Subject: [PATCH 033/109] Bluetooth: Use devm_kzalloc in bt3c_cs.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/bt3c_cs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 8925b6d672a6..7ffd3f407144 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link) bt3c_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link) static void bt3c_detach(struct pcmcia_device *link) { - bt3c_info_t *info = link->priv; - bt3c_release(link); - kfree(info); } static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data) From eb17ea3b1ce6302e7416c4ba58754fd70ee3ab62 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:36 +0530 Subject: [PATCH 034/109] Bluetooth: Use devm_kzalloc in btmrvl_sdio.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btmrvl_sdio.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 6a9e9717d3ab..03b3acba6143 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d", id->vendor, id->device, id->class, func->num); - card = kzalloc(sizeof(*card), GFP_KERNEL); - if (!card) { - ret = -ENOMEM; - goto done; - } + card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; card->func = func; @@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, if (btmrvl_sdio_register_dev(card) < 0) { BT_ERR("Failed to register BT device!"); - ret = -ENODEV; - goto free_card; + return -ENODEV; } /* Disable the interrupts on the card */ @@ -1023,9 +1020,6 @@ disable_host_int: btmrvl_sdio_disable_host_int(card); unreg_dev: btmrvl_sdio_unregister_dev(card); -free_card: - kfree(card); -done: return ret; } @@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func) BT_DBG("unregester dev"); btmrvl_sdio_unregister_dev(card); btmrvl_remove_card(card->priv); - kfree(card); } } } From 3a382772b51bbf55b23701746102bd75b9fe883f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:37 +0530 Subject: [PATCH 035/109] Bluetooth: Use devm_kzalloc in btsdio.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btsdio.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index e10ea0347051..4a9909713874 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func, tuple = tuple->next; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func, skb_queue_head_init(&data->txq); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_SDIO; hci_set_drvdata(hdev, data); @@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func, err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(data); } static struct sdio_driver btsdio_driver = { From fdefa118ebbcadad4adbaaab067be06a96a48e15 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:38 +0530 Subject: [PATCH 036/109] Bluetooth: Use devm_kzalloc in btuart_cs.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btuart_cs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 21e803a6a281..2f510a87b28f 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link) btuart_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link) static void btuart_detach(struct pcmcia_device *link) { - btuart_info_t *info = link->priv; - btuart_release(link); - kfree(info); } static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data) From 98921dbd00c4e2e4bdd56423cb5edf98d57b45f7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:39 +0530 Subject: [PATCH 037/109] Bluetooth: Use devm_kzalloc in btusb.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e27221411036..f637c2550016 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf, return -ENODEV; } - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf, } } - if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { - kfree(data); + if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) return -ENODEV; - } data->cmdreq_type = USB_TYPE_CLASS; @@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->deferred); hdev = hci_alloc_dev(); - if (!hdev) { - kfree(data); + if (!hdev) return -ENOMEM; - } hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); @@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf, data->isoc, data); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } } @@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf, err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); - kfree(data); return err; } @@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf) usb_driver_release_interface(&btusb_driver, data->isoc); hci_free_dev(hdev); - kfree(data); } #ifdef CONFIG_PM From 4f8d81584964730b08753da34f1e3fb7981cf742 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:40 +0530 Subject: [PATCH 038/109] Bluetooth: Use devm_kzalloc in btwilink.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btwilink.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 88694697f34f..4ad7b35cfc0e 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c @@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev) struct hci_dev *hdev; int err; - hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL); + hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL); if (!hst) return -ENOMEM; /* Expose "hciX" device to user space */ hdev = hci_alloc_dev(); - if (!hdev) { - kfree(hst); + if (!hdev) return -ENOMEM; - } BT_DBG("hdev %p", hdev); @@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev) err = hci_register_dev(hdev); if (err < 0) { BT_ERR("Can't register HCI device error %d", err); - kfree(hst); hci_free_dev(hdev); return err; } @@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev) hci_unregister_dev(hdev); hci_free_dev(hdev); - kfree(hst); dev_set_drvdata(&pdev->dev, NULL); return 0; From cd7cf78e9bef269ed482ad8ab572f197ae89af3c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 27 Jul 2012 12:38:41 +0530 Subject: [PATCH 039/109] Bluetooth: Use devm_kzalloc in dtl1_cs.c file devm_kzalloc() eliminates the need to free memory explicitly thereby saving some cleanup code. Signed-off-by: Sachin Kamat Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/dtl1_cs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 97a7784db4a2..036cb366fe6e 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link) dtl1_info_t *info; /* Create new info device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link) dtl1_close(info); pcmcia_disable_device(link); - kfree(info); } static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data) From 230fd16a2333fef9c012b054a127c7d157f7a7af Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:10 -0300 Subject: [PATCH 040/109] Bluetooth: Trivial refactoring This patch replaces the unlock-and-return statements by the goto statement. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0386e1e72275..e89d7f24136b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3364,8 +3364,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { BT_ERR("No memory for new connection"); - hci_dev_unlock(hdev); - return; + goto unlock; } conn->dst_type = ev->bdaddr_type; From b9b343d25484bbceaee454ab422daafb1c5eda96 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:11 -0300 Subject: [PATCH 041/109] Bluetooth: Fix hci_le_conn_complete_evt We need to check the 'Role' parameter from the LE Connection Complete Event in order to properly set 'out' and 'link_mode' fields from hci_conn structure. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_event.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 7f1955662455..23cf413e2acf 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1304,6 +1304,8 @@ struct hci_ev_num_comp_blocks { } __packed; /* Low energy meta events */ +#define LE_CONN_ROLE_MASTER 0x00 + #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e89d7f24136b..8b13cccd50cd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3368,6 +3368,11 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } conn->dst_type = ev->bdaddr_type; + + if (ev->role == LE_CONN_ROLE_MASTER) { + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + } } if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) From 847012c5e04544aef485dfec29c1c07dc90615a4 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:12 -0300 Subject: [PATCH 042/109] Bluetooth: Remove unneeded code This patch removes some unneeded code from hci_cs_le_create_conn. If the hci_conn is not found, it means this LE connection attempt was triggered by a thrid-party tool (e.g. hcitool). We should not create this new hci_conn in LE Create Connection command status event since it is already properly handled in LE Connection Complete event. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8b13cccd50cd..27064beda10d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1638,16 +1638,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) hci_proto_connect_cfm(conn, status); hci_conn_del(conn); } - } else { - if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); - if (conn) { - conn->dst_type = cp->peer_addr_type; - conn->out = true; - } else { - BT_ERR("No memory for new connection"); - } - } } hci_dev_unlock(hdev); From f00a06ac14becc3d78fecdf2513cc23ee267a96b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:13 -0300 Subject: [PATCH 043/109] Bluetooth: Refactor hci_cs_le_create_conn This patch does some code refactoring in hci_cs_le_create_conn function. The hci_conn object is only needed in case of failure, therefore hdev locking and hci_conn lookup were moved to if-statement scope. Also, the conn->state check was removed since we should always close the connection if it fails. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 27064beda10d..c0aa9f436998 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1623,24 +1623,26 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) if (!cp) return; - hci_dev_lock(hdev); - - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); - - BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), - conn); - if (status) { - if (conn && conn->state == BT_CONNECT) { - conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, - conn->dst_type, status); - hci_proto_connect_cfm(conn, status); - hci_conn_del(conn); - } - } + hci_dev_lock(hdev); - hci_dev_unlock(hdev); + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + if (!conn) { + hci_dev_unlock(hdev); + return; + } + + BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), + conn); + + conn->state = BT_CLOSED; + mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, + conn->dst_type, status); + hci_proto_connect_cfm(conn, status); + hci_conn_del(conn); + + hci_dev_unlock(hdev); + } } static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) From 0c95ab78be36e56ca69e36bc679f9dfd3d25f31e Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:14 -0300 Subject: [PATCH 044/109] Bluetooth: Find hci_conn by BT_CONNECT state This patch changes hci_cs_le_create_conn to perform hci_conn lookup by state instead of bdaddr. Since we can have only one LE connection in BT_CONNECT state, we can perform LE hci_conn lookup by state. This way, we don't rely on hci_sent_cmd_data helper to find the hci_conn object. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c0aa9f436998..8dc1f0fbe9c1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1614,29 +1614,24 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) { - struct hci_cp_le_create_conn *cp; struct hci_conn *conn; BT_DBG("%s status 0x%2.2x", hdev->name, status); - cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); - if (!cp) - return; - if (status) { hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); if (!conn) { hci_dev_unlock(hdev); return; } - BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), + BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), conn); conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, + mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, status); hci_proto_connect_cfm(conn, status); hci_conn_del(conn); From b47a09b33a4612ace2958996ce6e0134be23d043 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:15 -0300 Subject: [PATCH 045/109] Bluetooth: Lookup hci_conn in hci_le_conn_complete_evt This patch does a trivial code refactoring in hci_conn lookup in hci_le_conn_complete_evt. It performs the hci_conn lookup at the begining of the function since it is used by both flows (error and success). Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8dc1f0fbe9c1..92522b470f6b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3333,8 +3333,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (ev->status) { - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); if (!conn) goto unlock; @@ -3346,7 +3347,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) goto unlock; } - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); if (!conn) { conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { From cd17decbd9af41c9548bb108ccf156519f8253ec Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:16 -0300 Subject: [PATCH 046/109] Bluetooth: Refactor in hci_le_conn_complete_evt This patch moves the hci_conn check to begining of hci_le_conn_ complete_evt in order to improve code's readability and better error handling. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 92522b470f6b..32e21ad36a68 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3334,19 +3334,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - - if (ev->status) { - if (!conn) - goto unlock; - - mgmt_connect_failed(hdev, &conn->dst, conn->type, - conn->dst_type, ev->status); - hci_proto_connect_cfm(conn, ev->status); - conn->state = BT_CLOSED; - hci_conn_del(conn); - goto unlock; - } - if (!conn) { conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { @@ -3362,6 +3349,15 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } } + if (ev->status) { + mgmt_connect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, ev->status); + hci_proto_connect_cfm(conn, ev->status); + conn->state = BT_CLOSED; + hci_conn_del(conn); + goto unlock; + } + if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) mgmt_device_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type, 0, NULL, 0, NULL); From 858a455ba86b0b515d34972e68095ecd912c08cc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 24 Jul 2012 17:35:57 +0200 Subject: [PATCH 047/109] brcmsmac: use ieee80211_channel_to_frequency Instead of hard-coding almost the same functionality, just use ieee80211_channel_to_frequency() directly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/main.c | 13 ++++--------- drivers/net/wireless/brcm80211/include/brcmu_wifi.h | 5 ----- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 03ca65324845..75086b37c817 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -7512,15 +7512,10 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); - if (channel > 14) { - rx_status->band = IEEE80211_BAND_5GHZ; - rx_status->freq = ieee80211_ofdm_chan_to_freq( - WF_CHAN_FACTOR_5_G/2, channel); - - } else { - rx_status->band = IEEE80211_BAND_2GHZ; - rx_status->freq = ieee80211_dsss_chan_to_freq(channel); - } + rx_status->band = + channel > 14 ? IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + rx_status->freq = + ieee80211_channel_to_frequency(channel, rx_status->band); rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh); diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index f10d30274c23..c11a290a1edf 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h @@ -67,11 +67,6 @@ #define WL_CHANSPEC_BAND_2G 0x2000 #define INVCHANSPEC 255 -/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */ -#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ -#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ -#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ - #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) From fa0f2b38607e19a77096173a8d592cff6f10b32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 24 Jul 2012 19:18:19 +0200 Subject: [PATCH 048/109] b43: N-PHY: update workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 46 +++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b92bb9c92ad1..40bb63d4c39e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1916,7 +1916,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) rx2tx_delays[6] = 1; rx2tx_events[7] = 0x1F; } - b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, + b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays, ARRAY_SIZE(rx2tx_events)); } @@ -1926,8 +1926,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700); - b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D); - b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D); + if (!dev->phy.is_40mhz) { + b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D); + b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D); + } else { + b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D); + b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D); + } b43_nphy_gain_ctl_workarounds(dev); @@ -1963,13 +1968,14 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32); if (dev->phy.rev == 4 && - b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC, 0x70); b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC, 0x70); } + /* Dropped probably-always-true condition */ b43_phy_write(dev, 0x224, 0x03eb); b43_phy_write(dev, 0x225, 0x03eb); b43_phy_write(dev, 0x226, 0x0341); @@ -1982,6 +1988,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) b43_phy_write(dev, 0x22d, 0x042b); b43_phy_write(dev, 0x22e, 0x0381); b43_phy_write(dev, 0x22f, 0x0381); + + if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK) + ; /* TODO: 0x0080000000000000 HF */ } static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) @@ -1996,6 +2005,12 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; + if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD || + dev->dev->board_type == 0x8B) { + delays1[0] = 0x1; + delays1[5] = 0x14; + } + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && nphy->band5g_pwrgain) { b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); @@ -2007,8 +2022,10 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A); b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A); - b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); + if (dev->phy.rev < 3) { + b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); + b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); + } if (dev->phy.rev < 2) { b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000); @@ -2024,11 +2041,6 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); - if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD && - dev->dev->board_type == 0x8B) { - delays1[0] = 0x1; - delays1[5] = 0x14; - } b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); @@ -2055,11 +2067,13 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); - b43_phy_mask(dev, B43_NPHY_PIL_DW1, - ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); - b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); + if (dev->phy.rev < 3) { + b43_phy_mask(dev, B43_NPHY_PIL_DW1, + ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); + } if (dev->phy.rev == 2) b43_phy_set(dev, B43_NPHY_FINERX2_CGC, From d11d354b7b02aac09a20a8157bf990670f169f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 24 Jul 2012 19:18:20 +0200 Subject: [PATCH 049/109] b43: N-PHY: add PHY rev7+ workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 328 ++++++++++++++++++++++++++++++- 1 file changed, 326 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 40bb63d4c39e..e49d847c59f8 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1860,12 +1860,334 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev) { - if (dev->phy.rev >= 3) + if (dev->phy.rev >= 7) + ; /* TODO */ + else if (dev->phy.rev >= 3) b43_nphy_gain_ctl_workarounds_rev3plus(dev); else b43_nphy_gain_ctl_workarounds_rev1_2(dev); } +/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ +static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset) +{ + if (!offset) + offset = (dev->phy.is_40mhz) ? 0x159 : 0x154; + return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7; +} + +static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) +{ + struct ssb_sprom *sprom = dev->dev->bus_sprom; + struct b43_phy *phy = &dev->phy; + + u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, + 0x1F }; + u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + + u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; + u8 ntab7_138_146[] = { 0x11, 0x11 }; + u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; + + u16 lpf_20, lpf_40, lpf_11b; + u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; + u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40; + bool rccal_ovrd = false; + + u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n; + u16 bias, conv, filt; + + u32 tmp32; + u8 core; + + if (phy->rev == 7) { + b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); + b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); + } + if (phy->rev <= 8) { + b43_phy_write(dev, 0x23F, 0x1B0); + b43_phy_write(dev, 0x240, 0x1B0); + } + if (phy->rev >= 8) + b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); + + b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); + b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2); + tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); + tmp32 &= 0xffffff; + b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e); + + if (b43_nphy_ipa(dev)) + b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, + rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); + + b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000); + b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000); + + lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); + lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); + lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152); + if (b43_nphy_ipa(dev)) { + if ((phy->radio_rev == 5 && phy->is_40mhz) || + phy->radio_rev == 7 || phy->radio_rev == 8) { + bcap_val = b43_radio_read(dev, 0x16b); + scap_val = b43_radio_read(dev, 0x16a); + scap_val_11b = scap_val; + bcap_val_11b = bcap_val; + if (phy->radio_rev == 5 && phy->is_40mhz) { + scap_val_11n_20 = scap_val; + bcap_val_11n_20 = bcap_val; + scap_val_11n_40 = bcap_val_11n_40 = 0xc; + rccal_ovrd = true; + } else { /* Rev 7/8 */ + lpf_20 = 4; + lpf_11b = 1; + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + scap_val_11n_20 = 0xc; + bcap_val_11n_20 = 0xc; + scap_val_11n_40 = 0xa; + bcap_val_11n_40 = 0xa; + } else { + scap_val_11n_20 = 0x14; + bcap_val_11n_20 = 0x14; + scap_val_11n_40 = 0xf; + bcap_val_11n_40 = 0xf; + } + rccal_ovrd = true; + } + } + } else { + if (phy->radio_rev == 5) { + lpf_20 = 1; + lpf_40 = 3; + bcap_val = b43_radio_read(dev, 0x16b); + scap_val = b43_radio_read(dev, 0x16a); + scap_val_11b = scap_val; + bcap_val_11b = bcap_val; + scap_val_11n_20 = 0x11; + scap_val_11n_40 = 0x11; + bcap_val_11n_20 = 0x13; + bcap_val_11n_40 = 0x13; + rccal_ovrd = true; + } + } + if (rccal_ovrd) { + rx2tx_lut_20_11b = (bcap_val_11b << 8) | + (scap_val_11b << 3) | + lpf_11b; + rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | + (scap_val_11n_20 << 3) | + lpf_20; + rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | + (scap_val_11n_40 << 3) | + lpf_40; + for (core = 0; core < 2; core++) { + b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), + rx2tx_lut_20_11b); + b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), + rx2tx_lut_20_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), + rx2tx_lut_20_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), + rx2tx_lut_40_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), + rx2tx_lut_40_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), + rx2tx_lut_40_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), + rx2tx_lut_40_11n); + b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), + rx2tx_lut_40_11n); + } + /* b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, 0, 2); */ + } + b43_phy_write(dev, 0x32F, 0x3); + if (phy->radio_rev == 4 || phy->radio_rev == 6) + ; /* b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, 0, 0); */ + + if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) { + if (sprom->revision && + sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) { + b43_radio_write(dev, 0x5, 0x05); + b43_radio_write(dev, 0x6, 0x30); + b43_radio_write(dev, 0x7, 0x00); + b43_radio_set(dev, 0x4f, 0x1); + b43_radio_set(dev, 0xd4, 0x1); + bias = 0x1f; + conv = 0x6f; + filt = 0xaa; + } else { + bias = 0x2b; + conv = 0x7f; + filt = 0xee; + } + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + for (core = 0; core < 2; core++) { + if (core == 0) { + b43_radio_write(dev, 0x5F, bias); + b43_radio_write(dev, 0x64, conv); + b43_radio_write(dev, 0x66, filt); + } else { + b43_radio_write(dev, 0xE8, bias); + b43_radio_write(dev, 0xE9, conv); + b43_radio_write(dev, 0xEB, filt); + } + } + } + } + + if (b43_nphy_ipa(dev)) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (phy->radio_rev == 3 || phy->radio_rev == 4 || + phy->radio_rev == 6) { + for (core = 0; core < 2; core++) { + if (core == 0) + b43_radio_write(dev, 0x51, + 0x7f); + else + b43_radio_write(dev, 0xd6, + 0x7f); + } + } + if (phy->radio_rev == 3) { + for (core = 0; core < 2; core++) { + if (core == 0) { + b43_radio_write(dev, 0x64, + 0x13); + b43_radio_write(dev, 0x5F, + 0x1F); + b43_radio_write(dev, 0x66, + 0xEE); + b43_radio_write(dev, 0x59, + 0x8A); + b43_radio_write(dev, 0x80, + 0x3E); + } else { + b43_radio_write(dev, 0x69, + 0x13); + b43_radio_write(dev, 0xE8, + 0x1F); + b43_radio_write(dev, 0xEB, + 0xEE); + b43_radio_write(dev, 0xDE, + 0x8A); + b43_radio_write(dev, 0x105, + 0x3E); + } + } + } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { + if (!phy->is_40mhz) { + b43_radio_write(dev, 0x5F, 0x14); + b43_radio_write(dev, 0xE8, 0x12); + } else { + b43_radio_write(dev, 0x5F, 0x16); + b43_radio_write(dev, 0xE8, 0x16); + } + } + } else { + u16 freq = phy->channel_freq; + if ((freq >= 5180 && freq <= 5230) || + (freq >= 5745 && freq <= 5805)) { + b43_radio_write(dev, 0x7D, 0xFF); + b43_radio_write(dev, 0xFE, 0xFF); + } + } + } else { + if (phy->radio_rev != 5) { + for (core = 0; core < 2; core++) { + if (core == 0) { + b43_radio_write(dev, 0x5c, 0x61); + b43_radio_write(dev, 0x51, 0x70); + } else { + b43_radio_write(dev, 0xe1, 0x61); + b43_radio_write(dev, 0xd6, 0x70); + } + } + } + } + + if (phy->radio_rev == 4) { + b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); + b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); + for (core = 0; core < 2; core++) { + if (core == 0) { + b43_radio_write(dev, 0x1a1, 0x00); + b43_radio_write(dev, 0x1a2, 0x3f); + b43_radio_write(dev, 0x1a6, 0x3f); + } else { + b43_radio_write(dev, 0x1a7, 0x00); + b43_radio_write(dev, 0x1ab, 0x3f); + b43_radio_write(dev, 0x1ac, 0x3f); + } + } + } else { + b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4); + b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4); + + b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); + b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); + b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); + b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); + + b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); + b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4); + } + + b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); + + b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146); + b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146); + b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); + b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); + + if (!phy->is_40mhz) { + b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D); + b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D); + } else { + b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D); + b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D); + } + + b43_nphy_gain_ctl_workarounds(dev); + + /* TODO + b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, + aux_adc_vmid_rev7_core0); + b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, + aux_adc_vmid_rev7_core1); + b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4, + aux_adc_gain_rev7); + b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4, + aux_adc_gain_rev7); + */ +} + static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; @@ -2097,7 +2419,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_phy_set(dev, B43_NPHY_IQFLIP, B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); - if (dev->phy.rev >= 3) + if (dev->phy.rev >= 7) + b43_nphy_workarounds_rev7plus(dev); + else if (dev->phy.rev >= 3) b43_nphy_workarounds_rev3plus(dev); else b43_nphy_workarounds_rev1_2(dev); From 95a96e08967fed6e64e53b2d6a5e153a4d605e11 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 24 Jul 2012 21:16:42 +0200 Subject: [PATCH 050/109] p54pci: convert driver to use asynchronous firmware loading Drivers that load firmware from their probe routine have problems with the latest versions of udev as they get timeouts while waiting for user space to start. The problem is fixed by using request_firmware_nowait() and delaying the start of mac80211 until the firmware is loaded. To prevent the possibility of the driver being unloaded while the firmware loading callback is still active, a completion queue entry is used. Signed-off-by: Larry Finger Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 88 ++++++++++++++++++++++--------- drivers/net/wireless/p54/p54pci.h | 1 + 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 89318adc8c7f..b4390797d78c 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -488,6 +488,58 @@ static int p54p_open(struct ieee80211_hw *dev) return 0; } +static void p54p_firmware_step2(const struct firmware *fw, + void *context) +{ + struct p54p_priv *priv = context; + struct ieee80211_hw *dev = priv->common.hw; + struct pci_dev *pdev = priv->pdev; + int err; + + if (!fw) { + dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); + err = -ENOENT; + goto out; + } + + priv->firmware = fw; + + err = p54p_open(dev); + if (err) + goto out; + err = p54_read_eeprom(dev); + p54p_stop(dev); + if (err) + goto out; + + err = p54_register_common(dev, &pdev->dev); + if (err) + goto out; + +out: + + complete(&priv->fw_loaded); + + if (err) { + struct device *parent = pdev->dev.parent; + + if (parent) + device_lock(parent); + + /* + * This will indirectly result in a call to p54p_remove. + * Hence, we don't need to bother with freeing any + * allocated ressources at all. + */ + device_release_driver(&pdev->dev); + + if (parent) + device_unlock(parent); + } + + pci_dev_put(pdev); +} + static int __devinit p54p_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -496,6 +548,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, unsigned long mem_addr, mem_len; int err; + pci_dev_get(pdev); err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "Cannot enable new PCI device\n"); @@ -537,6 +590,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, priv = dev->priv; priv->pdev = pdev; + init_completion(&priv->fw_loaded); SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); @@ -561,32 +615,12 @@ static int __devinit p54p_probe(struct pci_dev *pdev, spin_lock_init(&priv->lock); tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev); - err = request_firmware(&priv->firmware, "isl3886pci", - &priv->pdev->dev); - if (err) { - dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); - err = request_firmware(&priv->firmware, "isl3886", - &priv->pdev->dev); - if (err) - goto err_free_common; - } + err = request_firmware_nowait(THIS_MODULE, 1, "isl3886pci", + &priv->pdev->dev, GFP_KERNEL, + priv, p54p_firmware_step2); + if (!err) + return 0; - err = p54p_open(dev); - if (err) - goto err_free_common; - err = p54_read_eeprom(dev); - p54p_stop(dev); - if (err) - goto err_free_common; - - err = p54_register_common(dev, &pdev->dev); - if (err) - goto err_free_common; - - return 0; - - err_free_common: - release_firmware(priv->firmware); pci_free_consistent(pdev, sizeof(*priv->ring_control), priv->ring_control, priv->ring_control_dma); @@ -601,6 +635,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, pci_release_regions(pdev); err_disable_dev: pci_disable_device(pdev); + pci_dev_put(pdev); return err; } @@ -612,8 +647,9 @@ static void __devexit p54p_remove(struct pci_dev *pdev) if (!dev) return; - p54_unregister_common(dev); priv = dev->priv; + wait_for_completion(&priv->fw_loaded); + p54_unregister_common(dev); release_firmware(priv->firmware); pci_free_consistent(pdev, sizeof(*priv->ring_control), priv->ring_control, priv->ring_control_dma); diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index 7aa509f7e387..68405c142f97 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h @@ -105,6 +105,7 @@ struct p54p_priv { struct sk_buff *tx_buf_data[32]; struct sk_buff *tx_buf_mgmt[4]; struct completion boot_comp; + struct completion fw_loaded; }; #endif /* P54USB_H */ From 6e6a2cd510351502064c3e2a56f411a19530cd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 25 Jul 2012 16:58:38 +0200 Subject: [PATCH 051/109] b43: rename host flags defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are more than 3 registers on new hardware. Host flags handling has to be rewritten, as we can't use u128 type to handle all 5 regs. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 8 +++++--- drivers/net/wireless/b43/main.c | 12 ++++++------ drivers/net/wireless/b43/phy_common.c | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 7c899fc7ddd0..56d0799e7b4b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -241,16 +241,18 @@ enum { #define B43_SHM_SH_PHYVER 0x0050 /* PHY version */ #define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */ #define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */ -#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */ -#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */ -#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */ +#define B43_SHM_SH_HOSTF1 0x005E /* Hostflags 1 for ucode options */ +#define B43_SHM_SH_HOSTF2 0x0060 /* Hostflags 2 for ucode options */ +#define B43_SHM_SH_HOSTF3 0x0062 /* Hostflags 3 for ucode options */ #define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */ #define B43_SHM_SH_RADAR 0x0066 /* Radar register */ #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */ #define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */ +#define B43_SHM_SH_HOSTF4 0x0078 /* Hostflags 4 for ucode options */ #define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ #define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5 Ghz channel */ #define B43_SHM_SH_CHAN_40MHZ 0x0200 /* Bit set, if 40 Mhz channel width */ +#define B43_SHM_SH_HOSTF5 0x00D4 /* Hostflags 5 for ucode options */ #define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ /* TSSI information */ #define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b80352b308d5..724c771133cc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -533,11 +533,11 @@ u64 b43_hf_read(struct b43_wldev *dev) { u64 ret; - ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI); + ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3); ret <<= 16; - ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI); + ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2); ret <<= 16; - ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO); + ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1); return ret; } @@ -550,9 +550,9 @@ void b43_hf_write(struct b43_wldev *dev, u64 value) lo = (value & 0x00000000FFFFULL); mi = (value & 0x0000FFFF0000ULL) >> 16; hi = (value & 0xFFFF00000000ULL) >> 32; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1, lo); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2, mi); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3, hi); } /* Read the firmware capabilities bitmask (Opensource firmware only) */ diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 3f8883b14d9c..f627cef33227 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -428,7 +428,7 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) average = (a + b + c + d + 2) / 4; if (is_ofdm) { /* Adjust for CCK-boost */ - if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO) + if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1) & B43_HF_CCKBOOST) average = (average >= 13) ? (average - 13) : 0; } From 0f941777c696e43e773b713a0078599aa22b3551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Jul 2012 00:07:37 +0200 Subject: [PATCH 052/109] b43: add helper waiting for given value in radio reg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_common.c | 15 +++++++++++++++ drivers/net/wireless/b43/phy_common.h | 6 ++++++ drivers/net/wireless/b43/phy_n.c | 12 +----------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index f627cef33227..f01676ac481b 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -240,6 +240,21 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) (b43_radio_read16(dev, offset) & mask) | set); } +bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask, + u16 value, int delay, int timeout) +{ + u16 val; + int i; + + for (i = 0; i < timeout; i += delay) { + val = b43_radio_read(dev, offset); + if ((val & mask) == value) + return true; + udelay(delay); + } + return false; +} + u16 b43_phy_read(struct b43_wldev *dev, u16 reg) { assert_mac_suspended(dev); diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 9233b13fc16d..f1b999349876 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -364,6 +364,12 @@ void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); */ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); +/** + * b43_radio_wait_value - Waits for a given value in masked register read + */ +bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask, + u16 value, int delay, int timeout); + /** * b43_radio_lock - Lock firmware radio register access */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e49d847c59f8..0963d593b247 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -753,8 +753,6 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; struct ssb_sprom *sprom = dev->dev->bus_sprom; - int i; - u16 val; bool workaround = false; if (sprom->revision < 4) @@ -777,15 +775,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) b43_radio_set(dev, B2055_CAL_MISC, 0x1); msleep(1); b43_radio_set(dev, B2055_CAL_MISC, 0x40); - for (i = 0; i < 200; i++) { - val = b43_radio_read(dev, B2055_CAL_COUT2); - if (val & 0x80) { - i = 0; - break; - } - udelay(10); - } - if (i) + if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000)) b43err(dev->wl, "radio post init timeout\n"); b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); b43_switch_channel(dev, dev->phy.channel); From d3d178f050813ec6b82b77cc2df668272e10daba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Jul 2012 00:07:38 +0200 Subject: [PATCH 053/109] b43: N-PHY: finish 0x2056 radio setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 95 ++++++++++++++++++++++++++++++-- drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 0963d593b247..0e75c3567f5d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -545,7 +545,9 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, enum ieee80211_band band = b43_current_band(dev->wl); u16 offset; u8 i; - u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost; + u16 bias, cbias; + u16 pag_boost, padg_boost, pgag_boost, mixg_boost; + u16 paa_boost, pada_boost, pgaa_boost, mixa_boost; B43_WARN_ON(dev->phy.rev < 3); @@ -630,7 +632,56 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee); } } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) { - /* TODO */ + u16 freq = dev->phy.channel_freq; + if (freq < 5100) { + paa_boost = 0xA; + pada_boost = 0x77; + pgaa_boost = 0xF; + mixa_boost = 0xF; + } else if (freq < 5340) { + paa_boost = 0x8; + pada_boost = 0x77; + pgaa_boost = 0xFB; + mixa_boost = 0xF; + } else if (freq < 5650) { + paa_boost = 0x0; + pada_boost = 0x77; + pgaa_boost = 0xB; + mixa_boost = 0xF; + } else { + paa_boost = 0x0; + pada_boost = 0x77; + if (freq != 5825) + pgaa_boost = -(freq - 18) / 36 + 168; + else + pgaa_boost = 6; + mixa_boost = 0xF; + } + + for (i = 0; i < 2; i++) { + offset = i ? B2056_TX1 : B2056_TX0; + + b43_radio_write(dev, + offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost); + b43_radio_write(dev, + offset | B2056_TX_PADA_BOOST_TUNE, pada_boost); + b43_radio_write(dev, + offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost); + b43_radio_write(dev, + offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost); + b43_radio_write(dev, + offset | B2056_TX_TXSPARE1, 0x30); + b43_radio_write(dev, + offset | B2056_TX_PA_SPARE2, 0xee); + b43_radio_write(dev, + offset | B2056_TX_PADA_CASCBIAS, 0x03); + b43_radio_write(dev, + offset | B2056_TX_INTPAA_IAUX_STAT, 0x50); + b43_radio_write(dev, + offset | B2056_TX_INTPAA_IMAIN_STAT, 0x50); + b43_radio_write(dev, + offset | B2056_TX_INTPAA_CASCBIAS, 0x30); + } } udelay(50); @@ -643,6 +694,37 @@ static void b43_radio_2056_setup(struct b43_wldev *dev, udelay(300); } +static u8 b43_radio_2056_rcal(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + u16 mast2, tmp; + + if (phy->rev != 3) + return 0; + + mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2); + b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7); + + udelay(10); + b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01); + udelay(10); + b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09); + + if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100, + 1000000)) { + b43err(dev->wl, "Radio recalibration timeout\n"); + return 0; + } + + b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01); + tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT); + b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00); + + b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2); + + return tmp & 0x1f; +} + static void b43_radio_init2056_pre(struct b43_wldev *dev) { b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, @@ -665,10 +747,8 @@ static void b43_radio_init2056_post(struct b43_wldev *dev) b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2); b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC); b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1); - /* - if (nphy->init_por) - Call Radio 2056 Recalibrate - */ + if (dev->phy.n->init_por) + b43_radio_2056_rcal(dev); } /* @@ -680,6 +760,8 @@ static void b43_radio_init2056(struct b43_wldev *dev) b43_radio_init2056_pre(dev); b2056_upload_inittabs(dev, 0, 0); b43_radio_init2056_post(dev); + + dev->phy.n->init_por = false; } /************************************************** @@ -5089,6 +5171,7 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); nphy->spur_avoid = (phy->rev >= 3) ? B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE; + nphy->init_por = true; nphy->gain_boost = true; /* this way we follow wl, assume it is true */ nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index fd12b386fea1..092c0140c249 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -785,6 +785,7 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; + bool init_por; bool gain_boost; bool elna_gain_config; From 572d37a48557e7d38a5d9b5857627bc29f33a26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Jul 2012 00:07:39 +0200 Subject: [PATCH 054/109] b43: N-PHY: init 0x2057 radio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/phy_n.c | 142 ++++++++- drivers/net/wireless/b43/radio_2057.c | 141 +++++++++ drivers/net/wireless/b43/radio_2057.h | 430 ++++++++++++++++++++++++++ 4 files changed, 712 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/b43/radio_2057.c create mode 100644 drivers/net/wireless/b43/radio_2057.h diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 4648bbf76abc..098fe9ee7096 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -4,6 +4,7 @@ b43-y += tables.o b43-$(CONFIG_B43_PHY_N) += tables_nphy.o b43-$(CONFIG_B43_PHY_N) += radio_2055.o b43-$(CONFIG_B43_PHY_N) += radio_2056.o +b43-$(CONFIG_B43_PHY_N) += radio_2057.o b43-y += phy_common.o b43-y += phy_g.o b43-y += phy_a.o diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 0e75c3567f5d..113d5ca6623b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -32,6 +32,7 @@ #include "tables_nphy.h" #include "radio_2055.h" #include "radio_2056.h" +#include "radio_2057.h" #include "main.h" struct nphy_txgains { @@ -458,6 +459,136 @@ static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, b43_nphy_stay_in_carrier_search(dev, false); } +/************************************************** + * Radio 0x2057 + **************************************************/ + +/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */ +static u8 b43_radio_2057_rcal(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + u16 tmp; + + if (phy->radio_rev == 5) { + b43_phy_mask(dev, 0x342, ~0x2); + udelay(10); + b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1); + b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1); + } + + b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1); + udelay(10); + b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3); + if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) { + b43err(dev->wl, "Radio 0x2057 rcal timeout\n"); + return 0; + } + b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2); + tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E; + b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1); + + if (phy->radio_rev == 5) { + b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1); + b43_radio_mask(dev, 0x1ca, ~0x2); + } + if (phy->radio_rev <= 4 || phy->radio_rev == 6) { + b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); + b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0, + tmp << 2); + } + + return tmp & 0x3e; +} + +/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */ +static u16 b43_radio_2057_rccal(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 || + phy->radio_rev == 6); + u16 tmp; + + if (special) { + b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0); + } else { + b43_radio_write(dev, 0x1AE, 0x61); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1); + } + b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); + if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500, + 5000000)) + b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n"); + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); + if (special) { + b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0); + } else { + b43_radio_write(dev, 0x1AE, 0x69); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5); + } + b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); + if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500, + 5000000)) + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); + if (special) { + b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73); + b43_radio_write(dev, R2057_RCCAL_X1, 0x28); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0); + } else { + b43_radio_write(dev, 0x1AE, 0x73); + b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); + b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99); + } + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); + if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500, + 5000000)) { + b43err(dev->wl, "Radio 0x2057 rcal timeout\n"); + return 0; + } + tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP); + b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); + return tmp; +} + +static void b43_radio_2057_init_pre(struct b43_wldev *dev) +{ + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU); + /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ + b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU); +} + +static void b43_radio_2057_init_post(struct b43_wldev *dev) +{ + b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1); + + b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78); + b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80); + mdelay(2); + b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78); + b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80); + + if (dev->phy.n->init_por) { + b43_radio_2057_rcal(dev); + b43_radio_2057_rccal(dev); + } + b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8); + + dev->phy.n->init_por = false; +} + +/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */ +static void b43_radio_2057_init(struct b43_wldev *dev) +{ + b43_radio_2057_init_pre(dev); + r2057_upload_inittabs(dev); + b43_radio_2057_init_post(dev); +} + /************************************************** * Radio 0x2056 **************************************************/ @@ -5212,6 +5343,8 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2; nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2; } + + nphy->init_por = true; } static void b43_nphy_op_free(struct b43_wldev *dev) @@ -5298,7 +5431,9 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, if (blocked) { b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU); - if (dev->phy.rev >= 3) { + if (dev->phy.rev >= 7) { + /* TODO */ + } else if (dev->phy.rev >= 3) { b43_radio_mask(dev, 0x09, ~0x2); b43_radio_write(dev, 0x204D, 0); @@ -5316,7 +5451,10 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, b43_radio_write(dev, 0x3064, 0); } } else { - if (dev->phy.rev >= 3) { + if (dev->phy.rev >= 7) { + b43_radio_2057_init(dev); + b43_switch_channel(dev, dev->phy.channel); + } else if (dev->phy.rev >= 3) { b43_radio_init2056(dev); b43_switch_channel(dev, dev->phy.channel); } else { diff --git a/drivers/net/wireless/b43/radio_2057.c b/drivers/net/wireless/b43/radio_2057.c new file mode 100644 index 000000000000..d61d6830c5c7 --- /dev/null +++ b/drivers/net/wireless/b43/radio_2057.c @@ -0,0 +1,141 @@ +/* + + Broadcom B43 wireless driver + IEEE 802.11n 2057 radio device data tables + + Copyright (c) 2010 Rafał Miłecki + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "radio_2057.h" +#include "phy_common.h" + +static u16 r2057_rev4_init[42][2] = { + { 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, + { 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff }, + { 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 }, + { 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c }, + { 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 }, + { 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c }, + { 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, + { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, + { 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, + { 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, + { 0x1AB, 0x00 }, { 0x1AC, 0x00 }, +}; + +static u16 r2057_rev5_init[44][2] = { + { 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 }, + { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, + { 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, + { 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 }, + { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 }, + { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f }, + { 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, + { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, + { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, + { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, + { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 }, +}; + +static u16 r2057_rev5a_init[45][2] = { + { 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 }, + { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, + { 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, + { 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 }, + { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 }, + { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f }, + { 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 }, + { 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, + { 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, + { 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, + { 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, + { 0x1C2, 0x80 }, +}; + +static u16 r2057_rev7_init[54][2] = { + { 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 }, + { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 }, + { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 }, + { 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, + { 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, + { 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, + { 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee }, + { 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 }, + { 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, + { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 }, + { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 }, + { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 }, + { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 }, + { 0x1B7, 0x05 }, { 0x1C2, 0xa0 }, +}; + +static u16 r2057_rev8_init[54][2] = { + { 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 }, + { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 }, + { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f }, + { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f }, + { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 }, + { 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, + { 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 }, + { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee }, + { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 }, + { 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 }, + { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 }, + { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 }, + { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 }, + { 0x1B7, 0x05 }, { 0x1C2, 0xa0 }, +}; + +void r2057_upload_inittabs(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + u16 *table = NULL; + u16 size, i; + + if (phy->rev == 7) { + table = r2057_rev4_init[0]; + size = ARRAY_SIZE(r2057_rev4_init); + } else if (phy->rev == 8 || phy->rev == 9) { + if (phy->radio_rev == 5) { + if (phy->radio_rev == 8) { + table = r2057_rev5_init[0]; + size = ARRAY_SIZE(r2057_rev5_init); + } else { + table = r2057_rev5a_init[0]; + size = ARRAY_SIZE(r2057_rev5a_init); + } + } else if (phy->radio_rev == 7) { + table = r2057_rev7_init[0]; + size = ARRAY_SIZE(r2057_rev7_init); + } else if (phy->radio_rev == 9) { + table = r2057_rev8_init[0]; + size = ARRAY_SIZE(r2057_rev8_init); + } + } + + if (table) { + for (i = 0; i < 10; i++) { + pr_info("radio_write 0x%X ", *table); + table++; + pr_info("0x%X\n", *table); + table++; + } + } +} diff --git a/drivers/net/wireless/b43/radio_2057.h b/drivers/net/wireless/b43/radio_2057.h new file mode 100644 index 000000000000..eeebd8fbeb0d --- /dev/null +++ b/drivers/net/wireless/b43/radio_2057.h @@ -0,0 +1,430 @@ +#ifndef B43_RADIO_2057_H_ +#define B43_RADIO_2057_H_ + +#include + +#include "tables_nphy.h" + +#define R2057_DACBUF_VINCM_CORE0 0x000 +#define R2057_IDCODE 0x001 +#define R2057_RCCAL_MASTER 0x002 +#define R2057_RCCAL_CAP_SIZE 0x003 +#define R2057_RCAL_CONFIG 0x004 +#define R2057_GPAIO_CONFIG 0x005 +#define R2057_GPAIO_SEL1 0x006 +#define R2057_GPAIO_SEL0 0x007 +#define R2057_CLPO_CONFIG 0x008 +#define R2057_BANDGAP_CONFIG 0x009 +#define R2057_BANDGAP_RCAL_TRIM 0x00a +#define R2057_AFEREG_CONFIG 0x00b +#define R2057_TEMPSENSE_CONFIG 0x00c +#define R2057_XTAL_CONFIG1 0x00d +#define R2057_XTAL_ICORE_SIZE 0x00e +#define R2057_XTAL_BUF_SIZE 0x00f +#define R2057_XTAL_PULLCAP_SIZE 0x010 +#define R2057_RFPLL_MASTER 0x011 +#define R2057_VCOMONITOR_VTH_L 0x012 +#define R2057_VCOMONITOR_VTH_H 0x013 +#define R2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x014 +#define R2057_VCO_VARCSIZE_IDAC 0x015 +#define R2057_VCOCAL_COUNTVAL0 0x016 +#define R2057_VCOCAL_COUNTVAL1 0x017 +#define R2057_VCOCAL_INTCLK_COUNT 0x018 +#define R2057_VCOCAL_MASTER 0x019 +#define R2057_VCOCAL_NUMCAPCHANGE 0x01a +#define R2057_VCOCAL_WINSIZE 0x01b +#define R2057_VCOCAL_DELAY_AFTER_REFRESH 0x01c +#define R2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x01d +#define R2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x01e +#define R2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x01f +#define R2057_VCO_FORCECAPEN_FORCECAP1 0x020 +#define R2057_VCO_FORCECAP0 0x021 +#define R2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x022 +#define R2057_RFPLL_PFD_RESET_PW 0x023 +#define R2057_RFPLL_LOOPFILTER_R2 0x024 +#define R2057_RFPLL_LOOPFILTER_R1 0x025 +#define R2057_RFPLL_LOOPFILTER_C3 0x026 +#define R2057_RFPLL_LOOPFILTER_C2 0x027 +#define R2057_RFPLL_LOOPFILTER_C1 0x028 +#define R2057_CP_KPD_IDAC 0x029 +#define R2057_RFPLL_IDACS 0x02a +#define R2057_RFPLL_MISC_EN 0x02b +#define R2057_RFPLL_MMD0 0x02c +#define R2057_RFPLL_MMD1 0x02d +#define R2057_RFPLL_MISC_CAL_RESETN 0x02e +#define R2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x02f +#define R2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x030 +#define R2057_VCOCAL_READCAP0 0x031 +#define R2057_VCOCAL_READCAP1 0x032 +#define R2057_VCOCAL_STATUS 0x033 +#define R2057_LOGEN_PUS 0x034 +#define R2057_LOGEN_PTAT_RESETS 0x035 +#define R2057_VCOBUF_IDACS 0x036 +#define R2057_VCOBUF_TUNE 0x037 +#define R2057_CMOSBUF_TX2GQ_IDACS 0x038 +#define R2057_CMOSBUF_TX2GI_IDACS 0x039 +#define R2057_CMOSBUF_TX5GQ_IDACS 0x03a +#define R2057_CMOSBUF_TX5GI_IDACS 0x03b +#define R2057_CMOSBUF_RX2GQ_IDACS 0x03c +#define R2057_CMOSBUF_RX2GI_IDACS 0x03d +#define R2057_CMOSBUF_RX5GQ_IDACS 0x03e +#define R2057_CMOSBUF_RX5GI_IDACS 0x03f +#define R2057_LOGEN_MX2G_IDACS 0x040 +#define R2057_LOGEN_MX2G_TUNE 0x041 +#define R2057_LOGEN_MX5G_IDACS 0x042 +#define R2057_LOGEN_MX5G_TUNE 0x043 +#define R2057_LOGEN_MX5G_RCCR 0x044 +#define R2057_LOGEN_INDBUF2G_IDAC 0x045 +#define R2057_LOGEN_INDBUF2G_IBOOST 0x046 +#define R2057_LOGEN_INDBUF2G_TUNE 0x047 +#define R2057_LOGEN_INDBUF5G_IDAC 0x048 +#define R2057_LOGEN_INDBUF5G_IBOOST 0x049 +#define R2057_LOGEN_INDBUF5G_TUNE 0x04a +#define R2057_CMOSBUF_TX_RCCR 0x04b +#define R2057_CMOSBUF_RX_RCCR 0x04c +#define R2057_LOGEN_SEL_PKDET 0x04d +#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e +#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f +#define R2057_TXGM_TXRF_PUS_CORE0 0x050 +#define R2057_TXGM_IDAC_BLEED_CORE0 0x051 +#define R2057_TXGM_GAIN_CORE0 0x056 +#define R2057_TXGM2G_PKDET_PUS_CORE0 0x057 +#define R2057_PAD2G_PTATS_CORE0 0x058 +#define R2057_PAD2G_IDACS_CORE0 0x059 +#define R2057_PAD2G_BOOST_PU_CORE0 0x05a +#define R2057_PAD2G_CASCV_GAIN_CORE0 0x05b +#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x05c +#define R2057_TXMIX2G_LODC_CORE0 0x05d +#define R2057_PAD2G_TUNE_PUS_CORE0 0x05e +#define R2057_IPA2G_GAIN_CORE0 0x05f +#define R2057_TSSI2G_SPARE1_CORE0 0x060 +#define R2057_TSSI2G_SPARE2_CORE0 0x061 +#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x062 +#define R2057_IPA2G_IMAIN_CORE0 0x063 +#define R2057_IPA2G_CASCONV_CORE0 0x064 +#define R2057_IPA2G_CASCOFFV_CORE0 0x065 +#define R2057_IPA2G_BIAS_FILTER_CORE0 0x066 +#define R2057_TX5G_PKDET_CORE0 0x069 +#define R2057_PGA_PTAT_TXGM5G_PU_CORE0 0x06a +#define R2057_PAD5G_PTATS1_CORE0 0x06b +#define R2057_PAD5G_CLASS_PTATS2_CORE0 0x06c +#define R2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x06d +#define R2057_PAD5G_CASCV_IMAIN_CORE0 0x06e +#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x06f +#define R2057_PGA_BOOST_TUNE_CORE0 0x070 +#define R2057_PGA_GAIN_CORE0 0x071 +#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x072 +#define R2057_TXMIX5G_BOOST_TUNE_CORE0 0x073 +#define R2057_PAD5G_TUNE_MISC_PUS_CORE0 0x074 +#define R2057_IPA5G_IAUX_CORE0 0x075 +#define R2057_IPA5G_GAIN_CORE0 0x076 +#define R2057_TSSI5G_SPARE1_CORE0 0x077 +#define R2057_TSSI5G_SPARE2_CORE0 0x078 +#define R2057_IPA5G_CASCOFFV_PU_CORE0 0x079 +#define R2057_IPA5G_PTAT_CORE0 0x07a +#define R2057_IPA5G_IMAIN_CORE0 0x07b +#define R2057_IPA5G_CASCONV_CORE0 0x07c +#define R2057_IPA5G_BIAS_FILTER_CORE0 0x07d +#define R2057_PAD_BIAS_FILTER_BWS_CORE0 0x080 +#define R2057_TR2G_CONFIG1_CORE0_NU 0x081 +#define R2057_TR2G_CONFIG2_CORE0_NU 0x082 +#define R2057_LNA5G_RFEN_CORE0 0x083 +#define R2057_TR5G_CONFIG2_CORE0_NU 0x084 +#define R2057_RXRFBIAS_IBOOST_PU_CORE0 0x085 +#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x086 +#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x087 +#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x088 +#define R2057_RXMIX_CMFBITAIL_PU_CORE0 0x089 +#define R2057_LNA2_IMAIN_PTAT_PU_CORE0 0x08a +#define R2057_LNA2_IAUX_PTAT_CORE0 0x08b +#define R2057_LNA1_IMAIN_PTAT_PU_CORE0 0x08c +#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x08d +#define R2057_RXRFBIAS_BANDSEL_CORE0 0x08e +#define R2057_TIA_CONFIG_CORE0 0x08f +#define R2057_TIA_IQGAIN_CORE0 0x090 +#define R2057_TIA_IBIAS2_CORE0 0x091 +#define R2057_TIA_IBIAS1_CORE0 0x092 +#define R2057_TIA_SPARE_Q_CORE0 0x093 +#define R2057_TIA_SPARE_I_CORE0 0x094 +#define R2057_RXMIX2G_PUS_CORE0 0x095 +#define R2057_RXMIX2G_VCMREFS_CORE0 0x096 +#define R2057_RXMIX2G_LODC_QI_CORE0 0x097 +#define R2057_W12G_BW_LNA2G_PUS_CORE0 0x098 +#define R2057_LNA2G_GAIN_CORE0 0x099 +#define R2057_LNA2G_TUNE_CORE0 0x09a +#define R2057_RXMIX5G_PUS_CORE0 0x09b +#define R2057_RXMIX5G_VCMREFS_CORE0 0x09c +#define R2057_RXMIX5G_LODC_QI_CORE0 0x09d +#define R2057_W15G_BW_LNA5G_PUS_CORE0 0x09e +#define R2057_LNA5G_GAIN_CORE0 0x09f +#define R2057_LNA5G_TUNE_CORE0 0x0a0 +#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0x0a1 +#define R2057_RXBB_BIAS_MASTER_CORE0 0x0a2 +#define R2057_RXBB_VGABUF_IDACS_CORE0 0x0a3 +#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0x0a4 +#define R2057_TXBUF_VINCM_CORE0 0x0a5 +#define R2057_TXBUF_IDACS_CORE0 0x0a6 +#define R2057_LPF_RESP_RXBUF_BW_CORE0 0x0a7 +#define R2057_RXBB_CC_CORE0 0x0a8 +#define R2057_RXBB_SPARE3_CORE0 0x0a9 +#define R2057_RXBB_RCCAL_HPC_CORE0 0x0aa +#define R2057_LPF_IDACS_CORE0 0x0ab +#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0x0ac +#define R2057_TXBUF_GAIN_CORE0 0x0ad +#define R2057_AFELOOPBACK_AACI_RESP_CORE0 0x0ae +#define R2057_RXBUF_DEGEN_CORE0 0x0af +#define R2057_RXBB_SPARE2_CORE0 0x0b0 +#define R2057_RXBB_SPARE1_CORE0 0x0b1 +#define R2057_RSSI_MASTER_CORE0 0x0b2 +#define R2057_W2_MASTER_CORE0 0x0b3 +#define R2057_NB_MASTER_CORE0 0x0b4 +#define R2057_W2_IDACS0_Q_CORE0 0x0b5 +#define R2057_W2_IDACS1_Q_CORE0 0x0b6 +#define R2057_W2_IDACS0_I_CORE0 0x0b7 +#define R2057_W2_IDACS1_I_CORE0 0x0b8 +#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0x0b9 +#define R2057_NB_IDACS_Q_CORE0 0x0ba +#define R2057_NB_IDACS_I_CORE0 0x0bb +#define R2057_BACKUP4_CORE0 0x0c1 +#define R2057_BACKUP3_CORE0 0x0c2 +#define R2057_BACKUP2_CORE0 0x0c3 +#define R2057_BACKUP1_CORE0 0x0c4 +#define R2057_SPARE16_CORE0 0x0c5 +#define R2057_SPARE15_CORE0 0x0c6 +#define R2057_SPARE14_CORE0 0x0c7 +#define R2057_SPARE13_CORE0 0x0c8 +#define R2057_SPARE12_CORE0 0x0c9 +#define R2057_SPARE11_CORE0 0x0ca +#define R2057_TX2G_BIAS_RESETS_CORE0 0x0cb +#define R2057_TX5G_BIAS_RESETS_CORE0 0x0cc +#define R2057_IQTEST_SEL_PU 0x0cd +#define R2057_XTAL_CONFIG2 0x0ce +#define R2057_BUFS_MISC_LPFBW_CORE0 0x0cf +#define R2057_TXLPF_RCCAL_CORE0 0x0d0 +#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1 +#define R2057_LPF_GAIN_CORE0 0x0d2 +#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3 +#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4 +#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5 +#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6 +#define R2057_TXGM_GAIN_CORE1 0x0db +#define R2057_TXGM2G_PKDET_PUS_CORE1 0x0dc +#define R2057_PAD2G_PTATS_CORE1 0x0dd +#define R2057_PAD2G_IDACS_CORE1 0x0de +#define R2057_PAD2G_BOOST_PU_CORE1 0x0df +#define R2057_PAD2G_CASCV_GAIN_CORE1 0x0e0 +#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0x0e1 +#define R2057_TXMIX2G_LODC_CORE1 0x0e2 +#define R2057_PAD2G_TUNE_PUS_CORE1 0x0e3 +#define R2057_IPA2G_GAIN_CORE1 0x0e4 +#define R2057_TSSI2G_SPARE1_CORE1 0x0e5 +#define R2057_TSSI2G_SPARE2_CORE1 0x0e6 +#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0x0e7 +#define R2057_IPA2G_IMAIN_CORE1 0x0e8 +#define R2057_IPA2G_CASCONV_CORE1 0x0e9 +#define R2057_IPA2G_CASCOFFV_CORE1 0x0ea +#define R2057_IPA2G_BIAS_FILTER_CORE1 0x0eb +#define R2057_TX5G_PKDET_CORE1 0x0ee +#define R2057_PGA_PTAT_TXGM5G_PU_CORE1 0x0ef +#define R2057_PAD5G_PTATS1_CORE1 0x0f0 +#define R2057_PAD5G_CLASS_PTATS2_CORE1 0x0f1 +#define R2057_PGA_BOOSTPTAT_IMAIN_CORE1 0x0f2 +#define R2057_PAD5G_CASCV_IMAIN_CORE1 0x0f3 +#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0x0f4 +#define R2057_PGA_BOOST_TUNE_CORE1 0x0f5 +#define R2057_PGA_GAIN_CORE1 0x0f6 +#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0x0f7 +#define R2057_TXMIX5G_BOOST_TUNE_CORE1 0x0f8 +#define R2057_PAD5G_TUNE_MISC_PUS_CORE1 0x0f9 +#define R2057_IPA5G_IAUX_CORE1 0x0fa +#define R2057_IPA5G_GAIN_CORE1 0x0fb +#define R2057_TSSI5G_SPARE1_CORE1 0x0fc +#define R2057_TSSI5G_SPARE2_CORE1 0x0fd +#define R2057_IPA5G_CASCOFFV_PU_CORE1 0x0fe +#define R2057_IPA5G_PTAT_CORE1 0x0ff +#define R2057_IPA5G_IMAIN_CORE1 0x100 +#define R2057_IPA5G_CASCONV_CORE1 0x101 +#define R2057_IPA5G_BIAS_FILTER_CORE1 0x102 +#define R2057_PAD_BIAS_FILTER_BWS_CORE1 0x105 +#define R2057_TR2G_CONFIG1_CORE1_NU 0x106 +#define R2057_TR2G_CONFIG2_CORE1_NU 0x107 +#define R2057_LNA5G_RFEN_CORE1 0x108 +#define R2057_TR5G_CONFIG2_CORE1_NU 0x109 +#define R2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a +#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b +#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c +#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d +#define R2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e +#define R2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f +#define R2057_LNA2_IAUX_PTAT_CORE1 0x110 +#define R2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111 +#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112 +#define R2057_RXRFBIAS_BANDSEL_CORE1 0x113 +#define R2057_TIA_CONFIG_CORE1 0x114 +#define R2057_TIA_IQGAIN_CORE1 0x115 +#define R2057_TIA_IBIAS2_CORE1 0x116 +#define R2057_TIA_IBIAS1_CORE1 0x117 +#define R2057_TIA_SPARE_Q_CORE1 0x118 +#define R2057_TIA_SPARE_I_CORE1 0x119 +#define R2057_RXMIX2G_PUS_CORE1 0x11a +#define R2057_RXMIX2G_VCMREFS_CORE1 0x11b +#define R2057_RXMIX2G_LODC_QI_CORE1 0x11c +#define R2057_W12G_BW_LNA2G_PUS_CORE1 0x11d +#define R2057_LNA2G_GAIN_CORE1 0x11e +#define R2057_LNA2G_TUNE_CORE1 0x11f +#define R2057_RXMIX5G_PUS_CORE1 0x120 +#define R2057_RXMIX5G_VCMREFS_CORE1 0x121 +#define R2057_RXMIX5G_LODC_QI_CORE1 0x122 +#define R2057_W15G_BW_LNA5G_PUS_CORE1 0x123 +#define R2057_LNA5G_GAIN_CORE1 0x124 +#define R2057_LNA5G_TUNE_CORE1 0x125 +#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126 +#define R2057_RXBB_BIAS_MASTER_CORE1 0x127 +#define R2057_RXBB_VGABUF_IDACS_CORE1 0x128 +#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129 +#define R2057_TXBUF_VINCM_CORE1 0x12a +#define R2057_TXBUF_IDACS_CORE1 0x12b +#define R2057_LPF_RESP_RXBUF_BW_CORE1 0x12c +#define R2057_RXBB_CC_CORE1 0x12d +#define R2057_RXBB_SPARE3_CORE1 0x12e +#define R2057_RXBB_RCCAL_HPC_CORE1 0x12f +#define R2057_LPF_IDACS_CORE1 0x130 +#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131 +#define R2057_TXBUF_GAIN_CORE1 0x132 +#define R2057_AFELOOPBACK_AACI_RESP_CORE1 0x133 +#define R2057_RXBUF_DEGEN_CORE1 0x134 +#define R2057_RXBB_SPARE2_CORE1 0x135 +#define R2057_RXBB_SPARE1_CORE1 0x136 +#define R2057_RSSI_MASTER_CORE1 0x137 +#define R2057_W2_MASTER_CORE1 0x138 +#define R2057_NB_MASTER_CORE1 0x139 +#define R2057_W2_IDACS0_Q_CORE1 0x13a +#define R2057_W2_IDACS1_Q_CORE1 0x13b +#define R2057_W2_IDACS0_I_CORE1 0x13c +#define R2057_W2_IDACS1_I_CORE1 0x13d +#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e +#define R2057_NB_IDACS_Q_CORE1 0x13f +#define R2057_NB_IDACS_I_CORE1 0x140 +#define R2057_BACKUP4_CORE1 0x146 +#define R2057_BACKUP3_CORE1 0x147 +#define R2057_BACKUP2_CORE1 0x148 +#define R2057_BACKUP1_CORE1 0x149 +#define R2057_SPARE16_CORE1 0x14a +#define R2057_SPARE15_CORE1 0x14b +#define R2057_SPARE14_CORE1 0x14c +#define R2057_SPARE13_CORE1 0x14d +#define R2057_SPARE12_CORE1 0x14e +#define R2057_SPARE11_CORE1 0x14f +#define R2057_TX2G_BIAS_RESETS_CORE1 0x150 +#define R2057_TX5G_BIAS_RESETS_CORE1 0x151 +#define R2057_SPARE8_CORE1 0x152 +#define R2057_SPARE7_CORE1 0x153 +#define R2057_BUFS_MISC_LPFBW_CORE1 0x154 +#define R2057_TXLPF_RCCAL_CORE1 0x155 +#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 +#define R2057_LPF_GAIN_CORE1 0x157 +#define R2057_DACBUF_IDACS_BW_CORE1 0x158 +#define R2057_DACBUF_VINCM_CORE1 0x159 +#define R2057_RCCAL_START_R1_Q1_P1 0x15a +#define R2057_RCCAL_X1 0x15b +#define R2057_RCCAL_TRC0 0x15c +#define R2057_RCCAL_TRC1 0x15d +#define R2057_RCCAL_DONE_OSCCAP 0x15e +#define R2057_RCCAL_N0_0 0x15f +#define R2057_RCCAL_N0_1 0x160 +#define R2057_RCCAL_N1_0 0x161 +#define R2057_RCCAL_N1_1 0x162 +#define R2057_RCAL_STATUS 0x163 +#define R2057_XTALPUOVR_PINCTRL 0x164 +#define R2057_OVR_REG0 0x165 +#define R2057_OVR_REG1 0x166 +#define R2057_OVR_REG2 0x167 +#define R2057_OVR_REG3 0x168 +#define R2057_OVR_REG4 0x169 +#define R2057_RCCAL_SCAP_VAL 0x16a +#define R2057_RCCAL_BCAP_VAL 0x16b +#define R2057_RCCAL_HPC_VAL 0x16c +#define R2057_RCCAL_OVERRIDES 0x16d +#define R2057_TX0_IQCAL_GAIN_BW 0x170 +#define R2057_TX0_LOFT_FINE_I 0x171 +#define R2057_TX0_LOFT_FINE_Q 0x172 +#define R2057_TX0_LOFT_COARSE_I 0x173 +#define R2057_TX0_LOFT_COARSE_Q 0x174 +#define R2057_TX0_TX_SSI_MASTER 0x175 +#define R2057_TX0_IQCAL_VCM_HG 0x176 +#define R2057_TX0_IQCAL_IDAC 0x177 +#define R2057_TX0_TSSI_VCM 0x178 +#define R2057_TX0_TX_SSI_MUX 0x179 +#define R2057_TX0_TSSIA 0x17a +#define R2057_TX0_TSSIG 0x17b +#define R2057_TX0_TSSI_MISC1 0x17c +#define R2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d +#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e +#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f +#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 +#define R2057_TX1_IQCAL_GAIN_BW 0x190 +#define R2057_TX1_LOFT_FINE_I 0x191 +#define R2057_TX1_LOFT_FINE_Q 0x192 +#define R2057_TX1_LOFT_COARSE_I 0x193 +#define R2057_TX1_LOFT_COARSE_Q 0x194 +#define R2057_TX1_TX_SSI_MASTER 0x195 +#define R2057_TX1_IQCAL_VCM_HG 0x196 +#define R2057_TX1_IQCAL_IDAC 0x197 +#define R2057_TX1_TSSI_VCM 0x198 +#define R2057_TX1_TX_SSI_MUX 0x199 +#define R2057_TX1_TSSIA 0x19a +#define R2057_TX1_TSSIG 0x19b +#define R2057_TX1_TSSI_MISC1 0x19c +#define R2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d +#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e +#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f +#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 +#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 +#define R2057_AFE_SET_VCM_I_CORE0 0x1a2 +#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3 +#define R2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4 +#define R2057_AFE_STATUS_VCM_I_CORE0 0x1a5 +#define R2057_AFE_STATUS_VCM_Q_CORE0 0x1a6 +#define R2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7 +#define R2057_AFE_SET_VCM_I_CORE1 0x1a8 +#define R2057_AFE_SET_VCM_Q_CORE1 0x1a9 +#define R2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa +#define R2057_AFE_STATUS_VCM_I_CORE1 0x1ab +#define R2057_AFE_STATUS_VCM_Q_CORE1 0x1ac + +#define R2057v7_DACBUF_VINCM_CORE0 0x1ad +#define R2057v7_RCCAL_MASTER 0x1ae +#define R2057v7_TR2G_CONFIG3_CORE0_NU 0x1af +#define R2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0 +#define R2057v7_LOGEN_PUS1 0x1b1 +#define R2057v7_OVR_REG5 0x1b2 +#define R2057v7_OVR_REG6 0x1b3 +#define R2057v7_OVR_REG7 0x1b4 +#define R2057v7_OVR_REG8 0x1b5 +#define R2057v7_OVR_REG9 0x1b6 +#define R2057v7_OVR_REG10 0x1b7 +#define R2057v7_OVR_REG11 0x1b8 +#define R2057v7_OVR_REG12 0x1b9 +#define R2057v7_OVR_REG13 0x1ba +#define R2057v7_OVR_REG14 0x1bb +#define R2057v7_OVR_REG15 0x1bc +#define R2057v7_OVR_REG16 0x1bd +#define R2057v7_OVR_REG1 0x1be +#define R2057v7_OVR_REG18 0x1bf +#define R2057v7_OVR_REG19 0x1c0 +#define R2057v7_OVR_REG20 0x1c1 +#define R2057v7_OVR_REG21 0x1c2 +#define R2057v7_OVR_REG2 0x1c3 +#define R2057v7_OVR_REG23 0x1c4 +#define R2057v7_OVR_REG24 0x1c5 +#define R2057v7_OVR_REG25 0x1c6 +#define R2057v7_OVR_REG26 0x1c7 +#define R2057v7_OVR_REG27 0x1c8 +#define R2057v7_OVR_REG28 0x1c9 +#define R2057v7_IQTEST_SEL_PU2 0x1ca + +#define R2057_VCM_MASK 0x7 + +void r2057_upload_inittabs(struct b43_wldev *dev); + +#endif /* B43_RADIO_2057_H_ */ From 2fdf8c54ea6ea161fa519a701188cbc56a3bb106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Jul 2012 08:16:01 +0200 Subject: [PATCH 055/109] b43: be more user friendly with PHY info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First of all, use PHY names instead of magic numbers. It should make configuring kernel easier in case of not enabled PHY type support. Secondly, always print info about PHY. This is really basic info about hardware and quite important for the support level. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 2 ++ drivers/net/wireless/b43/main.c | 39 ++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 56d0799e7b4b..b298e5d68be2 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -417,6 +417,8 @@ enum { #define B43_PHYTYPE_HT 0x07 #define B43_PHYTYPE_LCN 0x08 #define B43_PHYTYPE_LCNXN 0x09 +#define B43_PHYTYPE_LCN40 0x0a +#define B43_PHYTYPE_AC 0x0b /* PHYRegisters */ #define B43_PHY_ILT_A_CTRL 0x0072 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 724c771133cc..5efa77884704 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4277,6 +4277,35 @@ out: return err; } +static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type) +{ + switch (phy_type) { + case B43_PHYTYPE_A: + return "A"; + case B43_PHYTYPE_B: + return "B"; + case B43_PHYTYPE_G: + return "G"; + case B43_PHYTYPE_N: + return "N"; + case B43_PHYTYPE_LP: + return "LP"; + case B43_PHYTYPE_SSLPN: + return "SSLPN"; + case B43_PHYTYPE_HT: + return "HT"; + case B43_PHYTYPE_LCN: + return "LCN"; + case B43_PHYTYPE_LCNXN: + return "LCNXN"; + case B43_PHYTYPE_LCN40: + return "LCN40"; + case B43_PHYTYPE_AC: + return "AC"; + } + return "UNKNOWN"; +} + /* Get PHY and RADIO versioning numbers */ static int b43_phy_versioning(struct b43_wldev *dev) { @@ -4337,13 +4366,13 @@ static int b43_phy_versioning(struct b43_wldev *dev) unsupported = 1; } if (unsupported) { - b43err(dev->wl, "FOUND UNSUPPORTED PHY " - "(Analog %u, Type %u, Revision %u)\n", - analog_type, phy_type, phy_rev); + b43err(dev->wl, "FOUND UNSUPPORTED PHY (Analog %u, Type %d (%s), Revision %u)\n", + analog_type, phy_type, b43_phy_name(dev, phy_type), + phy_rev); return -EOPNOTSUPP; } - b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n", - analog_type, phy_type, phy_rev); + b43info(dev->wl, "Found PHY: Analog %u, Type %d (%s), Revision %u\n", + analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev); /* Get RADIO versioning */ if (dev->dev->core_rev >= 24) { From c071b9f666beee2b27b5a4667f099026ca539bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Jul 2012 10:25:09 +0200 Subject: [PATCH 056/109] b43: N-PHY: add overriding RF control for rev7+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 48 +++++++++++++++-- drivers/net/wireless/b43/tables_nphy.c | 75 ++++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 10 ++++ 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 113d5ca6623b..5c9074142a8e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -127,6 +127,46 @@ ok: b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ +static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field, + u16 value, u8 core, bool off, + u8 override) +{ + const struct nphy_rf_control_override_rev7 *e; + u16 en_addrs[3][2] = { + { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } + }; + u16 en_addr; + u16 en_mask = field; + u16 val_addr; + u8 i; + + /* Remember: we can get NULL! */ + e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override); + + for (i = 0; i < 2; i++) { + if (override >= ARRAY_SIZE(en_addrs)) { + b43err(dev->wl, "Invalid override value %d\n", override); + return; + } + en_addr = en_addrs[override][i]; + + val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; + + if (off) { + b43_phy_mask(dev, en_addr, ~en_mask); + if (e) /* Do it safer, better than wl */ + b43_phy_mask(dev, val_addr, ~e->val_mask); + } else { + if (!core || (core & (1 << i))) { + b43_phy_set(dev, en_addr, en_mask); + if (e) + b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift)); + } + } + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, u16 value, u8 core, bool off) @@ -2219,11 +2259,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), rx2tx_lut_40_11n); } - /* b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, 0, 2); */ + b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2); } b43_phy_write(dev, 0x32F, 0x3); if (phy->radio_rev == 4 || phy->radio_rev == 6) - ; /* b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, 0, 0); */ + b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0); if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) { if (sprom->revision && @@ -3083,7 +3123,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) b43_nphy_ipa_internal_tssi_setup(dev); if (phy->rev >= 7) - ; /* TODO: Override Rev7 with 0x2000, 0, 3, 0, 0 as arguments */ + b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0); else if (phy->rev >= 3) b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false); @@ -3095,7 +3135,7 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) b43_nphy_rssi_select(dev, 0, 0); if (phy->rev >= 7) - ; /* TODO: Override Rev7 with 0x2000, 0, 3, 1, 0 as arguments */ + b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0); else if (phy->rev >= 3) b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true); diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index f0d8377429c6..97d4e27bf36f 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2757,6 +2757,49 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = { { 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */ }; +/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */ +static const struct nphy_rf_control_override_rev7 + tbl_rf_control_override_rev7_over0[] = { + { 0x0004, 0x07A, 0x07D, 0x0002, 1 }, + { 0x0008, 0x07A, 0x07D, 0x0004, 2 }, + { 0x0010, 0x07A, 0x07D, 0x0010, 4 }, + { 0x0020, 0x07A, 0x07D, 0x0020, 5 }, + { 0x0040, 0x07A, 0x07D, 0x0040, 6 }, + { 0x0080, 0x0F8, 0x0FA, 0x0080, 7 }, + { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 }, + { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 }, + { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 }, + { 0x6000, 0x348, 0x349, 0xFFFF, 0 }, + { 0x2000, 0x348, 0x349, 0x000F, 0 }, +}; + +/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */ +static const struct nphy_rf_control_override_rev7 + tbl_rf_control_override_rev7_over1[] = { + { 0x0002, 0x340, 0x341, 0x0002, 1 }, + { 0x0008, 0x340, 0x341, 0x0008, 3 }, + { 0x0020, 0x340, 0x341, 0x0020, 5 }, + { 0x0010, 0x340, 0x341, 0x0010, 4 }, + { 0x0004, 0x340, 0x341, 0x0004, 2 }, + { 0x0080, 0x340, 0x341, 0x0700, 8 }, + { 0x0800, 0x340, 0x341, 0x4000, 14 }, + { 0x0400, 0x340, 0x341, 0x2000, 13 }, + { 0x0200, 0x340, 0x341, 0x0800, 12 }, + { 0x0100, 0x340, 0x341, 0x0100, 11 }, + { 0x0040, 0x340, 0x341, 0x0040, 6 }, + { 0x0001, 0x340, 0x341, 0x0001, 0 }, +}; + +/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */ +static const struct nphy_rf_control_override_rev7 + tbl_rf_control_override_rev7_over2[] = { + { 0x0008, 0x344, 0x345, 0x0008, 3 }, + { 0x0002, 0x344, 0x345, 0x0002, 1 }, + { 0x0001, 0x344, 0x345, 0x0001, 0 }, + { 0x0004, 0x344, 0x345, 0x0004, 2 }, + { 0x0010, 0x344, 0x345, 0x0010, 4 }, +}; + struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { { 10, 14, 19, 27 }, { -5, 6, 10, 15 }, @@ -3248,3 +3291,35 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( return e; } + +const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7( + struct b43_wldev *dev, u16 field, u8 override) +{ + const struct nphy_rf_control_override_rev7 *e; + u8 size, i; + + switch (override) { + case 0: + e = tbl_rf_control_override_rev7_over0; + size = ARRAY_SIZE(tbl_rf_control_override_rev7_over0); + break; + case 1: + e = tbl_rf_control_override_rev7_over1; + size = ARRAY_SIZE(tbl_rf_control_override_rev7_over1); + break; + case 2: + e = tbl_rf_control_override_rev7_over2; + size = ARRAY_SIZE(tbl_rf_control_override_rev7_over2); + break; + default: + b43err(dev->wl, "Invalid override value %d\n", override); + return NULL; + } + + for (i = 0; i < size; i++) { + if (e[i].field == field) + return &e[i]; + } + + return NULL; +} diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index f348953c0230..c600700ceedc 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -35,6 +35,14 @@ struct nphy_rf_control_override_rev3 { u8 val_addr1; }; +struct nphy_rf_control_override_rev7 { + u16 field; + u16 val_addr_core0; + u16 val_addr_core1; + u16 val_mask; + u8 val_shift; +}; + struct nphy_gain_ctl_workaround_entry { s8 lna1_gain[4]; s8 lna2_gain[4]; @@ -202,5 +210,7 @@ extern const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[]; extern const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[]; +const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7( + struct b43_wldev *dev, u16 field, u8 override); #endif /* B43_TABLES_NPHY_H_ */ From da93c26d0b26139f33cebf9af55715452a10f374 Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Fri, 27 Jul 2012 11:27:25 -0700 Subject: [PATCH 057/109] carl9170: Add support for NL80211_IFTYPE_MESH_POINT interfaces This patch contains following modifications: - Add mesh capabilities on fw.c to permit creation of mesh interfaces using this driver. - Modify carl9170_set_operating_mode, to use AP-style beaconing with mesh interfaces. - Allow beacon updates for NL80211_IFTYPE_MESH_POINT type in carl9170_handle_command_response. - Add NL80211_IFTYPE_MESH_POINT case on carl9170_op_add_interfaces to support mesh/ap/sta virtual interface combinations. Signed-off-by: Javier Lopez Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/fw.c | 1 + drivers/net/wireless/ath/carl9170/mac.c | 2 +- drivers/net/wireless/ath/carl9170/main.c | 4 +++- drivers/net/wireless/ath/carl9170/rx.c | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index c5ca6f1f5836..24ac2876a733 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -341,6 +341,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WLANTX_CAB)) { if_comb_types |= BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_P2P_GO); } } diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index 53415bfd8bef..f8676280dc36 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -318,10 +318,10 @@ int carl9170_set_operating_mode(struct ar9170 *ar) bssid = common->curbssid; switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: cam_mode |= AR9170_MAC_CAM_IBSS; break; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: cam_mode |= AR9170_MAC_CAM_AP; diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 858e58dfc4dc..18554ab76733 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -616,10 +616,12 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, goto unlock; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: if ((vif->type == NL80211_IFTYPE_STATION) || (vif->type == NL80211_IFTYPE_WDS) || - (vif->type == NL80211_IFTYPE_AP)) + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) break; err = -EBUSY; diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 6f6a34155667..b813f43061f5 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -206,6 +206,7 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: carl9170_update_beacon(ar, true); break; From 5fc512439f7a235e6b0ae05e42fa7d875fff3849 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 2 Aug 2012 16:00:51 +0200 Subject: [PATCH 058/109] ath9k: optimize power level initialization for CTL_[25]GHT20 The first part of the power array is initialized in a loop and the last two values are initialized separately. Extend the loop to cover the last two items, and remove the separate initialization. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2588848f4a82..a2aa80f2c210 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4963,16 +4963,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, case CTL_5GHT20: case CTL_2GHT20: for (i = ALL_TARGET_HT20_0_8_16; - i <= ALL_TARGET_HT20_21; i++) + i <= ALL_TARGET_HT20_23; i++) pPwrArray[i] = (u8)min((u16)pPwrArray[i], minCtlPower); - pPwrArray[ALL_TARGET_HT20_22] = - (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22], - minCtlPower); - pPwrArray[ALL_TARGET_HT20_23] = - (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23], - minCtlPower); break; case CTL_5GHT40: case CTL_2GHT40: From 2a0b50c7703930a1f5d1d32ae116d988e9612cb6 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 2 Aug 2012 16:00:52 +0200 Subject: [PATCH 059/109] ath9k: fix indentation in ar9003_hw_set_power_per_rate_table The current indentation is off by one tab. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 139 +++++++++--------- 1 file changed, 67 insertions(+), 72 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a2aa80f2c210..c37fe9620e41 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4901,84 +4901,79 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], chan->channel); - /* - * compare test group from regulatory - * channel list with test mode from pCtlMode - * list - */ - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((ctlIndex[i] & CTL_MODE_M) | - SD_NO_CTL))) { - twiceMinEdgePower = - ar9003_hw_get_max_edge_power(pEepData, - freq, i, - is2ghz); + /* + * compare test group from regulatory + * channel list with test mode from pCtlMode + * list + */ + if ((((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((ctlIndex[i] & CTL_MODE_M) | + SD_NO_CTL))) { + twiceMinEdgePower = + ar9003_hw_get_max_edge_power(pEepData, + freq, i, + is2ghz); - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) - /* - * Find the minimum of all CTL - * edge powers that apply to - * this channel - */ - twiceMaxEdgePower = - min(twiceMaxEdgePower, - twiceMinEdgePower); - else { - /* specific */ - twiceMaxEdgePower = - twiceMinEdgePower; - break; - } + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) + /* + * Find the minimum of all CTL + * edge powers that apply to + * this channel + */ + twiceMaxEdgePower = + min(twiceMaxEdgePower, + twiceMinEdgePower); + else { + /* specific */ + twiceMaxEdgePower = twiceMinEdgePower; + break; } } + } - minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); + minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - ath_dbg(common, REGULATORY, - "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n", - ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, - scaledPower, minCtlPower); + ath_dbg(common, REGULATORY, + "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n", + ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, + scaledPower, minCtlPower); - /* Apply ctl mode to correct target power set */ - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = ALL_TARGET_LEGACY_1L_5L; - i <= ALL_TARGET_LEGACY_11S; i++) - pPwrArray[i] = - (u8)min((u16)pPwrArray[i], - minCtlPower); - break; - case CTL_11A: - case CTL_11G: - for (i = ALL_TARGET_LEGACY_6_24; - i <= ALL_TARGET_LEGACY_54; i++) - pPwrArray[i] = - (u8)min((u16)pPwrArray[i], - minCtlPower); - break; - case CTL_5GHT20: - case CTL_2GHT20: - for (i = ALL_TARGET_HT20_0_8_16; - i <= ALL_TARGET_HT20_23; i++) - pPwrArray[i] = - (u8)min((u16)pPwrArray[i], - minCtlPower); - break; - case CTL_5GHT40: - case CTL_2GHT40: - for (i = ALL_TARGET_HT40_0_8_16; - i <= ALL_TARGET_HT40_23; i++) - pPwrArray[i] = - (u8)min((u16)pPwrArray[i], - minCtlPower); - break; - default: - break; - } + /* Apply ctl mode to correct target power set */ + switch (pCtlMode[ctlMode]) { + case CTL_11B: + for (i = ALL_TARGET_LEGACY_1L_5L; + i <= ALL_TARGET_LEGACY_11S; i++) + pPwrArray[i] = (u8)min((u16)pPwrArray[i], + minCtlPower); + break; + case CTL_11A: + case CTL_11G: + for (i = ALL_TARGET_LEGACY_6_24; + i <= ALL_TARGET_LEGACY_54; i++) + pPwrArray[i] = (u8)min((u16)pPwrArray[i], + minCtlPower); + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = ALL_TARGET_HT20_0_8_16; + i <= ALL_TARGET_HT20_23; i++) + pPwrArray[i] = (u8)min((u16)pPwrArray[i], + minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = ALL_TARGET_HT40_0_8_16; + i <= ALL_TARGET_HT40_23; i++) + pPwrArray[i] = (u8)min((u16)pPwrArray[i], + minCtlPower); + break; + default: + break; + } } /* end ctl mode checking */ } From d92a680359ff3230bd1e68ac8f3ac827639f494e Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 3 Aug 2012 18:05:59 -0700 Subject: [PATCH 060/109] mwifiex: copy MSDU subframes correctly All MSDU subframes, except the first one in AMSDU, were being written wrongly at the location of first MSDU frame. Fixing that by copying the MSDU at skb->tail of AMSDU. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index ab84eb943749..c631c7cc85f1 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -62,9 +62,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, }; struct tx_packet_hdr *tx_header; - skb_put(skb_aggr, sizeof(*tx_header)); - - tx_header = (struct tx_packet_hdr *) skb_aggr->data; + tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header)); /* Copy DA and SA */ dt_offset = 2 * ETH_ALEN; @@ -82,9 +80,8 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN); /* Add payload */ - skb_put(skb_aggr, skb_src->len); - memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data, - skb_src->len); + memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len); + *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + LLC_SNAP_LEN)) & 3)) : 0; skb_put(skb_aggr, *pad); From 7d273ef32a0d68f2751f74f7401de78f3c95afa8 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 3 Aug 2012 18:06:00 -0700 Subject: [PATCH 061/109] mwifiex: remove extra padding to AMSDU Since commit: fb3c19bc9687d972b83faf366b38ac807eca8f25, adding extra padding to AMSDU is redundant since same is being performed at mwifiex_11n_aggregate_pkt after forming the AMSDU packet. Fixing it by removing it. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index c631c7cc85f1..04222f27665f 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -84,7 +84,6 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + LLC_SNAP_LEN)) & 3)) : 0; - skb_put(skb_aggr, *pad); return skb_aggr->len + *pad; } From bda1b1b77918ea340bbfb2938a0fd7d5203e430c Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 3 Aug 2012 18:06:01 -0700 Subject: [PATCH 062/109] mwifiex: correction in MSDU padding logic Padding arithmetic will always work for MSDUs provided first MSDU ends on 4-byte boundary. Fixing it by making sure that all MSDU ends on 4-byte boundary. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_aggr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 04222f27665f..395f1bfd4102 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -82,8 +82,8 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, /* Add payload */ memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len); - *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + - LLC_SNAP_LEN)) & 3)) : 0; + /* Add padding for new MSDU to start from 4 byte boundary */ + *pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4; return skb_aggr->len + *pad; } From ed1ea6f42ecedbbb3a8c4e0211ad683b8680eebe Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 3 Aug 2012 18:06:02 -0700 Subject: [PATCH 063/109] mwifiex: do le_to_cpu conversion for Rx packet header elements We do similar conversion for Tx packet header but it was missing for Rx packet header. Without this fix, Rx packet header won't be correctly parsed on big endian platform. Signed-off-by: Amitkumar Karwar Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 8 +++--- drivers/net/wireless/mwifiex/sta_rx.c | 38 +++++++++++++-------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index e831b440a24a..a0222ec1cc38 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -424,10 +424,10 @@ struct txpd { struct rxpd { u8 bss_type; u8 bss_num; - u16 rx_pkt_length; - u16 rx_pkt_offset; - u16 rx_pkt_type; - u16 seq_num; + __le16 rx_pkt_length; + __le16 rx_pkt_offset; + __le16 rx_pkt_type; + __le16 seq_num; u8 priority; u8 rx_rate; s8 snr; diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 02ce3b77d3e7..d91d5c08c73a 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -54,8 +54,8 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, local_rx_pd = (struct rxpd *) (skb->data); - rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + - local_rx_pd->rx_pkt_offset); + rx_pkt_hdr = (void *)local_rx_pd + + le16_to_cpu(local_rx_pd->rx_pkt_offset); if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { @@ -125,7 +125,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); struct rx_packet_hdr *rx_pkt_hdr; u8 ta[ETH_ALEN]; - u16 rx_pkt_type; + u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; struct mwifiex_private *priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num, rx_info->bss_type); @@ -134,16 +134,17 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, return -1; local_rx_pd = (struct rxpd *) (skb->data); - rx_pkt_type = local_rx_pd->rx_pkt_type; + rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); + rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset); + rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length); + seq_num = le16_to_cpu(local_rx_pd->seq_num); - rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + - local_rx_pd->rx_pkt_offset); + rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; - if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) > - (u16) skb->len) { - dev_err(adapter->dev, "wrong rx packet: len=%d," - " rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, - local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length); + if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { + dev_err(adapter->dev, + "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", + skb->len, rx_pkt_offset, rx_pkt_length); priv->stats.rx_dropped++; if (adapter->if_ops.data_complete) @@ -154,14 +155,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, return ret; } - if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { + if (rx_pkt_type == PKT_TYPE_AMSDU) { struct sk_buff_head list; struct sk_buff *rx_skb; __skb_queue_head_init(&list); - skb_pull(skb, local_rx_pd->rx_pkt_offset); - skb_trim(skb, local_rx_pd->rx_pkt_length); + skb_pull(skb, rx_pkt_offset); + skb_trim(skb, rx_pkt_length); ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, priv->wdev->iftype, 0, false); @@ -189,17 +190,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); } else { if (rx_pkt_type != PKT_TYPE_BAR) - priv->rx_seq[local_rx_pd->priority] = - local_rx_pd->seq_num; + priv->rx_seq[local_rx_pd->priority] = seq_num; memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); } /* Reorder and send to OS */ - ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num, - local_rx_pd->priority, ta, - (u8) local_rx_pd->rx_pkt_type, - skb); + ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, + ta, (u8) rx_pkt_type, skb); if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { if (adapter->if_ops.data_complete) From b7525dbd075414ab2dc3742bacdc386f0f1223b2 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 3 Aug 2012 18:06:03 -0700 Subject: [PATCH 064/109] mwifiex: update max_chan_per_scan correctly for SSID scan As per recent patch "658f37b mwifiex: scan less channels..." less channels are scanned per scan command in associated state. Default number of channels per scan command for normal scan are already 4, but those are 14 for SSID specific scan operation. This code change in this patch is required for SSID specific scan. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 04dc7ca4ac22..3035412a0498 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -989,6 +989,8 @@ mwifiex_config_scan(struct mwifiex_private *priv, *max_chan_per_scan = 2; else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD) *max_chan_per_scan = 3; + else + *max_chan_per_scan = 4; } } From bdd37bed619b2445b2a04f398a7fe34b1e416172 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 3 Aug 2012 18:06:04 -0700 Subject: [PATCH 065/109] mwifiex: improve scan delay logic during Tx traffic Earlier scan command was postponed by 20msec multiple times to give preference to Tx traffic until we find empty wmm queue. There is a corner case in which wmm queue becomes empty immediately after processing the packet(before 20msec) and there may be next packet coming after some time. In this case we should not resume scan operation. We will use new flag to check Tx traffic and resume scan operation only if there is no traffic for 200msec. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 103 ++++++++++++++++------------ drivers/net/wireless/mwifiex/main.c | 3 + drivers/net/wireless/mwifiex/main.h | 3 + 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 21fdc6c02775..81fc8ed0e976 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -64,60 +64,72 @@ static void scan_delay_timer_fn(unsigned long data) struct cmd_ctrl_node *cmd_node, *tmp_node; unsigned long flags; - if (!mwifiex_wmm_lists_empty(adapter)) { - if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { + if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { + /* + * Abort scan operation by cancelling all pending scan + * commands + */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + cmd_node->wait_q_enabled = false; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = false; + adapter->scan_delay_cnt = 0; + adapter->empty_tx_q_cnt = 0; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + if (priv->user_scan_cfg) { + dev_dbg(priv->adapter->dev, + "info: %s: scan aborted\n", __func__); + cfg80211_scan_done(priv->scan_request, 1); + priv->scan_request = NULL; + kfree(priv->user_scan_cfg); + priv->user_scan_cfg = NULL; + } + goto done; + } + + if (!atomic_read(&priv->adapter->is_tx_received)) { + adapter->empty_tx_q_cnt++; + if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { /* - * Abort scan operation by cancelling all pending scan - * command + * No Tx traffic for 200msec. Get scan command from + * scan pending queue and put to cmd pending queue to + * resume scan operation */ + adapter->scan_delay_cnt = 0; + adapter->empty_tx_q_cnt = 0; spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, - list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } + cmd_node = list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, - flags); - - if (priv->user_scan_cfg) { - dev_dbg(priv->adapter->dev, - "info: %s: scan aborted\n", __func__); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - kfree(priv->user_scan_cfg); - priv->user_scan_cfg = NULL; - } - } else { - /* - * Tx data queue is still not empty, delay scan - * operation further by 20msec. - */ - mod_timer(&priv->scan_delay_timer, jiffies + - msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); - adapter->scan_delay_cnt++; + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, + true); + goto done; } - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); } else { - /* - * Tx data queue is empty. Get scan command from scan_pending_q - * and put to cmd_pending_q to resume scan operation - */ - adapter->scan_delay_cnt = 0; - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); + adapter->empty_tx_q_cnt = 0; } + + /* Delay scan operation further by 20msec */ + mod_timer(&priv->scan_delay_timer, jiffies + + msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); + adapter->scan_delay_cnt++; + +done: + if (atomic_read(&priv->adapter->is_tx_received)) + atomic_set(&priv->adapter->is_tx_received, false); + + return; } /* @@ -345,6 +357,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); adapter->arp_filter_size = 0; adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; + adapter->empty_tx_q_cnt = 0; } /* diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 46803621d015..cb1155286e0f 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -520,6 +520,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) mwifiex_wmm_add_buf_txqueue(priv, skb); atomic_inc(&priv->adapter->tx_pending); + if (priv->adapter->scan_delay_cnt) + atomic_set(&priv->adapter->is_tx_received, true); + if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { mwifiex_set_trans_start(dev); mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index e7c2a82fd610..16f046a556b5 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -88,6 +88,7 @@ enum { #define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) #define MWIFIEX_MAX_SCAN_DELAY_CNT 50 +#define MWIFIEX_MAX_EMPTY_TX_Q_CNT 10 #define MWIFIEX_SCAN_DELAY_MSEC 20 #define RSN_GTK_OUI_OFFSET 2 @@ -690,6 +691,8 @@ struct mwifiex_adapter { u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; u16 max_mgmt_ie_index; u8 scan_delay_cnt; + u8 empty_tx_q_cnt; + atomic_t is_tx_received; }; int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); From c82589131840767443f32f6d235a825cbef7b914 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:05 -0700 Subject: [PATCH 066/109] mwifiex: update 11n status as per start_ap IE If HT IE is present in beacon_data of start_ap cfg80211 handler, enable 11n flag in AP. Disable 11n flag when stop_ap handler is called. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 2 ++ drivers/net/wireless/mwifiex/init.c | 1 + drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/uap_cmd.c | 1 + 4 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index fe42137384da..1f80f7e13ba8 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -906,6 +906,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) if (mwifiex_del_mgmt_ies(priv)) wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); + priv->ap_11n_enabled = 0; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, HostCmd_ACT_GEN_SET, 0, NULL)) { wiphy_err(wiphy, "Failed to stop the BSS\n"); diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 81fc8ed0e976..118a29f6e240 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -208,6 +208,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->curr_bcn_size = 0; priv->wps_ie = NULL; priv->wps_ie_len = 0; + priv->ap_11n_enabled = 0; priv->scan_block = false; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 16f046a556b5..5eeb17c3db00 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -487,6 +487,7 @@ struct mwifiex_private { u16 assocresp_idx; u16 rsn_idx; struct timer_list scan_delay_timer; + u8 ap_11n_enabled; }; enum mwifiex_ba_status { diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index f40e93fe894a..c10aac04be6a 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -167,6 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, if (ht_ie) { memcpy(&bss_cfg->ht_cap, ht_ie + 2, sizeof(struct ieee80211_ht_cap)); + priv->ap_11n_enabled = 1; } else { memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); From 3d99d9877dabc6468c3df1c990d436bd221b5089 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:06 -0700 Subject: [PATCH 067/109] mwifiex: separate file for handling AP events Route AP events handling to separate function defined in uap_event.c. AP specific event handling is removed from sta_event.c. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/Makefile | 1 + drivers/net/wireless/mwifiex/cmdevt.c | 5 +- drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_event.c | 49 +---------- drivers/net/wireless/mwifiex/uap_event.c | 100 +++++++++++++++++++++++ 5 files changed, 107 insertions(+), 49 deletions(-) create mode 100644 drivers/net/wireless/mwifiex/uap_event.c diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 3f66ebb0a630..20932f24dc23 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile @@ -33,6 +33,7 @@ mwifiex-y += uap_cmd.o mwifiex-y += ie.o mwifiex-y += sta_cmdresp.o mwifiex-y += sta_event.o +mwifiex-y += uap_event.o mwifiex-y += sta_tx.o mwifiex-y += sta_rx.o mwifiex-y += cfg80211.o diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8b..c229dddcf1c2 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -447,7 +447,10 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); } - ret = mwifiex_process_sta_event(priv); + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + ret = mwifiex_process_uap_event(priv); + else + ret = mwifiex_process_sta_event(priv); adapter->event_cause = 0; adapter->event_skb = NULL; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 5eeb17c3db00..cac0c2d64b0f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -785,6 +785,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, struct sk_buff *skb); int mwifiex_process_sta_event(struct mwifiex_private *); +int mwifiex_process_uap_event(struct mwifiex_private *); void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index b8614a825460..2aad148db5c3 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -184,10 +184,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) int mwifiex_process_sta_event(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; - int len, ret = 0; + int ret = 0; u32 eventcause = adapter->event_cause; - struct station_info sinfo; - struct mwifiex_assoc_event *event; switch (eventcause) { case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: @@ -405,51 +403,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); break; - case EVENT_UAP_STA_ASSOC: - memset(&sinfo, 0, sizeof(sinfo)); - event = (struct mwifiex_assoc_event *) - (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER); - if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { - len = -1; - - if (ieee80211_is_assoc_req(event->frame_control)) - len = 0; - else if (ieee80211_is_reassoc_req(event->frame_control)) - /* There will be ETH_ALEN bytes of - * current_ap_addr before the re-assoc ies. - */ - len = ETH_ALEN; - - if (len != -1) { - sinfo.filled = STATION_INFO_ASSOC_REQ_IES; - sinfo.assoc_req_ies = &event->data[len]; - len = (u8 *)sinfo.assoc_req_ies - - (u8 *)&event->frame_control; - sinfo.assoc_req_ies_len = - le16_to_cpu(event->len) - (u16)len; - } - } - cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, - GFP_KERNEL); - break; - case EVENT_UAP_STA_DEAUTH: - cfg80211_del_sta(priv->netdev, adapter->event_body + - MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL); - break; - case EVENT_UAP_BSS_IDLE: - priv->media_connected = false; - break; - case EVENT_UAP_BSS_ACTIVE: - priv->media_connected = true; - break; - case EVENT_UAP_BSS_START: - dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); - memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN); - break; - case EVENT_UAP_MIC_COUNTERMEASURES: - /* For future development */ - dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); - break; default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c new file mode 100644 index 000000000000..5af60d8ac13e --- /dev/null +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -0,0 +1,100 @@ +/* + * Marvell Wireless LAN device driver: AP event handling + * + * Copyright (C) 2012, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "main.h" + +/* + * This function handles AP interface specific events generated by firmware. + * + * Event specific routines are called by this function based + * upon the generated event cause. + * + * + * Events supported for AP - + * - EVENT_UAP_STA_ASSOC + * - EVENT_UAP_STA_DEAUTH + * - EVENT_UAP_BSS_ACTIVE + * - EVENT_UAP_BSS_START + * - EVENT_UAP_BSS_IDLE + * - EVENT_UAP_MIC_COUNTERMEASURES: + */ +int mwifiex_process_uap_event(struct mwifiex_private *priv) +{ + struct mwifiex_adapter *adapter = priv->adapter; + int len; + u32 eventcause = adapter->event_cause; + struct station_info sinfo; + struct mwifiex_assoc_event *event; + + switch (eventcause) { + case EVENT_UAP_STA_ASSOC: + memset(&sinfo, 0, sizeof(sinfo)); + event = (struct mwifiex_assoc_event *) + (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER); + if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { + len = -1; + + if (ieee80211_is_assoc_req(event->frame_control)) + len = 0; + else if (ieee80211_is_reassoc_req(event->frame_control)) + /* There will be ETH_ALEN bytes of + * current_ap_addr before the re-assoc ies. + */ + len = ETH_ALEN; + + if (len != -1) { + sinfo.filled = STATION_INFO_ASSOC_REQ_IES; + sinfo.assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo.assoc_req_ies - + (u8 *)&event->frame_control; + sinfo.assoc_req_ies_len = + le16_to_cpu(event->len) - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, + GFP_KERNEL); + break; + case EVENT_UAP_STA_DEAUTH: + cfg80211_del_sta(priv->netdev, adapter->event_body + + MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL); + break; + case EVENT_UAP_BSS_IDLE: + priv->media_connected = false; + break; + case EVENT_UAP_BSS_ACTIVE: + priv->media_connected = true; + break; + case EVENT_UAP_BSS_START: + dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); + memcpy(priv->netdev->dev_addr, adapter->event_body + 2, + ETH_ALEN); + break; + case EVENT_UAP_MIC_COUNTERMEASURES: + /* For future development */ + dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); + break; + default: + dev_dbg(adapter->dev, "event: unknown event id: %#x\n", + eventcause); + break; + } + + return 0; +} From 017a92a15a119be3b751456cb04791282721c661 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:07 -0700 Subject: [PATCH 068/109] mwifiex: create list for associated stations in AP mode After station is associated an entry would be added to station list. This entry would have station specific information such as 11n support, AMSDU size. The entry would be deleted after deauthentication. All station entries would be deleted during BSS_IDLE event. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 3 + drivers/net/wireless/mwifiex/main.h | 19 +++ drivers/net/wireless/mwifiex/uap_event.c | 158 ++++++++++++++++++++++- 3 files changed, 177 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 118a29f6e240..fad2c8d2bdde 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -424,6 +424,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); list_del(&priv->tx_ba_stream_tbl_ptr); list_del(&priv->rx_reorder_tbl_ptr); + list_del(&priv->sta_list); } } } @@ -486,6 +487,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) spin_lock_init(&priv->rx_pkt_lock); spin_lock_init(&priv->wmm.ra_list_spinlock); spin_lock_init(&priv->curr_bcn_buf_lock); + spin_lock_init(&priv->sta_list_spinlock); } } @@ -518,6 +520,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) } INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); + INIT_LIST_HEAD(&priv->sta_list); spin_lock_init(&priv->tx_ba_stream_tbl_lock); spin_lock_init(&priv->rx_reorder_tbl_lock); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index cac0c2d64b0f..9a0174d06460 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -432,6 +432,9 @@ struct mwifiex_private { u8 wmm_enabled; u8 wmm_qosinfo; struct mwifiex_wmm_desc wmm; + struct list_head sta_list; + /* spin lock for associated station list */ + spinlock_t sta_list_spinlock; struct list_head tx_ba_stream_tbl_ptr; /* spin lock for tx_ba_stream_tbl_ptr queue */ spinlock_t tx_ba_stream_tbl_lock; @@ -552,6 +555,19 @@ struct mwifiex_bss_priv { u64 fw_tsf; }; +/* This is AP specific structure which stores information + * about associated STA + */ +struct mwifiex_sta_node { + struct list_head list; + u8 mac_addr[ETH_ALEN]; + u8 is_wmm_enabled; + u8 is_11n_enabled; + u8 ampdu_sta[MAX_NUM_TID]; + u16 rx_seq[MAX_NUM_TID]; + u16 max_amsdu; +}; + struct mwifiex_if_ops { int (*init_if) (struct mwifiex_adapter *); void (*cleanup_if) (struct mwifiex_adapter *); @@ -786,6 +802,9 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, struct sk_buff *skb); int mwifiex_process_sta_event(struct mwifiex_private *); int mwifiex_process_uap_event(struct mwifiex_private *); +struct mwifiex_sta_node * +mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); +void mwifiex_delete_all_station_list(struct mwifiex_private *priv); void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 5af60d8ac13e..37cc642a1b83 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -20,6 +20,130 @@ #include "decl.h" #include "main.h" +/* + * This function will return the pointer to station entry in station list + * table which matches specified mac address. + * This function should be called after acquiring RA list spinlock. + * NULL is returned if station entry is not found in associated STA list. + */ +struct mwifiex_sta_node * +mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) +{ + struct mwifiex_sta_node *node; + + if (!mac) + return NULL; + + list_for_each_entry(node, &priv->sta_list, list) { + if (!memcmp(node->mac_addr, mac, ETH_ALEN)) + return node; + } + + return NULL; +} + +/* + * This function will add a sta_node entry to associated station list + * table with the given mac address. + * If entry exist already, existing entry is returned. + * If received mac address is NULL, NULL is returned. + */ +static struct mwifiex_sta_node * +mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) +{ + struct mwifiex_sta_node *node; + unsigned long flags; + + if (!mac) + return NULL; + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + node = mwifiex_get_sta_entry(priv, mac); + if (node) + goto done; + + node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_KERNEL); + if (!node) + goto done; + + memcpy(node->mac_addr, mac, ETH_ALEN); + list_add_tail(&node->list, &priv->sta_list); + +done: + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + return node; +} + +/* + * This function will search for HT IE in association request IEs + * and set station HT parameters accordingly. + */ +static void +mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, + int ies_len, struct mwifiex_sta_node *node) +{ + const struct ieee80211_ht_cap *ht_cap; + + if (!ies) + return; + + ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len); + if (ht_cap) { + node->is_11n_enabled = 1; + node->max_amsdu = le16_to_cpu(ht_cap->cap_info) & + IEEE80211_HT_CAP_MAX_AMSDU ? + MWIFIEX_TX_DATA_BUF_SIZE_8K : + MWIFIEX_TX_DATA_BUF_SIZE_4K; + } else { + node->is_11n_enabled = 0; + } + + return; +} + +/* + * This function will delete a station entry from station list + */ +static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) +{ + struct mwifiex_sta_node *node, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + + node = mwifiex_get_sta_entry(priv, mac); + if (node) { + list_for_each_entry_safe(node, tmp, &priv->sta_list, + list) { + list_del(&node->list); + kfree(node); + } + } + + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + return; +} + +/* + * This function will delete all stations from associated station list. + */ +static void mwifiex_del_all_sta_list(struct mwifiex_private *priv) +{ + struct mwifiex_sta_node *node, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + + list_for_each_entry_safe(node, tmp, &priv->sta_list, list) { + list_del(&node->list); + kfree(node); + } + + INIT_LIST_HEAD(&priv->sta_list); + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + return; +} + /* * This function handles AP interface specific events generated by firmware. * @@ -38,10 +162,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) { struct mwifiex_adapter *adapter = priv->adapter; - int len; + int len, i; u32 eventcause = adapter->event_cause; struct station_info sinfo; struct mwifiex_assoc_event *event; + struct mwifiex_sta_node *node; + u8 *deauth_mac; switch (eventcause) { case EVENT_UAP_STA_ASSOC: @@ -70,13 +196,39 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) } cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, GFP_KERNEL); + + node = mwifiex_add_sta_entry(priv, event->sta_addr); + if (!node) { + dev_warn(adapter->dev, + "could not create station entry!\n"); + return -1; + } + + if (!priv->ap_11n_enabled) + break; + + mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies, + sinfo.assoc_req_ies_len, node); + + for (i = 0; i < MAX_NUM_TID; i++) { + if (node->is_11n_enabled) + node->ampdu_sta[i] = + priv->aggr_prio_tbl[i].ampdu_user; + else + node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; + } + memset(node->rx_seq, 0xff, sizeof(node->rx_seq)); break; case EVENT_UAP_STA_DEAUTH: - cfg80211_del_sta(priv->netdev, adapter->event_body + - MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL); + deauth_mac = adapter->event_body + + MWIFIEX_UAP_EVENT_EXTRA_HEADER; + cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); + + mwifiex_del_sta_entry(priv, deauth_mac); break; case EVENT_UAP_BSS_IDLE: priv->media_connected = false; + mwifiex_del_all_sta_list(priv); break; case EVENT_UAP_BSS_ACTIVE: priv->media_connected = true; From 838e4f44929782a2163c7bc95a7cd2da5d8b47f9 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:08 -0700 Subject: [PATCH 069/109] mwifiex: improve uAP RX handling 1. Separate file for uAP RX handling. 2. If received packet is broadcast/multicast, send it to kernel as well as requeue it back to uAP TX queue. 3. If received packet is for associated STA (intra-BSS), requeue it back to uAP TX queue. 4. In all other cases (packets for AP or inter-BSS packets), pass packet to kernel to handle it accordingly. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/Makefile | 1 + drivers/net/wireless/mwifiex/decl.h | 3 + drivers/net/wireless/mwifiex/fw.h | 25 +++ drivers/net/wireless/mwifiex/main.h | 5 + drivers/net/wireless/mwifiex/txrx.c | 5 + drivers/net/wireless/mwifiex/uap_txrx.c | 205 ++++++++++++++++++++++++ 6 files changed, 244 insertions(+) create mode 100644 drivers/net/wireless/mwifiex/uap_txrx.c diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 20932f24dc23..dd0410d2d465 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile @@ -36,6 +36,7 @@ mwifiex-y += sta_event.o mwifiex-y += uap_event.o mwifiex-y += sta_tx.o mwifiex-y += sta_rx.o +mwifiex-y += uap_txrx.o mwifiex-y += cfg80211.o mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o obj-$(CONFIG_MWIFIEX) += mwifiex.o diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 070ef25f5186..400d360ac91f 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -60,6 +60,9 @@ #define MWIFIEX_SDIO_BLOCK_SIZE 256 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) +#define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1) + +#define MWIFIEX_BRIDGED_PKTS_THRESHOLD 1024 enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index a0222ec1cc38..1c1274d8d789 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -439,6 +439,31 @@ struct rxpd { u8 reserved; } __packed; +struct uap_txpd { + u8 bss_type; + u8 bss_num; + __le16 tx_pkt_length; + __le16 tx_pkt_offset; + __le16 tx_pkt_type; + __le32 tx_control; + u8 priority; + u8 flags; + u8 pkt_delay_2ms; + u8 reserved1; + __le32 reserved2; +}; + +struct uap_rxpd { + u8 bss_type; + u8 bss_num; + __le16 rx_pkt_length; + __le16 rx_pkt_offset; + __le16 rx_pkt_type; + __le16 seq_num; + u8 priority; + u8 reserved1; +}; + enum mwifiex_chan_scan_mode_bitmasks { MWIFIEX_PASSIVE_SCAN = BIT(0), MWIFIEX_DISABLE_CHAN_FILT = BIT(1), diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 9a0174d06460..014fe9ab221f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -710,6 +710,7 @@ struct mwifiex_adapter { u8 scan_delay_cnt; u8 empty_tx_q_cnt; atomic_t is_tx_received; + atomic_t pending_bridged_pkts; }; int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); @@ -800,6 +801,10 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, struct host_cmd_ds_command *resp); int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, struct sk_buff *skb); +int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb); +int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, + struct sk_buff *skb); int mwifiex_process_sta_event(struct mwifiex_private *); int mwifiex_process_uap_event(struct mwifiex_private *); struct mwifiex_sta_node * diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index cecb27283196..985073d0df1a 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -51,6 +51,9 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, rx_info->bss_num = priv->bss_num; rx_info->bss_type = priv->bss_type; + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + return mwifiex_process_uap_rx_packet(adapter, skb); + return mwifiex_process_sta_rx_packet(adapter, skb); } EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); @@ -157,6 +160,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, priv->stats.tx_errors++; } + if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) + atomic_dec_return(&adapter->pending_bridged_pkts); if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING) goto done; diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c new file mode 100644 index 000000000000..f55c5ac3e5e0 --- /dev/null +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -0,0 +1,205 @@ +/* + * Marvell Wireless LAN device driver: AP TX and RX data handling + * + * Copyright (C) 2012, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "decl.h" +#include "ioctl.h" +#include "main.h" +#include "wmm.h" + +static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct uap_rxpd *uap_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + struct sk_buff *new_skb; + struct mwifiex_txinfo *tx_info; + int hdr_chop; + struct timeval tv; + u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + + uap_rx_pd = (struct uap_rxpd *)(skb->data); + rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + if ((atomic_read(&adapter->pending_bridged_pkts) >= + MWIFIEX_BRIDGED_PKTS_THRESHOLD)) { + dev_err(priv->adapter->dev, + "Tx: Bridge packet limit reached. Drop packet!\n"); + kfree_skb(skb); + return; + } + + if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, + rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) + /* Chop off the rxpd + the excess memory from + * 802.2/llc/snap header that was removed. + */ + hdr_chop = (u8 *)eth_hdr - (u8 *)uap_rx_pd; + else + /* Chop off the rxpd */ + hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd; + + /* Chop off the leading header bytes so the it points + * to the start of either the reconstructed EthII frame + * or the 802.2/llc/snap frame. + */ + skb_pull(skb, hdr_chop); + + if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { + dev_dbg(priv->adapter->dev, + "data: Tx: insufficient skb headroom %d\n", + skb_headroom(skb)); + /* Insufficient skb headroom - allocate a new skb */ + new_skb = + skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); + if (unlikely(!new_skb)) { + dev_err(priv->adapter->dev, + "Tx: cannot allocate new_skb\n"); + kfree_skb(skb); + priv->stats.tx_dropped++; + return; + } + + kfree_skb(skb); + skb = new_skb; + dev_dbg(priv->adapter->dev, "info: new skb headroom %d\n", + skb_headroom(skb)); + } + + tx_info = MWIFIEX_SKB_TXCB(skb); + tx_info->bss_num = priv->bss_num; + tx_info->bss_type = priv->bss_type; + tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; + + do_gettimeofday(&tv); + skb->tstamp = timeval_to_ktime(tv); + mwifiex_wmm_add_buf_txqueue(priv, skb); + atomic_inc(&adapter->tx_pending); + atomic_inc(&adapter->pending_bridged_pkts); + + if ((atomic_read(&adapter->tx_pending) >= MAX_TX_PENDING)) { + mwifiex_set_trans_start(priv->netdev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + } + return; +} + +/* + * This function contains logic for AP packet forwarding. + * + * If a packet is multicast/broadcast, it is sent to kernel/upper layer + * as well as queued back to AP TX queue so that it can be sent to other + * associated stations. + * If a packet is unicast and RA is present in associated station list, + * it is again requeued into AP TX queue. + * If a packet is unicast and RA is not in associated station list, + * packet is forwarded to kernel to handle routing logic. + */ +int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct uap_rxpd *uap_rx_pd; + struct rx_packet_hdr *rx_pkt_hdr; + u8 ra[ETH_ALEN]; + struct sk_buff *skb_uap; + + uap_rx_pd = (struct uap_rxpd *)(skb->data); + rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + /* don't do packet forwarding in disconnected state */ + if (!priv->media_connected) { + dev_err(adapter->dev, "drop packet in disconnected state.\n"); + dev_kfree_skb_any(skb); + return 0; + } + + memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN); + + if (is_multicast_ether_addr(ra)) { + skb_uap = skb_copy(skb, GFP_ATOMIC); + mwifiex_uap_queue_bridged_pkt(priv, skb_uap); + } else { + if (mwifiex_get_sta_entry(priv, ra)) { + /* Requeue Intra-BSS packet */ + mwifiex_uap_queue_bridged_pkt(priv, skb); + return 0; + } + } + + /* Forward unicat/Inter-BSS packets to kernel. */ + return mwifiex_process_rx_packet(adapter, skb); +} + +/* + * This function processes the packet received on AP interface. + * + * The function looks into the RxPD and performs sanity tests on the + * received buffer to ensure its a valid packet before processing it + * further. If the packet is determined to be aggregated, it is + * de-aggregated accordingly. Then skb is passed to AP packet forwarding logic. + * + * The completion callback is called after processing is complete. + */ +int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + int ret; + struct uap_rxpd *uap_rx_pd; + struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); + struct rx_packet_hdr *rx_pkt_hdr; + u16 rx_pkt_type; + struct mwifiex_private *priv = + mwifiex_get_priv_by_id(adapter, rx_info->bss_num, + rx_info->bss_type); + + if (!priv) + return -1; + + uap_rx_pd = (struct uap_rxpd *)(skb->data); + rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); + rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + + if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + + le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) { + dev_err(adapter->dev, + "wrong rx packet: len=%d, offset=%d, length=%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), + le16_to_cpu(uap_rx_pd->rx_pkt_length)); + priv->stats.rx_dropped++; + + if (adapter->if_ops.data_complete) + adapter->if_ops.data_complete(adapter, skb); + else + dev_kfree_skb_any(skb); + + return 0; + } + ret = mwifiex_handle_uap_rx_forward(priv, skb); + + if (ret) { + priv->stats.rx_dropped++; + if (adapter->if_ops.data_complete) + adapter->if_ops.data_complete(adapter, skb); + else + dev_kfree_skb_any(skb); + } + + return ret; +} From d1cf3b958cb6940cb4e0a71697458035dad9e5b9 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:09 -0700 Subject: [PATCH 070/109] mwifiex: support RX AMSDU aggregation for uAP This patch adds support for reception and decoding of AMSDU aggregation frames for AP interface. Patch also adds support for handling AMSDU aggregation event. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_rxreorder.c | 26 ++++++--- drivers/net/wireless/mwifiex/11n_rxreorder.h | 2 + drivers/net/wireless/mwifiex/uap_event.c | 13 +++++ drivers/net/wireless/mwifiex/uap_txrx.c | 56 ++++++++++++++++++-- 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 591ccd33f83c..20367fe1de44 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, tbl->rx_reorder_ptr[i] = NULL; } spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - if (rx_tmp_ptr) - mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); + if (rx_tmp_ptr) { + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); + else + mwifiex_process_rx_packet(priv->adapter, + rx_tmp_ptr); + } } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, rx_tmp_ptr = tbl->rx_reorder_ptr[i]; tbl->rx_reorder_ptr[i] = NULL; spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); + + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); + else + mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, * This function returns the pointer to an entry in Rx reordering * table which matches the given TA/TID pair. */ -static struct mwifiex_rx_reorder_tbl * +struct mwifiex_rx_reorder_tbl * mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) { struct mwifiex_rx_reorder_tbl *tbl; @@ -396,8 +405,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); if (!tbl) { - if (pkt_type != PKT_TYPE_BAR) - mwifiex_process_rx_packet(priv->adapter, payload); + if (pkt_type != PKT_TYPE_BAR) { + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + mwifiex_handle_uap_rx_forward(priv, payload); + else + mwifiex_process_rx_packet(priv->adapter, + payload); + } return 0; } start_win = tbl->start_win; diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 6c9815a0f5d8..1cd51d86fa57 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -68,5 +68,7 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); +struct mwifiex_rx_reorder_tbl * +mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); #endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 37cc642a1b83..6270c809130a 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -242,6 +242,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) /* For future development */ dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); break; + case EVENT_AMSDU_AGGR_CTRL: + dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", + *(u16 *)adapter->event_body); + + if (priv->media_connected) { + adapter->tx_buf_size = + min(adapter->curr_tx_buf_size, + le16_to_cpu(*(__le16 *)adapter->event_body)); + + dev_dbg(adapter->dev, "event: tx_buf_size %d\n", + adapter->tx_buf_size); + } + break; default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index f55c5ac3e5e0..6d814f0f07f2 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -21,6 +21,8 @@ #include "ioctl.h" #include "main.h" #include "wmm.h" +#include "11n_aggr.h" +#include "11n_rxreorder.h" static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, struct sk_buff *skb) @@ -165,6 +167,9 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); struct rx_packet_hdr *rx_pkt_hdr; u16 rx_pkt_type; + u8 ta[ETH_ALEN], pkt_type; + struct mwifiex_sta_node *node; + struct mwifiex_private *priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num, rx_info->bss_type); @@ -191,15 +196,60 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, return 0; } - ret = mwifiex_handle_uap_rx_forward(priv, skb); - if (ret) { - priv->stats.rx_dropped++; + if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { + struct sk_buff_head list; + struct sk_buff *rx_skb; + + __skb_queue_head_init(&list); + skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length)); + + ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, + priv->wdev->iftype, 0, false); + + while (!skb_queue_empty(&list)) { + rx_skb = __skb_dequeue(&list); + ret = mwifiex_recv_packet(adapter, rx_skb); + if (ret) + dev_err(adapter->dev, + "AP:Rx A-MSDU failed"); + } + + return 0; + } + + memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); + + if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) { + node = mwifiex_get_sta_entry(priv, ta); + if (node) + node->rx_seq[uap_rx_pd->priority] = + le16_to_cpu(uap_rx_pd->seq_num); + } + + if (!priv->ap_11n_enabled || + (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) && + (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) { + ret = mwifiex_handle_uap_rx_forward(priv, skb); + return ret; + } + + /* Reorder and send to kernel */ + pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type); + ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num), + uap_rx_pd->priority, ta, pkt_type, + skb); + + if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { if (adapter->if_ops.data_complete) adapter->if_ops.data_complete(adapter, skb); else dev_kfree_skb_any(skb); } + if (ret) + priv->stats.rx_dropped++; + return ret; } From 5a009adf32d28bacc02da2ddeb69765848266ce1 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:10 -0700 Subject: [PATCH 071/109] mwifiex: add 11n Block Ack support for uAP This patch adds support for handling BA request and BA setup events for AP interface. RA list is marked as either 11n enabled or disabled from station's capabilities in association request. BA setup is initiated only after some specific number of packets for particular RA list are transmitted. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.h | 14 +++++ drivers/net/wireless/mwifiex/11n_rxreorder.c | 15 +++-- drivers/net/wireless/mwifiex/11n_rxreorder.h | 2 + drivers/net/wireless/mwifiex/main.h | 3 + drivers/net/wireless/mwifiex/uap_event.c | 21 +++++++ drivers/net/wireless/mwifiex/wmm.c | 59 ++++++++++++++++++-- 6 files changed, 105 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 28366e9211fb..6d2edb4c2ad2 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -157,4 +157,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, return false; } + +/* + * This function checks whether associated station is 11n enabled + */ +static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, + struct mwifiex_sta_node *node) +{ + + if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) || + !priv->ap_11n_enabled) + return 0; + + return node->is_11n_enabled; +} #endif /* !_MWIFIEX_11N_H_ */ diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 20367fe1de44..e43d27dc06bf 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -235,6 +235,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, struct mwifiex_rx_reorder_tbl *tbl, *new_node; u16 last_seq = 0; unsigned long flags; + struct mwifiex_sta_node *node; /* * If we get a TID, ta pair which is already present dispatch all the @@ -257,13 +258,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, new_node->tid = tid; memcpy(new_node->ta, ta, ETH_ALEN); new_node->start_win = seq_num; - if (mwifiex_queuing_ra_based(priv)) - /* TODO for adhoc */ + + if (mwifiex_queuing_ra_based(priv)) { dev_dbg(priv->adapter->dev, - "info: ADHOC:last_seq=%d start_win=%d\n", + "info: AP/ADHOC:last_seq=%d start_win=%d\n", last_seq, new_node->start_win); - else + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { + node = mwifiex_get_sta_entry(priv, ta); + if (node) + last_seq = node->rx_seq[tid]; + } + } else { last_seq = priv->rx_seq[tid]; + } if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && last_seq >= new_node->start_win) diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 1cd51d86fa57..13ecb6101e23 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -38,6 +38,8 @@ #define ADDBA_RSP_STATUS_ACCEPT 0 #define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff +#define BA_SETUP_MAX_PACKET_THRESHOLD 16 +#define BA_SETUP_PACKET_OFFSET 16 static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) { diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 014fe9ab221f..c39cd8e50f9f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -200,6 +200,9 @@ struct mwifiex_ra_list_tbl { u8 ra[ETH_ALEN]; u32 total_pkts_size; u32 is_11n_enabled; + u16 max_amsdu; + u16 pkt_count; + u8 ba_packet_thr; }; struct mwifiex_tid_tbl { diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 6270c809130a..a10bd95aec12 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -19,6 +19,7 @@ #include "decl.h" #include "main.h" +#include "11n.h" /* * This function will return the pointer to station entry in station list @@ -168,6 +169,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) struct mwifiex_assoc_event *event; struct mwifiex_sta_node *node; u8 *deauth_mac; + struct host_cmd_ds_11n_batimeout *ba_timeout; switch (eventcause) { case EVENT_UAP_STA_ASSOC: @@ -255,6 +257,25 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) adapter->tx_buf_size); } break; + case EVENT_ADDBA: + dev_dbg(adapter->dev, "event: ADDBA Request\n"); + if (priv->media_connected) + mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, + HostCmd_ACT_GEN_SET, 0, + adapter->event_body); + break; + case EVENT_DELBA: + dev_dbg(adapter->dev, "event: DELBA Request\n"); + if (priv->media_connected) + mwifiex_11n_delete_ba_stream(priv, adapter->event_body); + break; + case EVENT_BA_STREAM_TIEMOUT: + dev_dbg(adapter->dev, "event: BA Stream timeout\n"); + if (priv->media_connected) { + ba_timeout = (void *)adapter->event_body; + mwifiex_11n_ba_stream_timeout(priv, ba_timeout); + } + break; default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 3fa4d4176993..8ccd6999fa9f 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) return ra_list; } +/* This function returns random no between 16 and 32 to be used as threshold + * for no of packets after which BA setup is initiated. + */ +static u8 mwifiex_get_random_ba_threshold(void) +{ + u32 sec, usec; + struct timeval ba_tstamp; + u8 ba_threshold; + + /* setup ba_packet_threshold here random number between + * [BA_SETUP_PACKET_OFFSET, + * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] + */ + + do_gettimeofday(&ba_tstamp); + sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16); + usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16); + ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) + + BA_SETUP_PACKET_OFFSET; + + return ba_threshold; +} + /* * This function allocates and adds a RA list for all TIDs * with the given RA. @@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) int i; struct mwifiex_ra_list_tbl *ra_list; struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_sta_node *node; + unsigned long flags; + + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + node = mwifiex_get_sta_entry(priv, ra); + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); for (i = 0; i < MAX_NUM_TID; ++i) { ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); @@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) if (!ra_list) break; - if (!mwifiex_queuing_ra_based(priv)) + ra_list->is_11n_enabled = 0; + if (!mwifiex_queuing_ra_based(priv)) { ra_list->is_11n_enabled = IS_11N_ENABLED(priv); - else - ra_list->is_11n_enabled = false; + } else { + ra_list->is_11n_enabled = + mwifiex_is_sta_11n_enabled(priv, node); + if (ra_list->is_11n_enabled) + ra_list->max_amsdu = node->max_amsdu; + } dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", ra_list, ra_list->is_11n_enabled); + if (ra_list->is_11n_enabled) { + ra_list->pkt_count = 0; + ra_list->ba_packet_thr = + mwifiex_get_random_ba_threshold(); + } list_add_tail(&ra_list->list, &priv->wmm.tid_tbl_ptr[i].ra_list); @@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, skb_queue_tail(&ra_list->skb_head, skb); ra_list->total_pkts_size += skb->len; + ra_list->pkt_count++; atomic_inc(&priv->wmm.tx_pkts_queued); @@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, { int count = 0, total_size = 0; struct sk_buff *skb, *tmp; + int max_amsdu_size; + + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled && + ptr->is_11n_enabled) + max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size); + else + max_amsdu_size = max_buf_size; skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { total_size += skb->len; - if (total_size >= max_buf_size) + if (total_size >= max_amsdu_size) break; if (++count >= MIN_NUM_AMSDU) return true; @@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, skb_queue_tail(&ptr->skb_head, skb); ptr->total_pkts_size += skb->len; + ptr->pkt_count++; tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) /* ra_list_spinlock has been freed in mwifiex_send_single_packet() */ } else { - if (mwifiex_is_ampdu_allowed(priv, tid)) { + if (mwifiex_is_ampdu_allowed(priv, tid) && + ptr->pkt_count > ptr->ba_packet_thr) { if (mwifiex_space_avail_for_new_ba_stream(adapter)) { mwifiex_create_ba_tbl(priv, ptr->ra, tid, BA_SETUP_INPROGRESS); From 3e238a1167cc5693a0d97b946100d74d75b72680 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 3 Aug 2012 18:06:11 -0700 Subject: [PATCH 072/109] mwifiex: cleanup TX/RX BA tables for uAP Cleanup TX/RX BA tables when AP receives deauthentication from associated station. During BSS_IDLE event, all wmm queues, BA streams created for AP interface are deleted. Signed-off-by: Avinash Patil Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n.c | 26 ++++++++++++++++++++ drivers/net/wireless/mwifiex/11n.h | 1 + drivers/net/wireless/mwifiex/11n_rxreorder.c | 25 +++++++++++++++++++ drivers/net/wireless/mwifiex/11n_rxreorder.h | 1 + drivers/net/wireless/mwifiex/uap_event.c | 5 ++++ 5 files changed, 58 insertions(+) diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index e535c937628b..d2732736f864 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -726,3 +726,29 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, return count; } + +/* + * This function retrieves the entry for specific tx BA stream table by RA and + * deletes it. + */ +void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra) +{ + struct mwifiex_tx_ba_stream_tbl *tbl, *tmp; + unsigned long flags; + + if (!ra) + return; + + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) { + if (!memcmp(tbl->ra, ra, ETH_ALEN)) { + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, + flags); + mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl); + spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); + } + } + spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); + + return; +} diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 6d2edb4c2ad2..67c087cf9dc7 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -69,6 +69,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, int cmd_action, struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); +void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); /* * This function checks whether AMPDU is allowed or not for a particular TID. diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index e43d27dc06bf..24e2582b467c 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -176,6 +176,31 @@ mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) return NULL; } +/* This function retrieves the pointer to an entry in Rx reordering + * table which matches the given TA and deletes it. + */ +void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta) +{ + struct mwifiex_rx_reorder_tbl *tbl, *tmp; + unsigned long flags; + + if (!ta) + return; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) { + if (!memcmp(tbl->ta, ta, ETH_ALEN)) { + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, + flags); + mwifiex_del_rx_reorder_entry(priv, tbl); + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); + } + } + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); + + return; +} + /* * This function finds the last sequence number used in the packets * buffered in Rx reordering table. diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 13ecb6101e23..72848591691a 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -72,5 +72,6 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct u8 *ta); struct mwifiex_rx_reorder_tbl * mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); +void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta); #endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index a10bd95aec12..14d4f04201b9 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -226,10 +226,15 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) MWIFIEX_UAP_EVENT_EXTRA_HEADER; cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); + if (priv->ap_11n_enabled) { + mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac); + mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac); + } mwifiex_del_sta_entry(priv, deauth_mac); break; case EVENT_UAP_BSS_IDLE: priv->media_connected = false; + mwifiex_clean_txrx(priv); mwifiex_del_all_sta_list(priv); break; case EVENT_UAP_BSS_ACTIVE: From 9d7aba63c8630c1fdd7cb321d979c757a1abd20f Mon Sep 17 00:00:00 2001 From: Ying Luo Date: Fri, 3 Aug 2012 18:06:12 -0700 Subject: [PATCH 073/109] mwifiex: rename wapi_rxpn to pn This array was used for wapi_rxpn only. Now it will be used for AES_CMAC as well. So make a generic name for it. Signed-off-by: Ying Luo Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/ioctl.h | 4 ++-- drivers/net/wireless/mwifiex/sta_cmd.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 50191539bb32..f2865b51d5d8 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -213,7 +213,7 @@ struct mwifiex_debug_info { }; #define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 -#define WAPI_RXPN_LEN 16 +#define PN_LEN 16 struct mwifiex_ds_encrypt_key { u32 key_disable; @@ -222,7 +222,7 @@ struct mwifiex_ds_encrypt_key { u8 key_material[WLAN_MAX_KEY_LEN]; u8 mac_addr[ETH_ALEN]; u32 is_wapi_key; - u8 wapi_rxpn[WAPI_RXPN_LEN]; + u8 pn[PN_LEN]; /* packet number */ }; struct mwifiex_power_cfg { diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index df3a33c530cf..a4a4a19b008a 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -610,7 +610,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, memcpy(&key_material->key_param_set.key[2], enc_key->key_material, enc_key->key_len); memcpy(&key_material->key_param_set.key[2 + enc_key->key_len], - enc_key->wapi_rxpn, WAPI_RXPN_LEN); + enc_key->pn, PN_LEN); key_material->key_param_set.length = cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); From 53b112315c015c50e4c092474adb6729269b0fc4 Mon Sep 17 00:00:00 2001 From: Ying Luo Date: Fri, 3 Aug 2012 18:06:13 -0700 Subject: [PATCH 074/109] mwifiex: pass key_params pointer in mwifiex_set_encode 'cipher' and 'seq' coming from cfg80211 add_key handler will be parsed in mwifiex_set_encode() to handle AES_CMAC cipher suite. Signed-off-by: Ying Luo Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 15 +++++++++------ drivers/net/wireless/mwifiex/ioctl.h | 1 + drivers/net/wireless/mwifiex/main.h | 6 +++--- drivers/net/wireless/mwifiex/sta_ioctl.c | 12 +++++++++--- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 1f80f7e13ba8..e57f543413de 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -99,7 +99,7 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const u8 *peer_mac = pairwise ? mac_addr : bc_mac; - if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) { + if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) { wiphy_err(wiphy, "deleting the crypto keys\n"); return -EFAULT; } @@ -171,7 +171,8 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) { priv->wep_key_curr_index = key_index; - } else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { + } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, + NULL, 0)) { wiphy_err(wiphy, "set default Tx key index\n"); return -EFAULT; } @@ -207,7 +208,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, return 0; } - if (mwifiex_set_encode(priv, params->key, params->key_len, + if (mwifiex_set_encode(priv, params, params->key, params->key_len, key_index, peer_mac, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; @@ -748,6 +749,7 @@ static const u32 mwifiex_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_AES_CMAC, }; /* @@ -1161,7 +1163,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, priv->wep_key_curr_index = 0; priv->sec_info.encryption_mode = 0; priv->sec_info.is_authtype_auto = 0; - ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1); + ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1); if (mode == NL80211_IFTYPE_ADHOC) { /* "privacy" is set only for ad-hoc mode */ @@ -1208,8 +1210,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, "info: setting wep encryption" " with key len %d\n", sme->key_len); priv->wep_key_curr_index = sme->key_idx; - ret = mwifiex_set_encode(priv, sme->key, sme->key_len, - sme->key_idx, NULL, 0); + ret = mwifiex_set_encode(priv, NULL, sme->key, + sme->key_len, sme->key_idx, + NULL, 0); } } done: diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index f2865b51d5d8..6a5eded3be10 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -223,6 +223,7 @@ struct mwifiex_ds_encrypt_key { u8 mac_addr[ETH_ALEN]; u32 is_wapi_key; u8 pn[PN_LEN]; /* packet number */ + u8 is_igtk_key; }; struct mwifiex_power_cfg { diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index c39cd8e50f9f..994bc4fc263e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -981,9 +981,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, const struct mwifiex_user_scan_cfg *user_scan_in); int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); -int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, - int key_len, u8 key_index, const u8 *mac_addr, - int disable); +int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, + const u8 *key, int key_len, u8 key_index, + const u8 *mac_addr, int disable); int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index fb2136089a22..3f025976f79a 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -942,20 +942,26 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler. */ -int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, - int key_len, u8 key_index, - const u8 *mac_addr, int disable) +int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, + const u8 *key, int key_len, u8 key_index, + const u8 *mac_addr, int disable) { struct mwifiex_ds_encrypt_key encrypt_key; memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); encrypt_key.key_len = key_len; + + if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) + encrypt_key.is_igtk_key = true; + if (!disable) { encrypt_key.key_index = key_index; if (key_len) memcpy(encrypt_key.key_material, key, key_len); if (mac_addr) memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); + if (kp && kp->seq && kp->seq_len) + memcpy(encrypt_key.pn, kp->seq, kp->seq_len); } else { encrypt_key.key_disable = true; if (mac_addr) From b877f4cf5af86528e07a0182e2b369ded38ccf38 Mon Sep 17 00:00:00 2001 From: Ying Luo Date: Fri, 3 Aug 2012 18:06:14 -0700 Subject: [PATCH 075/109] mwifiex: add AES_CMAC support in key_material cmd The sequence counter will be sent to firmware via key_material command. Signed-off-by: Ying Luo Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 9 +++++ drivers/net/wireless/mwifiex/sta_cmd.c | 55 ++++++++++++++++++++------ 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1c1274d8d789..ae06f31c6838 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -65,10 +65,12 @@ enum KEY_TYPE_ID { KEY_TYPE_ID_TKIP, KEY_TYPE_ID_AES, KEY_TYPE_ID_WAPI, + KEY_TYPE_ID_AES_CMAC, }; #define KEY_MCAST BIT(0) #define KEY_UNICAST BIT(1) #define KEY_ENABLED BIT(2) +#define KEY_IGTK BIT(10) #define WAPI_KEY_LEN 50 @@ -583,6 +585,13 @@ struct mwifiex_ie_type_key_param_set { u8 key[50]; } __packed; +#define IGTK_PN_LEN 8 + +struct mwifiex_cmac_param { + u8 ipn[IGTK_PN_LEN]; + u8 key[WLAN_KEY_LEN_AES_CMAC]; +} __packed; + struct host_cmd_ds_802_11_key_material { __le16 action; struct mwifiex_ie_type_key_param_set key_param_set; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index a4a4a19b008a..9af96926093e 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -621,23 +621,38 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, return ret; } if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { - dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_AES); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = + if (enc_key->is_igtk_key) { + dev_dbg(priv->adapter->dev, "cmd: CMAC_AES\n"); + key_material->key_param_set.key_type_id = + cpu_to_le16(KEY_TYPE_ID_AES_CMAC); + if (cmd_oid == KEY_INFO_ENABLED) + key_material->key_param_set.key_info = cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = + else + key_material->key_param_set.key_info = cpu_to_le16(!KEY_ENABLED); - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) + key_material->key_param_set.key_info |= + cpu_to_le16(KEY_IGTK); + } else { + dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n"); + key_material->key_param_set.key_type_id = + cpu_to_le16(KEY_TYPE_ID_AES); + if (cmd_oid == KEY_INFO_ENABLED) + key_material->key_param_set.key_info = + cpu_to_le16(KEY_ENABLED); + else + key_material->key_param_set.key_info = + cpu_to_le16(!KEY_ENABLED); + + if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) /* AES pairwise key: unicast */ - key_material->key_param_set.key_info |= + key_material->key_param_set.key_info |= cpu_to_le16(KEY_UNICAST); - else /* AES group key: multicast */ - key_material->key_param_set.key_info |= + else /* AES group key: multicast */ + key_material->key_param_set.key_info |= cpu_to_le16(KEY_MCAST); + } } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n"); key_material->key_param_set.key_type_id = @@ -668,6 +683,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN) + sizeof(struct mwifiex_ie_types_header); + if (le16_to_cpu(key_material->key_param_set.key_type_id) == + KEY_TYPE_ID_AES_CMAC) { + struct mwifiex_cmac_param *param = + (void *)key_material->key_param_set.key; + + memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN); + memcpy(param->key, enc_key->key_material, + enc_key->key_len); + + key_param_len = sizeof(struct mwifiex_cmac_param); + key_material->key_param_set.key_len = + cpu_to_le16(key_param_len); + key_param_len += KEYPARAMSET_FIXED_LEN; + key_material->key_param_set.length = + cpu_to_le16(key_param_len); + key_param_len += sizeof(struct mwifiex_ie_types_header); + } + cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN + key_param_len); From 9bc63816be9bf504414d350e605a4b30f857907d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 28 Jul 2012 02:57:51 +0200 Subject: [PATCH 076/109] p54: parse output power table For the upcoming tpc changes, the driver needs to provide sensible max output values for each supported channel. And while the eeprom always had a output_limit table, which defines the upper limit for each frequency and modulation, it was never really useful for anything... until now. Note: For anyone wondering about what your card is calibrated for: check "iw list". * 2412 MHz [1] (18.0 dBm) * 2437 MHz [6] (19.0 dBm) [...] * 5180 MHz [36] (18.0 dBm) * 5260 MHz [52] (17.0 dBm) (radar detection) * 5680 MHz [136] (19.0 dBm) (radar detection) (for a Dell Wireless 1450 USB Adapter) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 102 +++++++++++++++++++++++------- drivers/net/wireless/p54/eeprom.h | 12 ++++ 2 files changed, 91 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 14037092ba89..d4d86107e05a 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -76,6 +76,7 @@ struct p54_channel_entry { u16 freq; u16 data; int index; + int max_power; enum ieee80211_band band; }; @@ -173,6 +174,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, for (i = 0, j = 0; (j < list->band_channel_num[band]) && (i < list->entries); i++) { struct p54_channel_entry *chan = &list->channels[i]; + struct ieee80211_channel *dest = &tmp->channels[j]; if (chan->band != band) continue; @@ -190,14 +192,15 @@ static int p54_generate_band(struct ieee80211_hw *dev, continue; } - tmp->channels[j].band = chan->band; - tmp->channels[j].center_freq = chan->freq; + dest->band = chan->band; + dest->center_freq = chan->freq; + dest->max_power = chan->max_power; priv->survey[*chan_num].channel = &tmp->channels[j]; priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_TX; - tmp->channels[j].hw_value = (*chan_num); + dest->hw_value = (*chan_num); j++; (*chan_num)++; } @@ -229,10 +232,11 @@ err_out: return ret; } -static void p54_update_channel_param(struct p54_channel_list *list, - u16 freq, u16 data) +static struct p54_channel_entry *p54_update_channel_param(struct p54_channel_list *list, + u16 freq, u16 data) { - int band, i; + int i; + struct p54_channel_entry *entry = NULL; /* * usually all lists in the eeprom are mostly sorted. @@ -241,30 +245,74 @@ static void p54_update_channel_param(struct p54_channel_list *list, */ for (i = list->entries; i >= 0; i--) { if (freq == list->channels[i].freq) { - list->channels[i].data |= data; + entry = &list->channels[i]; break; } } if ((i < 0) && (list->entries < list->max_entries)) { /* entry does not exist yet. Initialize a new one. */ - band = p54_get_band_from_freq(freq); + int band = p54_get_band_from_freq(freq); /* * filter out frequencies which don't belong into * any supported band. */ - if (band < 0) - return ; + if (band >= 0) { + i = list->entries++; + list->band_channel_num[band]++; - i = list->entries++; - list->band_channel_num[band]++; + entry = &list->channels[i]; + entry->freq = freq; + entry->band = band; + entry->index = ieee80211_frequency_to_channel(freq); + entry->max_power = 0; + entry->data = 0; + } + } - list->channels[i].freq = freq; - list->channels[i].data = data; - list->channels[i].band = band; - list->channels[i].index = ieee80211_frequency_to_channel(freq); - /* TODO: parse output_limit and fill max_power */ + if (entry) + entry->data |= data; + + return entry; +} + +static int p54_get_maxpower(struct p54_common *priv, void *data) +{ + switch (priv->rxhw & PDR_SYNTH_FRONTEND_MASK) { + case PDR_SYNTH_FRONTEND_LONGBOW: { + struct pda_channel_output_limit_longbow *pda = data; + int j; + u16 rawpower = 0; + pda = data; + for (j = 0; j < ARRAY_SIZE(pda->point); j++) { + struct pda_channel_output_limit_point_longbow *point = + &pda->point[j]; + rawpower = max(rawpower, le16_to_cpu(point->val_qpsk)); + rawpower = max(rawpower, le16_to_cpu(point->val_bpsk)); + rawpower = max(rawpower, le16_to_cpu(point->val_16qam)); + rawpower = max(rawpower, le16_to_cpu(point->val_64qam)); + } + /* longbow seems to use 1/16 dBm units */ + return rawpower / 16; + } + + case PDR_SYNTH_FRONTEND_DUETTE3: + case PDR_SYNTH_FRONTEND_DUETTE2: + case PDR_SYNTH_FRONTEND_FRISBEE: + case PDR_SYNTH_FRONTEND_XBOW: { + struct pda_channel_output_limit *pda = data; + u8 rawpower = 0; + rawpower = max(rawpower, pda->val_qpsk); + rawpower = max(rawpower, pda->val_bpsk); + rawpower = max(rawpower, pda->val_16qam); + rawpower = max(rawpower, pda->val_64qam); + /* raw values are in 1/4 dBm units */ + return rawpower / 4; + } + + default: + return 20; } } @@ -315,12 +363,19 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) } if (i < priv->output_limit->entries) { - freq = le16_to_cpup((__le16 *) (i * - priv->output_limit->entry_size + - priv->output_limit->offset + - priv->output_limit->data)); + struct p54_channel_entry *tmp; - p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); + void *data = (void *) ((unsigned long) i * + priv->output_limit->entry_size + + priv->output_limit->offset + + priv->output_limit->data); + + freq = le16_to_cpup((__le16 *) data); + tmp = p54_update_channel_param(list, freq, + CHAN_HAS_LIMIT); + if (tmp) { + tmp->max_power = p54_get_maxpower(priv, data); + } } if (i < priv->curve_data->entries) { @@ -834,11 +889,12 @@ good_eeprom: goto err; } + priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; + err = p54_generate_channel_lists(dev); if (err) goto err; - priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h index afde72b84606..20ebe39a3f4e 100644 --- a/drivers/net/wireless/p54/eeprom.h +++ b/drivers/net/wireless/p54/eeprom.h @@ -57,6 +57,18 @@ struct pda_channel_output_limit { u8 rate_set_size; } __packed; +struct pda_channel_output_limit_point_longbow { + __le16 val_bpsk; + __le16 val_qpsk; + __le16 val_16qam; + __le16 val_64qam; +} __packed; + +struct pda_channel_output_limit_longbow { + __le16 freq; + struct pda_channel_output_limit_point_longbow point[3]; +} __packed; + struct pda_pa_curve_data_sample_rev0 { u8 rf_power; u8 pa_detector; From 94f3457f4da43a44f17789f3e0bc8fb2ee9593ca Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 5 Aug 2012 16:54:41 +0200 Subject: [PATCH 077/109] bcma: make some functions static The functions and structs are not used in an other file and the prototypes are in no header file, just make them static so the compiler is able to optimize them better. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/driver_chipcommon_pmu.c | 4 ++-- drivers/bcma/host_pci.c | 11 ++++++----- drivers/bcma/host_soc.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index c9a4f46c5143..8b8f2f3862a2 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -101,7 +101,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); } -void bcma_pmu_workarounds(struct bcma_drv_cc *cc) +static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -257,7 +257,7 @@ static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) } /* query bus clock frequency for PMU-enabled chipcommon */ -u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) +static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 11b32d2642df..fc996288090b 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, } #ifdef CONFIG_BCMA_BLOCKIO -void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, - size_t count, u16 offset, u8 reg_width) +static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, + size_t count, u16 offset, u8 reg_width) { void __iomem *addr = core->bus->mmio + offset; if (core->bus->mapped_core != core) @@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, } } -void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, - size_t count, u16 offset, u8 reg_width) +static void bcma_host_pci_block_write(struct bcma_device *core, + const void *buffer, size_t count, + u16 offset, u8 reg_width) { void __iomem *addr = core->bus->mmio + offset; if (core->bus->mapped_core != core) @@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); } -const struct bcma_host_ops bcma_host_pci_ops = { +static const struct bcma_host_ops bcma_host_pci_ops = { .read8 = bcma_host_pci_read8, .read16 = bcma_host_pci_read16, .read32 = bcma_host_pci_read32, diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c index 3c381fb8f9c4..3475e600011a 100644 --- a/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c @@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset, writel(value, core->io_wrap + offset); } -const struct bcma_host_ops bcma_host_soc_ops = { +static const struct bcma_host_ops bcma_host_soc_ops = { .read8 = bcma_host_soc_read8, .read16 = bcma_host_soc_read16, .read32 = bcma_host_soc_read32, From d12c5c53ce4c8c65c694d1103673182ef5afdc65 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 5 Aug 2012 22:35:33 +0300 Subject: [PATCH 078/109] ath5k: Use correct value for min_pwr and cur_pwr Make sure we don't store the table offsets for min and cur power levels, store the 0.25dB values instead. This way we don't clamp the tx power level to max (because now cur_pwr holds the 0.25dB value, not the table offset) after re-using cur_pwr on reset. Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 8b71a2d947e0..aa1a77d4cd90 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3562,6 +3562,20 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, for (i = 8; i <= 15; i++) rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; + /* Save min/max and current tx power for this channel + * in 0.25dB units. + * + * Note: We use rates[0] for current tx power because + * it covers most of the rates, in most cases. It's our + * tx power limit and what the user expects to see. */ + ah->ah_txpower.txp_min_pwr = 2 * rates[7]; + ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; + + /* Set max txpower for correct OFDM operation on all rates + * -that is the txpower for 54Mbit-, it's used for the PAPD + * gain probe and it's in 0.5dB units */ + ah->ah_txpower.txp_ofdm = rates[7]; + /* Now that we have all rates setup use table offset to * match the power range set by user with the power indices * on PCDAC/PDADC table */ @@ -3571,11 +3585,6 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, if (rates[i] > 63) rates[i] = 63; } - - /* Min/max in 0.25dB units */ - ah->ah_txpower.txp_min_pwr = 2 * rates[7]; - ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; - ah->ah_txpower.txp_ofdm = rates[7]; } From 755051993bfcdf07acd84a7ffd08d463b85bfd69 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 5 Aug 2012 22:35:34 +0300 Subject: [PATCH 079/109] ath5k: Fix range scaling when setting rate power table rates[i] is unsigned but txp_offset can be negative for newer parts with PDADC table. We cover the case when rates[i] + txp_offset > 63 but we must also cover the case when its < 0 or else rates[i] will overflow. Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index aa1a77d4cd90..84a9aafd91a2 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3516,6 +3516,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, { unsigned int i; u16 *rates; + s16 rate_idx_scaled = 0; /* max_pwr is power level we got from driver/user in 0.5dB * units, switch to 0.25dB units so we can compare */ @@ -3580,10 +3581,13 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, * match the power range set by user with the power indices * on PCDAC/PDADC table */ for (i = 0; i < 16; i++) { - rates[i] += ah->ah_txpower.txp_offset; + rate_idx_scaled = rates[i] + ah->ah_txpower.txp_offset; /* Don't get out of bounds */ - if (rates[i] > 63) - rates[i] = 63; + if (rate_idx_scaled > 63) + rate_idx_scaled = 63; + if (rate_idx_scaled < 0) + rate_idx_scaled = 0; + rates[i] = rate_idx_scaled; } } From 493ca5ef4ec8a7e8396d6ab26f48de66bdf73dca Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 5 Aug 2012 22:35:35 +0300 Subject: [PATCH 080/109] ath5k: Preserve tx power level requested from above on phy_init By using cur_pwr on phy_init we re-use the power level previously set by the driver, not the one we got from above. Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 84a9aafd91a2..27ca993586d7 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3802,8 +3802,8 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, * RF buffer settings on 5211/5212+ so that we * properly set curve indices. */ - ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ? - ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER); + ret = ath5k_hw_txpower(ah, channel, ah->power_level ? + ah->power_level * 2 : AR5K_TUNE_MAX_TXPOWER); if (ret) return ret; From 987af54fa93b1c01eb3a85229bc93dfe77e6d2e1 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 5 Aug 2012 22:35:36 +0300 Subject: [PATCH 081/109] ath5k: Put power_level where it belongs and rename it Put power_level to ah_txpower struct with the rest tx power infos and also rename it to txp_requested to make more sense. v2 make sure we don't memset it to zero on reset Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/base.c | 5 +++-- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 4 ++-- drivers/net/wireless/ath/ath5k/phy.c | 14 +++++++++++--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 64a453a6dfe4..3150def17193 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1331,7 +1331,6 @@ struct ath5k_hw { unsigned int nexttbtt; /* next beacon time in TU */ struct ath5k_txq *cabq; /* content after beacon */ - int power_level; /* Requested tx power in dBm */ bool assoc; /* associate state */ bool enable_beacon; /* true if beacons are on */ @@ -1425,6 +1424,7 @@ struct ath5k_hw { /* Value in dB units */ s16 txp_cck_ofdm_pwr_delta; bool txp_setup; + int txp_requested; /* Requested tx power in dBm */ } ah_txpower; struct ath5k_nfcal_hist ah_nfcal_hist; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8c4c040a47b8..9d48f9a461e1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -723,7 +723,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), padsize, get_hw_packet_type(skb), - (ah->power_level * 2), + (ah->ah_txpower.txp_requested * 2), hw_rate, info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, cts_rate, duration); @@ -1778,7 +1778,8 @@ ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf) ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), padsize, - AR5K_PKT_TYPE_BEACON, (ah->power_level * 2), + AR5K_PKT_TYPE_BEACON, + (ah->ah_txpower.txp_requested * 2), ieee80211_get_tx_rate(ah->hw, info)->hw_value, 1, AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 260e7dc7f751..92ee3a0a5192 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -207,8 +207,8 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) } if ((changed & IEEE80211_CONF_CHANGE_POWER) && - (ah->power_level != conf->power_level)) { - ah->power_level = conf->power_level; + (ah->ah_txpower.txp_requested != conf->power_level)) { + ah->ah_txpower.txp_requested = conf->power_level; /* Half dB steps */ ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 27ca993586d7..01c90ed58453 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3652,10 +3652,17 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, if (!ah->ah_txpower.txp_setup || (channel->hw_value != curr_channel->hw_value) || (channel->center_freq != curr_channel->center_freq)) { - /* Reset TX power values */ + /* Reset TX power values but preserve requested + * tx power from above */ + int requested_txpower = ah->ah_txpower.txp_requested; + memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); + + /* Restore TPC setting and requested tx power */ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; + ah->ah_txpower.txp_requested = requested_txpower; + /* Calculate the powertable */ ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); @@ -3802,8 +3809,9 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, * RF buffer settings on 5211/5212+ so that we * properly set curve indices. */ - ret = ath5k_hw_txpower(ah, channel, ah->power_level ? - ah->power_level * 2 : AR5K_TUNE_MAX_TXPOWER); + ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_requested ? + ah->ah_txpower.txp_requested * 2 : + AR5K_TUNE_MAX_TXPOWER); if (ret) return ret; From 2f9279b5568c4de8c37566f11e7c26292a3f4bf2 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 7 Aug 2012 10:26:53 +0800 Subject: [PATCH 082/109] mwifiex: fix code mis-alignment after the if statement Signed-off-by: Fengguang Wu Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 3035412a0498..215d07e6c462 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1435,9 +1435,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, if (ret) dev_err(priv->adapter->dev, "cannot find ssid " "%s\n", bss_desc->ssid.ssid); - break; + break; default: - ret = 0; + ret = 0; } } From 450e9038ee65e3246b2a942669fc79001466f9be Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Aug 2012 21:46:44 +0200 Subject: [PATCH 083/109] iwlegacy: clean up suspend/resume There's no need to export the il_pci_suspend and il_pci_resume functions since they're only referenced from il_pm_ops. The latter can also be defined using SIMPLE_DEV_PM_OPS instead of open-coding it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.c | 15 +++------------ drivers/net/wireless/iwlegacy/common.h | 2 -- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 0370403fd0bd..eb9987520d61 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4860,7 +4860,7 @@ EXPORT_SYMBOL(il_add_beacon_time); #ifdef CONFIG_PM -int +static int il_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); @@ -4877,9 +4877,8 @@ il_pci_suspend(struct device *device) return 0; } -EXPORT_SYMBOL(il_pci_suspend); -int +static int il_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); @@ -4906,16 +4905,8 @@ il_pci_resume(struct device *device) return 0; } -EXPORT_SYMBOL(il_pci_resume); -const struct dev_pm_ops il_pm_ops = { - .suspend = il_pci_suspend, - .resume = il_pci_resume, - .freeze = il_pci_suspend, - .thaw = il_pci_resume, - .poweroff = il_pci_suspend, - .restore = il_pci_resume, -}; +SIMPLE_DEV_PM_OPS(il_pm_ops, il_pci_suspend, il_pci_resume); EXPORT_SYMBOL(il_pm_ops); #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 5f5017767b99..3d3135ed62d7 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1845,8 +1845,6 @@ __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon, u32 beacon_interval); #ifdef CONFIG_PM -int il_pci_suspend(struct device *device); -int il_pci_resume(struct device *device); extern const struct dev_pm_ops il_pm_ops; #define IL_LEGACY_PM_OPS (&il_pm_ops) From 8dd4372e2a462081b92b38af18accb427fa2d554 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Tue, 7 Aug 2012 16:08:08 -0700 Subject: [PATCH 084/109] mwifiex: fix powerpc64-linux- compilation warnings These warnings can be detected by using powerpc64-linux toolchain (gcc-4.6.3-nolibc). CC [M] drivers/net/wireless/mwifiex/sta_event.o drivers/net/wireless/mwifiex/sta_event.c: In function 'mwifiex_process_sta_event': drivers/net/wireless/mwifiex/sta_event.c:388:4: warning: comparison of distinct pointer types lacks a cast [enabled by default] CC [M] drivers/net/wireless/mwifiex/uap_event.o drivers/net/wireless/mwifiex/uap_event.c: In function 'mwifiex_process_uap_event': drivers/net/wireless/mwifiex/uap_event.c:258:11: warning: comparison of distinct pointer types lacks a cast [enabled by default] Use min_t() instead of min() to fix the warnings. Reported-by: Fengguang Wu Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_event.c | 9 +++++---- drivers/net/wireless/mwifiex/uap_event.c | 9 ++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 2aad148db5c3..4758d3064887 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -186,6 +186,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; u32 eventcause = adapter->event_cause; + u16 ctrl; switch (eventcause) { case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: @@ -382,11 +383,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->event_body); break; case EVENT_AMSDU_AGGR_CTRL: - dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", - *(u16 *) adapter->event_body); + ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); + dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl); + adapter->tx_buf_size = - min(adapter->curr_tx_buf_size, - le16_to_cpu(*(__le16 *) adapter->event_body)); + min_t(u16, adapter->curr_tx_buf_size, ctrl); dev_dbg(adapter->dev, "event: tx_buf_size %d\n", adapter->tx_buf_size); break; diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 14d4f04201b9..1703abf73dac 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -170,6 +170,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) struct mwifiex_sta_node *node; u8 *deauth_mac; struct host_cmd_ds_11n_batimeout *ba_timeout; + u16 ctrl; switch (eventcause) { case EVENT_UAP_STA_ASSOC: @@ -250,14 +251,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); break; case EVENT_AMSDU_AGGR_CTRL: - dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", - *(u16 *)adapter->event_body); + ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); + dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl); if (priv->media_connected) { adapter->tx_buf_size = - min(adapter->curr_tx_buf_size, - le16_to_cpu(*(__le16 *)adapter->event_body)); - + min_t(u16, adapter->curr_tx_buf_size, ctrl); dev_dbg(adapter->dev, "event: tx_buf_size %d\n", adapter->tx_buf_size); } From 3213e1a570783ca3a41d025cede4a27b18bc24c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 8 Aug 2012 19:10:14 +0200 Subject: [PATCH 085/109] bcma: add (mostly) NAND defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- include/linux/bcma/bcma_driver_chipcommon.h | 85 +++++++++++++++++++++ include/linux/bcma/bcma_regs.h | 2 + 2 files changed, 87 insertions(+) diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 3c80885fa829..fcb06fb284eb 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -94,6 +94,7 @@ #define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ +#define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ #define BCMA_CC_JCMD_START 0x80000000 #define BCMA_CC_JCMD_BUSY 0x80000000 @@ -260,6 +261,29 @@ #define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004 #define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1 #define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001 +/* Block 0x140 - 0x190 registers are chipset specific */ +#define BCMA_CC_4706_FLASHSCFG 0x18C /* Flash struct configuration */ +#define BCMA_CC_4706_FLASHSCFG_MASK 0x000000ff +#define BCMA_CC_4706_FLASHSCFG_SF1 0x00000001 /* 2nd serial flash present */ +#define BCMA_CC_4706_FLASHSCFG_PF1 0x00000002 /* 2nd parallel flash present */ +#define BCMA_CC_4706_FLASHSCFG_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ +#define BCMA_CC_4706_FLASHSCFG_NF1 0x00000008 /* 2nd NAND flash present */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_MASK 0x000000f0 +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ +#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ +/* NAND flash registers for BCM4706 (corerev = 31) */ +#define BCMA_CC_NFLASH_CTL 0x01A0 +#define BCMA_CC_NFLASH_CTL_ERR 0x08000000 +#define BCMA_CC_NFLASH_CONF 0x01A4 +#define BCMA_CC_NFLASH_COL_ADDR 0x01A8 +#define BCMA_CC_NFLASH_ROW_ADDR 0x01AC +#define BCMA_CC_NFLASH_DATA 0x01B0 +#define BCMA_CC_NFLASH_WAITCNT0 0x01B4 /* 0x1E0 is defined as shared BCMA_CLKCTLST */ #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define BCMA_CC_UART0_DATA 0x0300 @@ -319,6 +343,60 @@ #define BCMA_CC_PLLCTL_ADDR 0x0660 #define BCMA_CC_PLLCTL_DATA 0x0664 #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ +/* NAND flash MLC controller registers (corerev >= 38) */ +#define BCMA_CC_NAND_REVISION 0x0C00 +#define BCMA_CC_NAND_CMD_START 0x0C04 +#define BCMA_CC_NAND_CMD_ADDR_X 0x0C08 +#define BCMA_CC_NAND_CMD_ADDR 0x0C0C +#define BCMA_CC_NAND_CMD_END_ADDR 0x0C10 +#define BCMA_CC_NAND_CS_NAND_SELECT 0x0C14 +#define BCMA_CC_NAND_CS_NAND_XOR 0x0C18 +#define BCMA_CC_NAND_SPARE_RD0 0x0C20 +#define BCMA_CC_NAND_SPARE_RD4 0x0C24 +#define BCMA_CC_NAND_SPARE_RD8 0x0C28 +#define BCMA_CC_NAND_SPARE_RD12 0x0C2C +#define BCMA_CC_NAND_SPARE_WR0 0x0C30 +#define BCMA_CC_NAND_SPARE_WR4 0x0C34 +#define BCMA_CC_NAND_SPARE_WR8 0x0C38 +#define BCMA_CC_NAND_SPARE_WR12 0x0C3C +#define BCMA_CC_NAND_ACC_CONTROL 0x0C40 +#define BCMA_CC_NAND_CONFIG 0x0C48 +#define BCMA_CC_NAND_TIMING_1 0x0C50 +#define BCMA_CC_NAND_TIMING_2 0x0C54 +#define BCMA_CC_NAND_SEMAPHORE 0x0C58 +#define BCMA_CC_NAND_DEVID 0x0C60 +#define BCMA_CC_NAND_DEVID_X 0x0C64 +#define BCMA_CC_NAND_BLOCK_LOCK_STATUS 0x0C68 +#define BCMA_CC_NAND_INTFC_STATUS 0x0C6C +#define BCMA_CC_NAND_ECC_CORR_ADDR_X 0x0C70 +#define BCMA_CC_NAND_ECC_CORR_ADDR 0x0C74 +#define BCMA_CC_NAND_ECC_UNC_ADDR_X 0x0C78 +#define BCMA_CC_NAND_ECC_UNC_ADDR 0x0C7C +#define BCMA_CC_NAND_READ_ERROR_COUNT 0x0C80 +#define BCMA_CC_NAND_CORR_STAT_THRESHOLD 0x0C84 +#define BCMA_CC_NAND_READ_ADDR_X 0x0C90 +#define BCMA_CC_NAND_READ_ADDR 0x0C94 +#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR_X 0x0C98 +#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR 0x0C9C +#define BCMA_CC_NAND_COPY_BACK_ADDR_X 0x0CA0 +#define BCMA_CC_NAND_COPY_BACK_ADDR 0x0CA4 +#define BCMA_CC_NAND_BLOCK_ERASE_ADDR_X 0x0CA8 +#define BCMA_CC_NAND_BLOCK_ERASE_ADDR 0x0CAC +#define BCMA_CC_NAND_INV_READ_ADDR_X 0x0CB0 +#define BCMA_CC_NAND_INV_READ_ADDR 0x0CB4 +#define BCMA_CC_NAND_BLK_WR_PROTECT 0x0CC0 +#define BCMA_CC_NAND_ACC_CONTROL_CS1 0x0CD0 +#define BCMA_CC_NAND_CONFIG_CS1 0x0CD4 +#define BCMA_CC_NAND_TIMING_1_CS1 0x0CD8 +#define BCMA_CC_NAND_TIMING_2_CS1 0x0CDC +#define BCMA_CC_NAND_SPARE_RD16 0x0D30 +#define BCMA_CC_NAND_SPARE_RD20 0x0D34 +#define BCMA_CC_NAND_SPARE_RD24 0x0D38 +#define BCMA_CC_NAND_SPARE_RD28 0x0D3C +#define BCMA_CC_NAND_CACHE_ADDR 0x0D40 +#define BCMA_CC_NAND_CACHE_DATA 0x0D44 +#define BCMA_CC_NAND_CTRL_CONFIG 0x0D48 +#define BCMA_CC_NAND_CTRL_STATUS 0x0D4C /* Divider allocation in 4716/47162/5356 */ #define BCMA_CC_PMU5_MAINPLL_CPU 1 @@ -409,6 +487,13 @@ /* 4313 Chip specific ChipControl register bits */ #define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ +/* BCM5357 ChipControl register bits */ +#define BCMA_CHIPCTL_5357_EXTPA BIT(14) +#define BCMA_CHIPCTL_5357_ANT_MUX_2O3 BIT(15) +#define BCMA_CHIPCTL_5357_NFLASH BIT(16) +#define BCMA_CHIPCTL_5357_I2S_PINS_ENABLE BIT(18) +#define BCMA_CHIPCTL_5357_I2CSPI_PINS_ENABLE BIT(19) + /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index 5a71d5719640..a393e82bf7bf 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h @@ -11,11 +11,13 @@ #define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ #define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ #define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */ +#define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8 #define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ #define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */ #define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */ #define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */ #define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */ +#define BCMA_CLKCTLST_EXTRESST_SHIFT 24 /* Is there any BCM4328 on BCMA bus? */ #define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ #define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ From 6c1872369d53966dc26be71c96c4c5db13f65981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 8 Aug 2012 19:10:15 +0200 Subject: [PATCH 086/109] b43: N-PHY: fix 0x2057 radio calib copy/paste mistake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Reported-by: Fengguang Wu Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 5c9074142a8e..3c35382ee6c2 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -572,6 +572,7 @@ static u16 b43_radio_2057_rccal(struct b43_wldev *dev) b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500, 5000000)) + b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n"); b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); if (special) { b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73); From 85ce5ae52690aab0b3a4a6e9a1c2f951d2d8a5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 8 Aug 2012 19:10:16 +0200 Subject: [PATCH 087/109] b43legacy: fix logic in GPIO init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 8156135a0590..3ea1a85d38d1 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1920,7 +1920,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev) return 0; ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, (ssb_read32(gpiodev, B43legacy_GPIO_CONTROL) - & mask) | set); + & ~mask) | set); return 0; } From 902d9e0f48ddc18fb37c1b1edf5e3b27aaba1505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 8 Aug 2012 19:37:04 +0200 Subject: [PATCH 088/109] ssb: check for flash presentence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can not assume parallel flash is always present, there are boards with *serial* flash and probably some without flash at all. Define some bits by the way. Signed-off-by: Rafał Miłecki Reviewed-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/ssb/driver_mipscore.c | 28 +++++++++++++++++------ include/linux/ssb/ssb_driver_chipcommon.h | 4 +++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 7e2ddc042f5b..c6250867a95d 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -190,16 +190,30 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; - mcore->flash_buswidth = 2; - if (bus->chipco.dev) { - mcore->flash_window = 0x1c000000; - mcore->flash_window_size = 0x02000000; + /* When there is no chipcommon on the bus there is 4MB flash */ + if (!bus->chipco.dev) { + mcore->flash_buswidth = 2; + mcore->flash_window = SSB_FLASH1; + mcore->flash_window_size = SSB_FLASH1_SZ; + return; + } + + /* There is ChipCommon, so use it to read info about flash */ + switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { + case SSB_CHIPCO_FLASHT_STSER: + case SSB_CHIPCO_FLASHT_ATSER: + pr_err("Serial flash not supported\n"); + break; + case SSB_CHIPCO_FLASHT_PARA: + pr_debug("Found parallel flash\n"); + mcore->flash_window = SSB_FLASH2; + mcore->flash_window_size = SSB_FLASH2_SZ; if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) & SSB_CHIPCO_CFG_DS16) == 0) mcore->flash_buswidth = 1; - } else { - mcore->flash_window = 0x1fc00000; - mcore->flash_window_size = 0x00400000; + else + mcore->flash_buswidth = 2; + break; } } diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 1a6b0045b06b..c2b02a5c86ae 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -504,7 +504,9 @@ #define SSB_CHIPCO_FLASHCTL_ST_SE 0x02D8 /* Sector Erase */ #define SSB_CHIPCO_FLASHCTL_ST_BE 0x00C7 /* Bulk Erase */ #define SSB_CHIPCO_FLASHCTL_ST_DP 0x00B9 /* Deep Power-down */ -#define SSB_CHIPCO_FLASHCTL_ST_RSIG 0x03AB /* Read Electronic Signature */ +#define SSB_CHIPCO_FLASHCTL_ST_RES 0x03AB /* Read Electronic Signature */ +#define SSB_CHIPCO_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */ +#define SSB_CHIPCO_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */ /* Status register bits for ST flashes */ #define SSB_CHIPCO_FLASHSTA_ST_WIP 0x01 /* Write In Progress */ From 641c869d40c7ec6a34930843f41e95bf1f53f29f Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 8 Aug 2012 19:01:52 -0700 Subject: [PATCH 089/109] mwifiex: fix 'smatch' warning in preparing key_material cmd The key length can be 32 bytes for TKIP and 16 bytes for AES_CMAC. 'smatch' warns on memcpy using key_len variable to copy data to a 16 bytes buffer. Use fixed length to avoid the warning. Reported-by: Dan Carpenter Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 9af96926093e..0cc3406050dc 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -690,7 +690,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN); memcpy(param->key, enc_key->key_material, - enc_key->key_len); + WLAN_KEY_LEN_AES_CMAC); key_param_len = sizeof(struct mwifiex_cmac_param); key_material->key_param_set.key_len = From 9c7ff737b6a783a6641dca71fab4f94aaab4bb2a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 8 Aug 2012 19:02:56 -0700 Subject: [PATCH 090/109] mwifiex: notify cfg80211 about MIC failures Call cfg80211_michael_mic_failure() handler when there is a MIC error event from firmware. Signed-off-by: Amitkumar Karwar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_event.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 4758d3064887..dff51d55271c 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -278,10 +278,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_MIC_ERR_UNICAST: dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n"); + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_PAIRWISE, + -1, NULL, GFP_KERNEL); break; case EVENT_MIC_ERR_MULTICAST: dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n"); + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_GROUP, + -1, NULL, GFP_KERNEL); break; case EVENT_MIB_CHANGED: case EVENT_INIT_DONE: From 126f492355be8c771338b680b3dfbb38a19c88ab Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Aug 2012 09:57:57 +0300 Subject: [PATCH 091/109] mwifiex: use GFP_ATOMIC under spin lock We're holding the sta_list_spinlock here so we can't sleep. Signed-off-by: Dan Carpenter Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/uap_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 1703abf73dac..a33fa394e349 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -63,7 +63,7 @@ mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) if (node) goto done; - node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_KERNEL); + node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_ATOMIC); if (!node) goto done; From 62a291869bac318d5e6760e45979bcd047dcd503 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:45:52 +0530 Subject: [PATCH 092/109] ath9k: Simplify rate table initialization Remove various local variables that duplicate information already stored in mac80211. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 65 ++++++++--------------------- 1 file changed, 17 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e034add9cd5a..2188d1ba5764 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1185,8 +1185,6 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, enum ieee80211_band band, bool is_ht) { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - switch(band) { case IEEE80211_BAND_2GHZ: if (is_ht) @@ -1197,7 +1195,6 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, return &ar5416_11na_ratetable; return &ar5416_11a_ratetable; default: - ath_dbg(common, CONFIG, "Invalid band\n"); return NULL; } } @@ -1278,8 +1275,7 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->ht_cap); } -static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, - bool is_cw40, bool is_sgi) +static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta) { u8 caps = 0; @@ -1289,9 +1285,10 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; else if (sta->ht_cap.mcs.rx_mask[1]) caps |= WLAN_RC_DS_FLAG; - if (is_cw40) + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) caps |= WLAN_RC_40_FLAG; - if (is_sgi) + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40 || + sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) caps |= WLAN_RC_SGI_FLAG; } @@ -1393,9 +1390,9 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { struct ath_softc *sc = priv; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table; - bool is_cw40, is_sgi = false; int i, j = 0; for (i = 0; i < sband->n_bitrates; i++) { @@ -1417,19 +1414,14 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ath_rc_priv->neg_ht_rates.rs_nrates = j; } - is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - - if (is_cw40) - is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); - else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) - is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); - - /* Choose rate table first */ - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported); + sta->ht_cap.ht_supported); + if (!rate_table) { + ath_err(common, "No rate table chosen\n"); + return; + } - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); ath_rc_init(sc, priv_sta, sband, sta, rate_table); } @@ -1440,39 +1432,16 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table = NULL; - bool oper_cw40 = false, oper_sgi; - bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); - bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG); - - /* FIXME: Handle AP mode later when we support CWM */ if (changed & IEEE80211_RC_BW_CHANGED) { - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) - return; - - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - oper_cw40 = true; - - if (oper_cw40) - oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - true : false; - else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) - oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - true : false; - else - oper_sgi = false; - - if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { - rate_table = ath_choose_rate_table(sc, sband->band, + rate_table = ath_choose_rate_table(sc, sband->band, sta->ht_cap.ht_supported); - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, - oper_cw40, oper_sgi); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); + ath_rc_init(sc, priv_sta, sband, sta, rate_table); - ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); - } + ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, + "Operating HT Bandwidth changed to: %d\n", + sc->hw->conf.channel_type); } } From ea2771f642315847cdc0d392602fa3039af41743 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:04 +0530 Subject: [PATCH 093/109] ath9k: Cleanup RC init API A reference to the rate table is stored inside the private structure, so there is no need to pass "rate_table" around. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 99 ++++++++++------------------- 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2188d1ba5764..49c71da9edb2 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -405,9 +405,9 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, return rix; } -static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv) +static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; u8 i, j, idx, idx_next; for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { @@ -424,14 +424,6 @@ static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, } } -static void ath_rc_init_valid_rate_idx(struct ath_rate_priv *ath_rc_priv) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->rate_table_size; i++) - ath_rc_priv->valid_rate_index[i] = 0; -} - static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv, u8 index, int valid_tx_rate) { @@ -495,10 +487,9 @@ ath_rc_get_lower_rix(const struct ath_rate_table *rate_table, return 0; } -static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - u32 capflag) +static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; u8 i, hi = 0; for (i = 0; i < rate_table->rate_cnt; i++) { @@ -506,7 +497,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, u32 phy = rate_table->info[i].phy; u8 valid_rate_count = 0; - if (!ath_rc_valid_phyrate(phy, capflag, 0)) + if (!ath_rc_valid_phyrate(phy, ath_rc_priv->ht_cap, 0)) continue; valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; @@ -521,14 +512,13 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, return hi; } -static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - struct ath_rateset *rateset, - u32 capflag) +static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; + struct ath_rateset *rateset = &ath_rc_priv->neg_rates; + u32 capflag = ath_rc_priv->ht_cap; u8 i, j, hi = 0; - /* Use intersection of working rates and valid rates */ for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; @@ -565,13 +555,13 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, return hi; } -static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - struct ath_rateset *rateset, u32 capflag) +static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; + struct ath_rateset *rateset = &ath_rc_priv->neg_ht_rates; + u32 capflag = ath_rc_priv->ht_cap; u8 i, j, hi = 0; - /* Use intersection of working rates and valid rates */ for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; @@ -1200,28 +1190,20 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, } static void ath_rc_init(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, - const struct ath_rate_table *rate_table) + struct ath_rate_priv *ath_rc_priv) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; struct ath_rateset *rateset = &ath_rc_priv->neg_rates; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_rateset *ht_mcs = &ath_rc_priv->neg_ht_rates; u8 i, j, k, hi = 0, hthi = 0; - /* Initial rate table size. Will change depending - * on the working rate set */ ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; - /* Initialize thresholds according to the global rate table */ for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { ath_rc_priv->per[i] = 0; + ath_rc_priv->valid_rate_index[i] = 0; } - /* Determine the valid rates */ - ath_rc_init_valid_rate_idx(ath_rc_priv); - for (i = 0; i < WLAN_RC_PHY_MAX; i++) { for (j = 0; j < RATE_TABLE_SIZE; j++) ath_rc_priv->valid_phy_rateidx[i][j] = 0; @@ -1229,25 +1211,19 @@ static void ath_rc_init(struct ath_softc *sc, } if (!rateset->rs_nrates) { - /* No working rate, just initialize valid rates */ - hi = ath_rc_init_validrates(ath_rc_priv, rate_table, - ath_rc_priv->ht_cap); + hi = ath_rc_init_validrates(ath_rc_priv); } else { - /* Use intersection of working rates and valid rates */ - hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, - rateset, ath_rc_priv->ht_cap); - if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { - hthi = ath_rc_setvalid_htrates(ath_rc_priv, - rate_table, - ht_mcs, - ath_rc_priv->ht_cap); - } + hi = ath_rc_setvalid_rates(ath_rc_priv); + + if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) + hthi = ath_rc_setvalid_htrates(ath_rc_priv); + hi = max(hi, hthi); } ath_rc_priv->rate_table_size = hi + 1; ath_rc_priv->rate_max_phy = 0; - BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); + WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { @@ -1255,21 +1231,20 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->valid_phy_rateidx[i][j]; } - if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) - || !ath_rc_priv->valid_phy_ratecnt[i]) + if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) || + !ath_rc_priv->valid_phy_ratecnt[i]) continue; ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; } - BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); - BUG_ON(k > RATE_TABLE_SIZE); + WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); + WARN_ON(k > RATE_TABLE_SIZE); ath_rc_priv->max_valid_rate = k; - ath_rc_sort_validrates(rate_table, ath_rc_priv); + ath_rc_sort_validrates(ath_rc_priv); ath_rc_priv->rate_max_phy = (k > 4) ? - ath_rc_priv->valid_rate_index[k-4] : - ath_rc_priv->valid_rate_index[k-1]; - ath_rc_priv->rate_table = rate_table; + ath_rc_priv->valid_rate_index[k-4] : + ath_rc_priv->valid_rate_index[k-1]; ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n", ath_rc_priv->ht_cap); @@ -1392,7 +1367,6 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ath_softc *sc = priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table; int i, j = 0; for (i = 0; i < sband->n_bitrates; i++) { @@ -1414,15 +1388,15 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, ath_rc_priv->neg_ht_rates.rs_nrates = j; } - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported); - if (!rate_table) { + ath_rc_priv->rate_table = ath_choose_rate_table(sc, sband->band, + sta->ht_cap.ht_supported); + if (!ath_rc_priv->rate_table) { ath_err(common, "No rate table chosen\n"); return; } ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); + ath_rc_init(sc, priv_sta); } static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, @@ -1431,13 +1405,10 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table = NULL; if (changed & IEEE80211_RC_BW_CHANGED) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported); ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); + ath_rc_init(sc, priv_sta); ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, "Operating HT Bandwidth changed to: %d\n", From c05ea151770f6508e611b789f84c8bf57fa267cd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:11 +0530 Subject: [PATCH 094/109] ath9k: Cleanup ath_rc_setvalid_rates Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 47 ++++++++++++----------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 49c71da9edb2..a34f678fc57b 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -516,39 +516,32 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv) { const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; struct ath_rateset *rateset = &ath_rc_priv->neg_rates; - u32 capflag = ath_rc_priv->ht_cap; - u8 i, j, hi = 0; + u32 phy, capflag = ath_rc_priv->ht_cap; + u16 rate_flags; + u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u16 rate_flags = rate_table->info[j].rate_flags; - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; + phy = rate_table->info[j].phy; + rate_flags = rate_table->info[j].rate_flags; + rate = rateset->rs_rates[i]; + dot11rate = rate_table->info[j].dot11rate; - /* We allow a rate only if its valid and the - * capflag matches one of the validity - * (VALID/VALID_20/VALID_40) flags */ + if (rate != dot11rate + || ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != + WLAN_RC_CAP_MODE(capflag)) + || !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) + || WLAN_RC_PHY_HT(phy)) + continue; - if ((rate == dot11rate) && - (rate_flags & WLAN_RC_CAP_MODE(capflag)) == - WLAN_RC_CAP_MODE(capflag) && - (rate_flags & WLAN_RC_CAP_STREAM(capflag)) && - !WLAN_RC_PHY_HT(phy)) { - u8 valid_rate_count = 0; + if (!ath_rc_valid_phyrate(phy, capflag, 0)) + continue; - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = - ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy] - [valid_rate_count] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); - hi = max(hi, j); - } + valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; + ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; + ath_rc_priv->valid_phy_ratecnt[phy] += 1; + ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); + hi = max(hi, j); } } From dacde3570865202fedcfa7c642d6c2ffde0dd0af Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:18 +0530 Subject: [PATCH 095/109] ath9k: Cleanup ath_rc_setvalid_htrates Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a34f678fc57b..69745ad6e171 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -552,15 +552,16 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) { const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; struct ath_rateset *rateset = &ath_rc_priv->neg_ht_rates; - u32 capflag = ath_rc_priv->ht_cap; - u8 i, j, hi = 0; + u32 phy, capflag = ath_rc_priv->ht_cap; + u16 rate_flags; + u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u16 rate_flags = rate_table->info[j].rate_flags; - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; + phy = rate_table->info[j].phy; + rate_flags = rate_table->info[j].rate_flags; + rate = rateset->rs_rates[i]; + dot11rate = rate_table->info[j].dot11rate; if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) || !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) || @@ -570,8 +571,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) if (!ath_rc_valid_phyrate(phy, capflag, 0)) continue; - ath_rc_priv->valid_phy_rateidx[phy] - [ath_rc_priv->valid_phy_ratecnt[phy]] = j; + valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; + ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; ath_rc_priv->valid_phy_ratecnt[phy] += 1; ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); hi = max(hi, j); From fc8d023834f6462e1675a28a15da251b3cb28b9a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:24 +0530 Subject: [PATCH 096/109] ath9k: Cleanup index retrieval routines Trim API and remove unused variables. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 56 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 69745ad6e171..2e517c0edccd 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -471,8 +471,7 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) } static inline int -ath_rc_get_lower_rix(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, +ath_rc_get_lower_rix(struct ath_rate_priv *ath_rc_priv, u8 cur_valid_txrate, u8 *next_idx) { int8_t i; @@ -582,13 +581,11 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) return hi; } -/* Finds the highest rate index we can use */ -static u8 ath_rc_get_highest_rix(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, +static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv, int *is_probing, bool legacy) { + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; u32 best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; int8_t index = 0; @@ -773,14 +770,8 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate = 4; rate_table = ath_rc_priv->rate_table; - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, - &is_probe, false); + rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe, false); - /* - * If we're in HT mode and both us and our peer supports LDPC. - * We don't need to check our own device's capabilities as our own - * ht capabilities would have already been intersected with our peer's. - */ if (conf_is_ht(&sc->hw->conf) && (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) tx_info->flags |= IEEE80211_TX_CTL_LDPC; @@ -790,35 +781,42 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT); if (is_probe) { - /* set one try for probe rates. For the - * probes don't enable rts */ + /* + * Set one try for probe rates. For the + * probes don't enable RTS. + */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, 1, rix, 0); - - /* Get the next tried/allowed rate. No RTS for the next series - * after the probe rate + /* + * Get the next tried/allowed rate. + * No RTS for the next series after the probe rate. */ - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); + ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, rix, 0); tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { - /* Set the chosen rate. No RTS for first series entry. */ + /* + * Set the chosen rate. No RTS for first series entry. + */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, rix, 0); } - /* Fill in the other rates for multirate retry */ for ( ; i < 3; i++) { + ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); - /* All other rates in the series have RTS enabled */ + /* + * All other rates in the series have RTS enabled. + */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_per_rate, rix, 1); } - /* Use twice the number of tries for the last MRR segment. */ + /* + * Use twice the number of tries for the last MRR segment. + */ try_per_rate = 8; /* @@ -827,11 +825,11 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, * as last retry to ensure that the frame is tried in both * MCS and legacy rate. */ - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); + ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); + if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) && (ath_rc_priv->per[rix] > 45)) - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, - &is_probe, true); + rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe, true); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, @@ -1061,8 +1059,8 @@ static void ath_rc_update_ht(struct ath_softc *sc, if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && rate_table->info[tx_rate].ratekbps <= rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { - ath_rc_get_lower_rix(rate_table, ath_rc_priv, - (u8)tx_rate, &ath_rc_priv->rate_max_phy); + ath_rc_get_lower_rix(ath_rc_priv, (u8)tx_rate, + &ath_rc_priv->rate_max_phy); /* Don't probe for a little while. */ ath_rc_priv->probe_time = now_msec; From 6e1e3743227119e66162f701d73314d0a26dfafe Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:31 +0530 Subject: [PATCH 097/109] ath9k: Change rateset calculation Commit "ath9k: Change rate control to use legacy rate as last MRR" resulted in the mixing of HT/legacy rates in a single rateset, which is undesirable. Revert this behavior. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 35 ++++++++--------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2e517c0edccd..e8f8e3d73574 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -582,8 +582,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) } static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv, - int *is_probing, - bool legacy) + int *is_probing) { const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; u32 best_thruput, this_thruput, now_msec; @@ -605,8 +604,6 @@ static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv, u8 per_thres; rate = ath_rc_priv->valid_rate_index[index]; - if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY)) - continue; if (rate > ath_rc_priv->rate_max_phy) continue; @@ -770,7 +767,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate = 4; rate_table = ath_rc_priv->rate_table; - rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe, false); + rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe); if (conf_is_ht(&sc->hw->conf) && (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) @@ -804,7 +801,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate, rix, 0); } - for ( ; i < 3; i++) { + for ( ; i < 4; i++) { + /* + * Use twice the number of tries for the last MRR segment. + */ + if (i + 1 == 4) + try_per_rate = 8; + ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); /* @@ -814,26 +817,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, try_per_rate, rix, 1); } - /* - * Use twice the number of tries for the last MRR segment. - */ - try_per_rate = 8; - - /* - * If the last rate in the rate series is MCS and has - * more than 80% of per thresh, then use a legacy rate - * as last retry to ensure that the frame is tried in both - * MCS and legacy rate. - */ - ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); - - if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) && - (ath_rc_priv->per[rix] > 45)) - rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe, true); - - /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_per_rate, rix, 1); /* * NB:Change rate series to enable aggregation when operating * at lower MCS rates. When first rate in series is MCS2 From f5c9a804935029a70f14c0336ac054af9b1953a5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:37 +0530 Subject: [PATCH 098/109] ath9k: Remove ath_rc_set_valid_rate_idx Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e8f8e3d73574..8a5fc62cf491 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -424,13 +424,6 @@ static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv) } } -static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv, - u8 index, int valid_tx_rate) -{ - BUG_ON(index > ath_rc_priv->rate_table_size); - ath_rc_priv->valid_rate_index[index] = !!valid_tx_rate; -} - static inline int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, @@ -503,7 +496,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv) ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_rate_idx(ath_rc_priv, i, 1); + ath_rc_priv->valid_rate_index[i] = true; hi = i; } } @@ -539,7 +532,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv) valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); + ath_rc_priv->valid_rate_index[j] = true; hi = max(hi, j); } } @@ -573,7 +566,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); + ath_rc_priv->valid_rate_index[j] = true; hi = max(hi, j); } } From 3d2776f62140369619b0e6c13ea19b814eed03b4 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:44 +0530 Subject: [PATCH 099/109] ath9k: Unify valid rate calculation routines Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 78 +++++++++++++++-------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8a5fc62cf491..ed48d3d3e6b2 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -504,50 +504,49 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv) return hi; } -static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv) +static inline bool ath_rc_check_legacy(u8 rate, u8 dot11rate, u16 rate_flags, + u32 phy, u32 capflag) { - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - struct ath_rateset *rateset = &ath_rc_priv->neg_rates; - u32 phy, capflag = ath_rc_priv->ht_cap; - u16 rate_flags; - u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; + if (rate != dot11rate || WLAN_RC_PHY_HT(phy)) + return false; - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - phy = rate_table->info[j].phy; - rate_flags = rate_table->info[j].rate_flags; - rate = rateset->rs_rates[i]; - dot11rate = rate_table->info[j].dot11rate; + if ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != WLAN_RC_CAP_MODE(capflag)) + return false; - if (rate != dot11rate - || ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != - WLAN_RC_CAP_MODE(capflag)) - || !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) - || WLAN_RC_PHY_HT(phy)) - continue; + if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) + return false; - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; - ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_priv->valid_rate_index[j] = true; - hi = max(hi, j); - } - } - - return hi; + return true; } -static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) +static inline bool ath_rc_check_ht(u8 rate, u8 dot11rate, u16 rate_flags, + u32 phy, u32 capflag) +{ + if (rate != dot11rate || !WLAN_RC_PHY_HT(phy)) + return false; + + if (!WLAN_RC_PHY_HT_VALID(rate_flags, capflag)) + return false; + + if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) + return false; + + return true; +} + +static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, bool legacy) { const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - struct ath_rateset *rateset = &ath_rc_priv->neg_ht_rates; + struct ath_rateset *rateset; u32 phy, capflag = ath_rc_priv->ht_cap; u16 rate_flags; u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; + if (legacy) + rateset = &ath_rc_priv->neg_rates; + else + rateset = &ath_rc_priv->neg_ht_rates; + for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { phy = rate_table->info[j].phy; @@ -555,9 +554,14 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv) rate = rateset->rs_rates[i]; dot11rate = rate_table->info[j].dot11rate; - if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) || - !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) || - !WLAN_RC_PHY_HT_VALID(rate_flags, capflag)) + if (legacy && + !ath_rc_check_legacy(rate, dot11rate, + rate_flags, phy, capflag)) + continue; + + if (!legacy && + !ath_rc_check_ht(rate, dot11rate, + rate_flags, phy, capflag)) continue; if (!ath_rc_valid_phyrate(phy, capflag, 0)) @@ -1181,10 +1185,10 @@ static void ath_rc_init(struct ath_softc *sc, if (!rateset->rs_nrates) { hi = ath_rc_init_validrates(ath_rc_priv); } else { - hi = ath_rc_setvalid_rates(ath_rc_priv); + hi = ath_rc_setvalid_rates(ath_rc_priv, true); if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) - hthi = ath_rc_setvalid_htrates(ath_rc_priv); + hthi = ath_rc_setvalid_rates(ath_rc_priv, false); hi = max(hi, hthi); } From 97f7e8a785b9877098d7f255654b25bf85ae9d6a Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:50 +0530 Subject: [PATCH 100/109] ath9k: Do not set IEEE80211_TX_RC_USE_SHORT_PREAMBLE mac80211 does it for us. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ed48d3d3e6b2..78192c19fe54 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -682,8 +682,6 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, rate->count = tries; rate->idx = rate_table->info[rix].ratecode; - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; if (txrc->rts || rtsctsenable) rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; From 2e546755b947c08cdc1c4f2bdba70130c6ed0736 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:46:57 +0530 Subject: [PATCH 101/109] ath9k: Fix RTS/CTS rate selection The current method of assigning the RTS/CTS rate is completely broken for HT mode and breaks P2P operation. Fix this by using the basic_rates provided to the driver by mac80211. For now, choose the lowest supported basic rate for HT frames. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 41 ++++++++++------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 78192c19fe54..a94c52b24a0b 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -699,37 +699,25 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, const struct ath_rate_table *rate_table, struct ieee80211_tx_info *tx_info) { - struct ieee80211_tx_rate *rates = tx_info->control.rates; - int i = 0, rix = 0, cix, enable_g_protection = 0; + struct ieee80211_bss_conf *bss_conf; - /* get the cix for the lowest valid rix */ - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { - rix = ath_rc_get_rateindex(rate_table, &rates[i]); - break; - } - } - cix = rate_table->info[rix].ctrl_rate; + if (!tx_info->control.vif) + return; + /* + * For legacy frames, mac80211 takes care of CTS protection. + */ + if (!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) + return; - /* All protection frames are transmited at 2Mb/s for 802.11g, - * otherwise we transmit them at 1Mb/s */ - if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ && - !conf_is_ht(&sc->hw->conf)) - enable_g_protection = 1; + bss_conf = &tx_info->control.vif->bss_conf; + + if (!bss_conf->basic_rates) + return; /* - * If 802.11g protection is enabled, determine whether to use RTS/CTS or - * just CTS. Note that this is only done for OFDM/HT unicast frames. + * For now, use the lowest allowed basic rate for HT frames. */ - if ((tx_info->control.vif && - tx_info->control.vif->bss_conf.use_cts_prot) && - (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || - WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { - rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; - cix = rate_table->info[enable_g_protection].ctrl_rate; - } - - tx_info->control.rts_cts_rate_idx = cix; + tx_info->control.rts_cts_rate_idx = __ffs(bss_conf->basic_rates); } static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, @@ -853,7 +841,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, rates[0].count = ATH_TXMAXTRY; } - /* Setup RTS/CTS */ ath_rc_rate_set_rtscts(sc, rate_table, tx_info); } From c1610117f81ae70b49aaf51ccb9040f2ce5bd358 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:47:03 +0530 Subject: [PATCH 102/109] ath9k: Bail out properly before calculating rate index Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a94c52b24a0b..0e3d20a864e6 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1264,23 +1264,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; int final_ts_idx = 0, tx_status = 0; int long_retry = 0; - __le16 fc; + __le16 fc = hdr->frame_control; int i; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - for (i = 0; i < sc->hw->max_rates; i++) { - struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; - if (rate->idx < 0 || !rate->count) - break; - - final_ts_idx = i; - long_retry = rate->count - 1; - } - if (!priv_sta || !ieee80211_is_data(fc)) return; @@ -1292,6 +1281,15 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) return; + for (i = 0; i < sc->hw->max_rates; i++) { + struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; + if (rate->idx < 0 || !rate->count) + break; + + final_ts_idx = i; + long_retry = rate->count - 1; + } + if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) tx_status = 1; From 88dcc2dd717b292d1ef7311a6487c610f709bd10 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:47:09 +0530 Subject: [PATCH 103/109] ath9k: Cleanup TX status API Calculate the final rate index inside ath_rc_tx_status(). Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 71 ++++++++++++----------------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 0e3d20a864e6..2051fac82582 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -993,9 +993,6 @@ static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, stats->per = per; } -/* Update PER, RSSI and whatever else that the code thinks it is doing. - If you can make sense of all this, you really need to go out more. */ - static void ath_rc_update_ht(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_info *tx_info, @@ -1069,25 +1066,43 @@ static void ath_rc_update_ht(struct ath_softc *sc, } +static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) +{ + struct ath_rc_stats *stats; + + stats = &rc->rcstats[final_rate]; + stats->success++; +} static void ath_rc_tx_status(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int final_ts_idx, int xretries, int long_retry) + struct sk_buff *skb) { - const struct ath_rate_table *rate_table; + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->status.rates; + struct ieee80211_tx_rate *rate; + int final_ts_idx = 0, xretries = 0, long_retry = 0; u8 flags; u32 i = 0, rix; - rate_table = ath_rc_priv->rate_table; + for (i = 0; i < sc->hw->max_rates; i++) { + rate = &tx_info->status.rates[i]; + if (rate->idx < 0 || !rate->count) + break; + + final_ts_idx = i; + long_retry = rate->count - 1; + } + + if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) + xretries = 1; /* * If the first rate is not the final index, there * are intermediate rate failures to be processed. */ if (final_ts_idx != 0) { - /* Process intermediate rates that failed.*/ for (i = 0; i < final_ts_idx ; i++) { if (rates[i].count != 0 && (rates[i].idx >= 0)) { flags = rates[i].flags; @@ -1101,8 +1116,8 @@ static void ath_rc_tx_status(struct ath_softc *sc, rix = ath_rc_get_rateindex(rate_table, &rates[i]); ath_rc_update_ht(sc, ath_rc_priv, tx_info, - rix, xretries ? 1 : 2, - rates[i].count); + rix, xretries ? 1 : 2, + rates[i].count); } } } else { @@ -1116,15 +1131,16 @@ static void ath_rc_tx_status(struct ath_softc *sc, xretries = 2; } - flags = rates[i].flags; + flags = rates[final_ts_idx].flags; /* If HT40 and we have switched mode from 40 to 20 => don't update */ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; - rix = ath_rc_get_rateindex(rate_table, &rates[i]); + rix = ath_rc_get_rateindex(rate_table, &rates[final_ts_idx]); ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry); + ath_debug_stat_rc(ath_rc_priv, rix); } static const @@ -1248,15 +1264,6 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta, /* mac80211 Rate Control callbacks */ /***********************************/ -static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) -{ - struct ath_rc_stats *stats; - - stats = &rc->rcstats[final_rate]; - stats->success++; -} - - static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) @@ -1265,10 +1272,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, struct ath_rate_priv *ath_rc_priv = priv_sta; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int final_ts_idx = 0, tx_status = 0; - int long_retry = 0; __le16 fc = hdr->frame_control; - int i; if (!priv_sta || !ieee80211_is_data(fc)) return; @@ -1281,20 +1285,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) return; - for (i = 0; i < sc->hw->max_rates; i++) { - struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; - if (rate->idx < 0 || !rate->count) - break; - - final_ts_idx = i; - long_retry = rate->count - 1; - } - - if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) - tx_status = 1; - - ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, - long_retry); + ath_rc_tx_status(sc, ath_rc_priv, skb); /* Check if aggregation has to be enabled for this tid */ if (conf_is_ht(&sc->hw->conf) && @@ -1310,10 +1301,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, ieee80211_start_tx_ba_session(sta, tid, 0); } } - - ath_debug_stat_rc(ath_rc_priv, - ath_rc_get_rateindex(ath_rc_priv->rate_table, - &tx_info->status.rates[final_ts_idx])); } static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, From f8a87017f4a9f1638df54dd79d0f5ad1bae51c1d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:47:16 +0530 Subject: [PATCH 104/109] ath9k: Remove MIMO-PS specific code Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2051fac82582..cce0c516b3c4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1120,15 +1120,6 @@ static void ath_rc_tx_status(struct ath_softc *sc, rates[i].count); } } - } else { - /* - * Handle the special case of MIMO PS burst, where the second - * aggregate is sent out with only one rate and one try. - * Treating it as an excessive retry penalizes the rate - * inordinately. - */ - if (rates[0].count == 1 && xretries == 1) - xretries = 2; } flags = rates[final_ts_idx].flags; From 23d9939459362c555d2ad18f9c036f55594e7fee Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 10 Aug 2012 16:47:23 +0530 Subject: [PATCH 105/109] ath9k: Trim rate table Remove ctrl_rate, cw40index, sgi_index, ht_index and calculate the rate index for TX status from the valid_rate_index that is populated at initialization time. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 350 ++++++++++++++-------------- drivers/net/wireless/ath/ath9k/rc.h | 4 - 2 files changed, 174 insertions(+), 180 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index cce0c516b3c4..4a04fff291e8 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -25,141 +25,141 @@ static const struct ath_rate_table ar5416_11na_ratetable = { 8, /* MCS start */ { [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, - 5400, 0, 12, 0, 0, 0, 0 }, /* 6 Mb */ + 5400, 0, 12 }, /* 6 Mb */ [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, - 7800, 1, 18, 0, 1, 1, 1 }, /* 9 Mb */ + 7800, 1, 18 }, /* 9 Mb */ [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, - 10000, 2, 24, 2, 2, 2, 2 }, /* 12 Mb */ + 10000, 2, 24 }, /* 12 Mb */ [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, - 13900, 3, 36, 2, 3, 3, 3 }, /* 18 Mb */ + 13900, 3, 36 }, /* 18 Mb */ [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, - 17300, 4, 48, 4, 4, 4, 4 }, /* 24 Mb */ + 17300, 4, 48 }, /* 24 Mb */ [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, - 23000, 5, 72, 4, 5, 5, 5 }, /* 36 Mb */ + 23000, 5, 72 }, /* 36 Mb */ [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, - 27400, 6, 96, 4, 6, 6, 6 }, /* 48 Mb */ + 27400, 6, 96 }, /* 48 Mb */ [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, - 29300, 7, 108, 4, 7, 7, 7 }, /* 54 Mb */ + 29300, 7, 108 }, /* 54 Mb */ [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500, - 6400, 0, 0, 0, 38, 8, 38 }, /* 6.5 Mb */ + 6400, 0, 0 }, /* 6.5 Mb */ [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, - 12700, 1, 1, 2, 39, 9, 39 }, /* 13 Mb */ + 12700, 1, 1 }, /* 13 Mb */ [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, - 18800, 2, 2, 2, 40, 10, 40 }, /* 19.5 Mb */ + 18800, 2, 2 }, /* 19.5 Mb */ [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, - 25000, 3, 3, 4, 41, 11, 41 }, /* 26 Mb */ + 25000, 3, 3 }, /* 26 Mb */ [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, - 36700, 4, 4, 4, 42, 12, 42 }, /* 39 Mb */ + 36700, 4, 4 }, /* 39 Mb */ [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, - 48100, 5, 5, 4, 43, 13, 43 }, /* 52 Mb */ + 48100, 5, 5 }, /* 52 Mb */ [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, - 53500, 6, 6, 4, 44, 14, 44 }, /* 58.5 Mb */ + 53500, 6, 6 }, /* 58.5 Mb */ [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, - 59000, 7, 7, 4, 45, 16, 46 }, /* 65 Mb */ + 59000, 7, 7 }, /* 65 Mb */ [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, - 65400, 7, 7, 4, 45, 16, 46 }, /* 75 Mb */ + 65400, 7, 7 }, /* 75 Mb */ [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, - 12700, 8, 8, 0, 47, 17, 47 }, /* 13 Mb */ + 12700, 8, 8 }, /* 13 Mb */ [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, - 24800, 9, 9, 2, 48, 18, 48 }, /* 26 Mb */ + 24800, 9, 9 }, /* 26 Mb */ [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, - 36600, 10, 10, 2, 49, 19, 49 }, /* 39 Mb */ + 36600, 10, 10 }, /* 39 Mb */ [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, - 48100, 11, 11, 4, 50, 20, 50 }, /* 52 Mb */ + 48100, 11, 11 }, /* 52 Mb */ [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, - 69500, 12, 12, 4, 51, 21, 51 }, /* 78 Mb */ + 69500, 12, 12 }, /* 78 Mb */ [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, - 89500, 13, 13, 4, 52, 22, 52 }, /* 104 Mb */ + 89500, 13, 13 }, /* 104 Mb */ [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, - 98900, 14, 14, 4, 53, 23, 53 }, /* 117 Mb */ + 98900, 14, 14 }, /* 117 Mb */ [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, - 108300, 15, 15, 4, 54, 25, 55 }, /* 130 Mb */ + 108300, 15, 15 }, /* 130 Mb */ [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, - 120000, 15, 15, 4, 54, 25, 55 }, /* 144.4 Mb */ + 120000, 15, 15 }, /* 144.4 Mb */ [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, - 17400, 16, 16, 0, 56, 26, 56 }, /* 19.5 Mb */ + 17400, 16, 16 }, /* 19.5 Mb */ [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, - 35100, 17, 17, 2, 57, 27, 57 }, /* 39 Mb */ + 35100, 17, 17 }, /* 39 Mb */ [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, - 52600, 18, 18, 2, 58, 28, 58 }, /* 58.5 Mb */ + 52600, 18, 18 }, /* 58.5 Mb */ [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, - 70400, 19, 19, 4, 59, 29, 59 }, /* 78 Mb */ + 70400, 19, 19 }, /* 78 Mb */ [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, - 104900, 20, 20, 4, 60, 31, 61 }, /* 117 Mb */ + 104900, 20, 20 }, /* 117 Mb */ [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, - 115800, 20, 20, 4, 60, 31, 61 }, /* 130 Mb*/ + 115800, 20, 20 }, /* 130 Mb*/ [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, - 137200, 21, 21, 4, 62, 33, 63 }, /* 156 Mb */ + 137200, 21, 21 }, /* 156 Mb */ [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, - 151100, 21, 21, 4, 62, 33, 63 }, /* 173.3 Mb */ + 151100, 21, 21 }, /* 173.3 Mb */ [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, - 152800, 22, 22, 4, 64, 35, 65 }, /* 175.5 Mb */ + 152800, 22, 22 }, /* 175.5 Mb */ [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, - 168400, 22, 22, 4, 64, 35, 65 }, /* 195 Mb*/ + 168400, 22, 22 }, /* 195 Mb*/ [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, - 168400, 23, 23, 4, 66, 37, 67 }, /* 195 Mb */ + 168400, 23, 23 }, /* 195 Mb */ [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, - 185000, 23, 23, 4, 66, 37, 67 }, /* 216.7 Mb */ + 185000, 23, 23 }, /* 216.7 Mb */ [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, - 13200, 0, 0, 0, 38, 38, 38 }, /* 13.5 Mb*/ + 13200, 0, 0 }, /* 13.5 Mb*/ [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, - 25900, 1, 1, 2, 39, 39, 39 }, /* 27.0 Mb*/ + 25900, 1, 1 }, /* 27.0 Mb*/ [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, - 38600, 2, 2, 2, 40, 40, 40 }, /* 40.5 Mb*/ + 38600, 2, 2 }, /* 40.5 Mb*/ [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, - 49800, 3, 3, 4, 41, 41, 41 }, /* 54 Mb */ + 49800, 3, 3 }, /* 54 Mb */ [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, - 72200, 4, 4, 4, 42, 42, 42 }, /* 81 Mb */ + 72200, 4, 4 }, /* 81 Mb */ [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000, - 92900, 5, 5, 4, 43, 43, 43 }, /* 108 Mb */ + 92900, 5, 5 }, /* 108 Mb */ [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, - 102700, 6, 6, 4, 44, 44, 44 }, /* 121.5 Mb*/ + 102700, 6, 6 }, /* 121.5 Mb*/ [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, - 112000, 7, 7, 4, 45, 46, 46 }, /* 135 Mb */ + 112000, 7, 7 }, /* 135 Mb */ [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, - 122000, 7, 7, 4, 45, 46, 46 }, /* 150 Mb */ + 122000, 7, 7 }, /* 150 Mb */ [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, - 25800, 8, 8, 0, 47, 47, 47 }, /* 27 Mb */ + 25800, 8, 8 }, /* 27 Mb */ [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, - 49800, 9, 9, 2, 48, 48, 48 }, /* 54 Mb */ + 49800, 9, 9 }, /* 54 Mb */ [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, - 71900, 10, 10, 2, 49, 49, 49 }, /* 81 Mb */ + 71900, 10, 10 }, /* 81 Mb */ [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, - 92500, 11, 11, 4, 50, 50, 50 }, /* 108 Mb */ + 92500, 11, 11 }, /* 108 Mb */ [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, - 130300, 12, 12, 4, 51, 51, 51 }, /* 162 Mb */ + 130300, 12, 12 }, /* 162 Mb */ [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, - 162800, 13, 13, 4, 52, 52, 52 }, /* 216 Mb */ + 162800, 13, 13 }, /* 216 Mb */ [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, - 178200, 14, 14, 4, 53, 53, 53 }, /* 243 Mb */ + 178200, 14, 14 }, /* 243 Mb */ [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, - 192100, 15, 15, 4, 54, 55, 55 }, /* 270 Mb */ + 192100, 15, 15 }, /* 270 Mb */ [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, - 207000, 15, 15, 4, 54, 55, 55 }, /* 300 Mb */ + 207000, 15, 15 }, /* 300 Mb */ [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, - 36100, 16, 16, 0, 56, 56, 56 }, /* 40.5 Mb */ + 36100, 16, 16 }, /* 40.5 Mb */ [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, - 72900, 17, 17, 2, 57, 57, 57 }, /* 81 Mb */ + 72900, 17, 17 }, /* 81 Mb */ [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, - 108300, 18, 18, 2, 58, 58, 58 }, /* 121.5 Mb */ + 108300, 18, 18 }, /* 121.5 Mb */ [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, - 142000, 19, 19, 4, 59, 59, 59 }, /* 162 Mb */ + 142000, 19, 19 }, /* 162 Mb */ [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, - 205100, 20, 20, 4, 60, 61, 61 }, /* 243 Mb */ + 205100, 20, 20 }, /* 243 Mb */ [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, - 224700, 20, 20, 4, 60, 61, 61 }, /* 270 Mb */ + 224700, 20, 20 }, /* 270 Mb */ [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, - 263100, 21, 21, 4, 62, 63, 63 }, /* 324 Mb */ + 263100, 21, 21 }, /* 324 Mb */ [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, - 288000, 21, 21, 4, 62, 63, 63 }, /* 360 Mb */ + 288000, 21, 21 }, /* 360 Mb */ [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, - 290700, 22, 22, 4, 64, 65, 65 }, /* 364.5 Mb */ + 290700, 22, 22 }, /* 364.5 Mb */ [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, - 317200, 22, 22, 4, 64, 65, 65 }, /* 405 Mb */ + 317200, 22, 22 }, /* 405 Mb */ [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, - 317200, 23, 23, 4, 66, 67, 67 }, /* 405 Mb */ + 317200, 23, 23 }, /* 405 Mb */ [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, - 346400, 23, 23, 4, 66, 67, 67 }, /* 450 Mb */ + 346400, 23, 23 }, /* 450 Mb */ }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -173,149 +173,149 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { 12, /* MCS start */ { [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000, - 900, 0, 2, 0, 0, 0, 0 }, /* 1 Mb */ + 900, 0, 2 }, /* 1 Mb */ [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000, - 1900, 1, 4, 1, 1, 1, 1 }, /* 2 Mb */ + 1900, 1, 4 }, /* 2 Mb */ [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500, - 4900, 2, 11, 2, 2, 2, 2 }, /* 5.5 Mb */ + 4900, 2, 11 }, /* 5.5 Mb */ [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000, - 8100, 3, 22, 3, 3, 3, 3 }, /* 11 Mb */ + 8100, 3, 22 }, /* 11 Mb */ [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, - 5400, 4, 12, 4, 4, 4, 4 }, /* 6 Mb */ + 5400, 4, 12 }, /* 6 Mb */ [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, - 7800, 5, 18, 4, 5, 5, 5 }, /* 9 Mb */ + 7800, 5, 18 }, /* 9 Mb */ [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, - 10100, 6, 24, 6, 6, 6, 6 }, /* 12 Mb */ + 10100, 6, 24 }, /* 12 Mb */ [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, - 14100, 7, 36, 6, 7, 7, 7 }, /* 18 Mb */ + 14100, 7, 36 }, /* 18 Mb */ [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, - 17700, 8, 48, 8, 8, 8, 8 }, /* 24 Mb */ + 17700, 8, 48 }, /* 24 Mb */ [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, - 23700, 9, 72, 8, 9, 9, 9 }, /* 36 Mb */ + 23700, 9, 72 }, /* 36 Mb */ [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, - 27400, 10, 96, 8, 10, 10, 10 }, /* 48 Mb */ + 27400, 10, 96 }, /* 48 Mb */ [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, - 30900, 11, 108, 8, 11, 11, 11 }, /* 54 Mb */ + 30900, 11, 108 }, /* 54 Mb */ [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500, - 6400, 0, 0, 4, 42, 12, 42 }, /* 6.5 Mb */ + 6400, 0, 0 }, /* 6.5 Mb */ [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, - 12700, 1, 1, 6, 43, 13, 43 }, /* 13 Mb */ + 12700, 1, 1 }, /* 13 Mb */ [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, - 18800, 2, 2, 6, 44, 14, 44 }, /* 19.5 Mb*/ + 18800, 2, 2 }, /* 19.5 Mb*/ [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, - 25000, 3, 3, 8, 45, 15, 45 }, /* 26 Mb */ + 25000, 3, 3 }, /* 26 Mb */ [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, - 36700, 4, 4, 8, 46, 16, 46 }, /* 39 Mb */ + 36700, 4, 4 }, /* 39 Mb */ [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, - 48100, 5, 5, 8, 47, 17, 47 }, /* 52 Mb */ + 48100, 5, 5 }, /* 52 Mb */ [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, - 53500, 6, 6, 8, 48, 18, 48 }, /* 58.5 Mb */ + 53500, 6, 6 }, /* 58.5 Mb */ [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, - 59000, 7, 7, 8, 49, 20, 50 }, /* 65 Mb */ + 59000, 7, 7 }, /* 65 Mb */ [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, - 65400, 7, 7, 8, 49, 20, 50 }, /* 65 Mb*/ + 65400, 7, 7 }, /* 65 Mb*/ [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, - 12700, 8, 8, 4, 51, 21, 51 }, /* 13 Mb */ + 12700, 8, 8 }, /* 13 Mb */ [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, - 24800, 9, 9, 6, 52, 22, 52 }, /* 26 Mb */ + 24800, 9, 9 }, /* 26 Mb */ [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, - 36600, 10, 10, 6, 53, 23, 53 }, /* 39 Mb */ + 36600, 10, 10 }, /* 39 Mb */ [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, - 48100, 11, 11, 8, 54, 24, 54 }, /* 52 Mb */ + 48100, 11, 11 }, /* 52 Mb */ [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, - 69500, 12, 12, 8, 55, 25, 55 }, /* 78 Mb */ + 69500, 12, 12 }, /* 78 Mb */ [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, - 89500, 13, 13, 8, 56, 26, 56 }, /* 104 Mb */ + 89500, 13, 13 }, /* 104 Mb */ [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, - 98900, 14, 14, 8, 57, 27, 57 }, /* 117 Mb */ + 98900, 14, 14 }, /* 117 Mb */ [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, - 108300, 15, 15, 8, 58, 29, 59 }, /* 130 Mb */ + 108300, 15, 15 }, /* 130 Mb */ [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, - 120000, 15, 15, 8, 58, 29, 59 }, /* 144.4 Mb */ + 120000, 15, 15 }, /* 144.4 Mb */ [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, - 17400, 16, 16, 4, 60, 30, 60 }, /* 19.5 Mb */ + 17400, 16, 16 }, /* 19.5 Mb */ [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, - 35100, 17, 17, 6, 61, 31, 61 }, /* 39 Mb */ + 35100, 17, 17 }, /* 39 Mb */ [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, - 52600, 18, 18, 6, 62, 32, 62 }, /* 58.5 Mb */ + 52600, 18, 18 }, /* 58.5 Mb */ [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, - 70400, 19, 19, 8, 63, 33, 63 }, /* 78 Mb */ + 70400, 19, 19 }, /* 78 Mb */ [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, - 104900, 20, 20, 8, 64, 35, 65 }, /* 117 Mb */ + 104900, 20, 20 }, /* 117 Mb */ [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, - 115800, 20, 20, 8, 64, 35, 65 }, /* 130 Mb */ + 115800, 20, 20 }, /* 130 Mb */ [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, - 137200, 21, 21, 8, 66, 37, 67 }, /* 156 Mb */ + 137200, 21, 21 }, /* 156 Mb */ [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, - 151100, 21, 21, 8, 66, 37, 67 }, /* 173.3 Mb */ + 151100, 21, 21 }, /* 173.3 Mb */ [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, - 152800, 22, 22, 8, 68, 39, 69 }, /* 175.5 Mb */ + 152800, 22, 22 }, /* 175.5 Mb */ [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, - 168400, 22, 22, 8, 68, 39, 69 }, /* 195 Mb */ + 168400, 22, 22 }, /* 195 Mb */ [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, - 168400, 23, 23, 8, 70, 41, 71 }, /* 195 Mb */ + 168400, 23, 23 }, /* 195 Mb */ [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, - 185000, 23, 23, 8, 70, 41, 71 }, /* 216.7 Mb */ + 185000, 23, 23 }, /* 216.7 Mb */ [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, - 13200, 0, 0, 8, 42, 42, 42 }, /* 13.5 Mb */ + 13200, 0, 0 }, /* 13.5 Mb */ [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, - 25900, 1, 1, 8, 43, 43, 43 }, /* 27.0 Mb */ + 25900, 1, 1 }, /* 27.0 Mb */ [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, - 38600, 2, 2, 8, 44, 44, 44 }, /* 40.5 Mb */ + 38600, 2, 2 }, /* 40.5 Mb */ [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, - 49800, 3, 3, 8, 45, 45, 45 }, /* 54 Mb */ + 49800, 3, 3 }, /* 54 Mb */ [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, - 72200, 4, 4, 8, 46, 46, 46 }, /* 81 Mb */ + 72200, 4, 4 }, /* 81 Mb */ [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000, - 92900, 5, 5, 8, 47, 47, 47 }, /* 108 Mb */ + 92900, 5, 5 }, /* 108 Mb */ [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, - 102700, 6, 6, 8, 48, 48, 48 }, /* 121.5 Mb */ + 102700, 6, 6 }, /* 121.5 Mb */ [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, - 112000, 7, 7, 8, 49, 50, 50 }, /* 135 Mb */ + 112000, 7, 7 }, /* 135 Mb */ [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, - 122000, 7, 7, 8, 49, 50, 50 }, /* 150 Mb */ + 122000, 7, 7 }, /* 150 Mb */ [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, - 25800, 8, 8, 8, 51, 51, 51 }, /* 27 Mb */ + 25800, 8, 8 }, /* 27 Mb */ [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, - 49800, 9, 9, 8, 52, 52, 52 }, /* 54 Mb */ + 49800, 9, 9 }, /* 54 Mb */ [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, - 71900, 10, 10, 8, 53, 53, 53 }, /* 81 Mb */ + 71900, 10, 10 }, /* 81 Mb */ [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, - 92500, 11, 11, 8, 54, 54, 54 }, /* 108 Mb */ + 92500, 11, 11 }, /* 108 Mb */ [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, - 130300, 12, 12, 8, 55, 55, 55 }, /* 162 Mb */ + 130300, 12, 12 }, /* 162 Mb */ [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, - 162800, 13, 13, 8, 56, 56, 56 }, /* 216 Mb */ + 162800, 13, 13 }, /* 216 Mb */ [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, - 178200, 14, 14, 8, 57, 57, 57 }, /* 243 Mb */ + 178200, 14, 14 }, /* 243 Mb */ [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, - 192100, 15, 15, 8, 58, 59, 59 }, /* 270 Mb */ + 192100, 15, 15 }, /* 270 Mb */ [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, - 207000, 15, 15, 8, 58, 59, 59 }, /* 300 Mb */ + 207000, 15, 15 }, /* 300 Mb */ [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, - 36100, 16, 16, 8, 60, 60, 60 }, /* 40.5 Mb */ + 36100, 16, 16 }, /* 40.5 Mb */ [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, - 72900, 17, 17, 8, 61, 61, 61 }, /* 81 Mb */ + 72900, 17, 17 }, /* 81 Mb */ [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, - 108300, 18, 18, 8, 62, 62, 62 }, /* 121.5 Mb */ + 108300, 18, 18 }, /* 121.5 Mb */ [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, - 142000, 19, 19, 8, 63, 63, 63 }, /* 162 Mb */ + 142000, 19, 19 }, /* 162 Mb */ [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, - 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */ + 205100, 20, 20 }, /* 243 Mb */ [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, - 224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */ + 224700, 20, 20 }, /* 270 Mb */ [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, - 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */ + 263100, 21, 21 }, /* 324 Mb */ [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, - 288000, 21, 21, 8, 66, 67, 67 }, /* 360 Mb */ + 288000, 21, 21 }, /* 360 Mb */ [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, - 290700, 22, 22, 8, 68, 69, 69 }, /* 364.5 Mb */ + 290700, 22, 22 }, /* 364.5 Mb */ [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, - 317200, 22, 22, 8, 68, 69, 69 }, /* 405 Mb */ + 317200, 22, 22 }, /* 405 Mb */ [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, - 317200, 23, 23, 8, 70, 71, 71 }, /* 405 Mb */ + 317200, 23, 23 }, /* 405 Mb */ [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, - 346400, 23, 23, 8, 70, 71, 71 }, /* 450 Mb */ + 346400, 23, 23 }, /* 450 Mb */ }, 50, /* probe interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ @@ -326,21 +326,21 @@ static const struct ath_rate_table ar5416_11a_ratetable = { 0, { { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0, 12, 0}, + 5400, 0, 12}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 1, 18, 0}, + 7800, 1, 18}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 2, 24, 2}, + 10000, 2, 24}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 3, 36, 2}, + 13900, 3, 36}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 4, 48, 4}, + 17300, 4, 48}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 5, 72, 4}, + 23000, 5, 72}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 6, 96, 4}, + 27400, 6, 96}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 7, 108, 4}, + 29300, 7, 108}, }, 50, /* probe interval */ 0, /* Phy rates allowed initially */ @@ -351,56 +351,55 @@ static const struct ath_rate_table ar5416_11g_ratetable = { 0, { { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0, 2, 0}, + 900, 0, 2}, { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 1, 4, 1}, + 1900, 1, 4}, { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 2, 11, 2}, + 4900, 2, 11}, { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 3, 22, 3}, + 8100, 3, 22}, { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 4, 12, 4}, + 5400, 4, 12}, { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 5, 18, 4}, + 7800, 5, 18}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 6, 24, 6}, + 10000, 6, 24}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 7, 36, 6}, + 13900, 7, 36}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 8, 48, 8}, + 17300, 8, 48}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 9, 72, 8}, + 23000, 9, 72}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 10, 96, 8}, + 27400, 10, 96}, { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 11, 108, 8}, + 29300, 11, 108}, }, 50, /* probe interval */ 0, /* Phy rates allowed initially */ }; -static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, +static int ath_rc_get_rateindex(struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_rate *rate) { - int rix = 0, i = 0; - static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; + int rix, i, idx = 0; if (!(rate->flags & IEEE80211_TX_RC_MCS)) return rate->idx; - while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { - rix++; i++; + for (i = 0; i < ath_rc_priv->max_valid_rate; i++) { + idx = ath_rc_priv->valid_rate_index[i]; + + if (WLAN_RC_PHY_HT(rate_table->info[idx].phy) && + rate_table->info[idx].ratecode == rate->idx) + break; } - rix += rate->idx + rate_table->mcs_start; + rix = idx; - if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (rate->flags & IEEE80211_TX_RC_SHORT_GI)) - rix = rate_table->info[rix].ht_index; - else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - rix = rate_table->info[rix].sgi_index; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - rix = rate_table->info[rix].cw40index; + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + rix++; return rix; } @@ -1078,7 +1077,6 @@ static void ath_rc_tx_status(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct sk_buff *skb) { - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->status.rates; struct ieee80211_tx_rate *rate; @@ -1114,7 +1112,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; - rix = ath_rc_get_rateindex(rate_table, &rates[i]); + rix = ath_rc_get_rateindex(ath_rc_priv, &rates[i]); ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries ? 1 : 2, rates[i].count); @@ -1129,7 +1127,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; - rix = ath_rc_get_rateindex(rate_table, &rates[final_ts_idx]); + rix = ath_rc_get_rateindex(ath_rc_priv, &rates[final_ts_idx]); ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry); ath_debug_stat_rc(ath_rc_priv, rix); } diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 75f8e9b06b28..268e67dc5fb2 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -160,10 +160,6 @@ struct ath_rate_table { u32 user_ratekbps; u8 ratecode; u8 dot11rate; - u8 ctrl_rate; - u8 cw40index; - u8 sgi_index; - u8 ht_index; } info[RATE_TABLE_SIZE]; u32 probe_interval; u8 initial_ratemax; From c771b518199eb329c3a38e479b36b36553e25b2d Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 10 Aug 2012 16:47:30 +0530 Subject: [PATCH 106/109] ath9k: tune rc_stats to display only valid rates This could make rc_stats more simpler and ease the debugging. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4a04fff291e8..4b12c347d188 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1355,7 +1355,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, struct ath_rate_priv *rc = file->private_data; char *buf; unsigned int len = 0, max; - int i = 0; + int rix; ssize_t retval; if (rc->rate_table == NULL) @@ -1371,7 +1371,8 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, "HT", "MCS", "Rate", "Success", "Retries", "XRetries", "PER"); - for (i = 0; i < rc->rate_table_size; i++) { + for (rix = 0; rix < rc->max_valid_rate; rix++) { + u8 i = rc->valid_rate_index[rix]; u32 ratekbps = rc->rate_table->info[i].ratekbps; struct ath_rc_stats *stats = &rc->rcstats[i]; char mcs[5]; From faa97bd4a43ac69a55029e3b07708bdff0959c07 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Mon, 6 Aug 2012 15:17:26 -0400 Subject: [PATCH 107/109] brcmsmac: document firmware dependencies The brcmsmac driver requests firmware but doesn't document the dependency. This means that software that analyzes the modules to determine if firmware is needed won't detect it. Specifically, (at least) openSUSE won't install the kernel-firmware package if no hardware requires it. This patch adds the MODULE_FIRMWARE directives. Signed-off-by: Jeff Mahoney Acked-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 9e79d47e077f..683a8652e155 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -86,7 +86,9 @@ MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); - +/* This needs to be adjusted when brcms_firmwares changes */ +MODULE_FIRMWARE("brcm/bcm43xx-0.fw"); +MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw"); /* recognized BCMA Core IDs */ static struct bcma_device_id brcms_coreid_table[] = { From df32381896f5f0c78a371df2e49ab7c776b1a5ba Mon Sep 17 00:00:00 2001 From: Marco Porsch Date: Wed, 8 Aug 2012 07:58:43 +0200 Subject: [PATCH 108/109] mac80211: fix unnecessary beacon update after peering status change ieee80211_bss_info_change_notify is called everytime a peer link is established or closed, because the accepting_plinks flag in the meshconf IE *might* have changed. With this patch the corresponding functions return the BSS_CHANGED_BEACON flag when a beacon update is necessary. Also it makes mesh_accept_plinks_update the common place to update the accepting_plinks flag. mesh_accept_plinks_update is called upon plink change and also periodically from ieee80211_mesh_housekeeping. Thus, it also picks up changes of local->num_sta. Signed-off-by: Marco Porsch Acked-by: Thomas Pedersen Signed-off-by: John W. Linville --- net/mac80211/mesh.c | 21 ++++++++++++------- net/mac80211/mesh.h | 2 +- net/mac80211/mesh_plink.c | 44 +++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6fac18c0423f..856dcf49ce75 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) * mesh_accept_plinks_update - update accepting_plink in local mesh beacons * * @sdata: mesh interface in which mesh beacons are going to be updated + * + * Returns: beacon changed flag if the beacon content changed. */ -void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) +u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) { bool free_plinks; + u32 changed = 0; /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, * the mesh interface might be able to establish plinks with peers that @@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) */ free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.mesh.accepting_plinks) - ieee80211_mesh_housekeeping_timer((unsigned long) sdata); + if (free_plinks != sdata->u.mesh.accepting_plinks) { + sdata->u.mesh.accepting_plinks = free_plinks; + changed = BSS_CHANGED_BEACON; + } + + return changed; } int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) @@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) neighbors = (neighbors > 15) ? 15 : neighbors; *pos++ = neighbors << 1; /* Mesh capability */ - ifmsh->accepting_plinks = mesh_plink_availables(sdata); *pos = MESHCONF_CAPAB_FORWARDING; *pos |= ifmsh->accepting_plinks ? MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; @@ -521,14 +527,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_mesh *ifmsh) { - bool free_plinks; + u32 changed; ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); mesh_path_expire(sdata); - free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.mesh.accepting_plinks) - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); + changed = mesh_accept_plinks_update(sdata); + ieee80211_bss_info_change_notify(sdata, changed); mod_timer(&ifmsh->housekeeping_timer, round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index faaa39bcfd10..13fd5b5fdb0a 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -282,7 +282,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, u8 *hw_addr, struct ieee802_11_elems *ie); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); -void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); +u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); void mesh_plink_deactivate(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index af671b984df3..f20e9f26d137 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, u8 *da, __le16 llid, __le16 plid, __le16 reason); static inline -void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) +u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); - mesh_accept_plinks_update(sdata); + return mesh_accept_plinks_update(sdata); } static inline -void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) +u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); - mesh_accept_plinks_update(sdata); + return mesh_accept_plinks_update(sdata); } /** @@ -170,22 +170,21 @@ out: * @sta: mesh peer link to deactivate * * All mesh paths with this peer as next hop will be flushed + * Returns beacon changed flag if the beacon content changed. * * Locking: the caller must hold sta->lock */ -static bool __mesh_plink_deactivate(struct sta_info *sta) +static u32 __mesh_plink_deactivate(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; - bool deactivated = false; + u32 changed = 0; - if (sta->plink_state == NL80211_PLINK_ESTAB) { - mesh_plink_dec_estab_count(sdata); - deactivated = true; - } + if (sta->plink_state == NL80211_PLINK_ESTAB) + changed = mesh_plink_dec_estab_count(sdata); sta->plink_state = NL80211_PLINK_BLOCKED; mesh_path_flush_by_nexthop(sta); - return deactivated; + return changed; } /** @@ -198,18 +197,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) void mesh_plink_deactivate(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; - bool deactivated; + u32 changed; spin_lock_bh(&sta->lock); - deactivated = __mesh_plink_deactivate(sta); + changed = __mesh_plink_deactivate(sta); sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, sta->sta.addr, sta->llid, sta->plid, sta->reason); spin_unlock_bh(&sta->lock); - if (deactivated) - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); + ieee80211_bss_info_change_notify(sdata, changed); } static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, @@ -541,15 +539,14 @@ int mesh_plink_open(struct sta_info *sta) void mesh_plink_block(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; - bool deactivated; + u32 changed; spin_lock_bh(&sta->lock); - deactivated = __mesh_plink_deactivate(sta); + changed = __mesh_plink_deactivate(sta); sta->plink_state = NL80211_PLINK_BLOCKED; spin_unlock_bh(&sta->lock); - if (deactivated) - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); + ieee80211_bss_info_change_notify(sdata, changed); } @@ -852,9 +849,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m del_timer(&sta->plink_timer); sta->plink_state = NL80211_PLINK_ESTAB; spin_unlock_bh(&sta->lock); - mesh_plink_inc_estab_count(sdata); + changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= BSS_CHANGED_BEACON; mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); break; @@ -888,9 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m del_timer(&sta->plink_timer); sta->plink_state = NL80211_PLINK_ESTAB; spin_unlock_bh(&sta->lock); - mesh_plink_inc_estab_count(sdata); + changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= BSS_CHANGED_BEACON; mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); mesh_plink_frame_tx(sdata, @@ -908,13 +903,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m case CLS_ACPT: reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); sta->reason = reason; - __mesh_plink_deactivate(sta); + changed |= __mesh_plink_deactivate(sta); sta->plink_state = NL80211_PLINK_HOLDING; llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); changed |= mesh_set_ht_prot_mode(sdata); - changed |= BSS_CHANGED_BEACON; mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, sta->sta.addr, llid, plid, reason); break; From 22c5649eef0fc37532e20c14d2656b28ca708a69 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Aug 2012 13:09:20 +0200 Subject: [PATCH 109/109] p54: fix powerpc gcc warnings My commit "p54: parse output power table" introduced the following compiler warnings for powerpc-allmodconfig eeprom.c: In function 'p54_get_maxpower': eeprom.c:291 warning: comparison of distinct pointer types lacks a cast eeporm.c:292 warning: comparison of distinct pointer types lacks a cast eeprom.c:293 warning: comparison of distinct pointer types lacks a cast eeprom.c:294 warning: comparison of distinct pointer types lacks a cast This patch fixes those by using max_t(u16 which forces a type cast. Reported-by: Fengguang Wu Tested-by: Fengguang Wu Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index d4d86107e05a..1ef1bfe6a9d7 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -288,10 +288,14 @@ static int p54_get_maxpower(struct p54_common *priv, void *data) for (j = 0; j < ARRAY_SIZE(pda->point); j++) { struct pda_channel_output_limit_point_longbow *point = &pda->point[j]; - rawpower = max(rawpower, le16_to_cpu(point->val_qpsk)); - rawpower = max(rawpower, le16_to_cpu(point->val_bpsk)); - rawpower = max(rawpower, le16_to_cpu(point->val_16qam)); - rawpower = max(rawpower, le16_to_cpu(point->val_64qam)); + rawpower = max_t(u16, + rawpower, le16_to_cpu(point->val_qpsk)); + rawpower = max_t(u16, + rawpower, le16_to_cpu(point->val_bpsk)); + rawpower = max_t(u16, + rawpower, le16_to_cpu(point->val_16qam)); + rawpower = max_t(u16, + rawpower, le16_to_cpu(point->val_64qam)); } /* longbow seems to use 1/16 dBm units */ return rawpower / 16;