summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c5
-rw-r--r--drivers/net/phy/dp83640.c2
-rw-r--r--drivers/net/phy/micrel.c2
-rw-r--r--drivers/net/vrf.c18
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c133
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h83
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c21
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h23
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c5
-rw-r--r--drivers/net/wireless/cnss/cnss_pci.c232
-rw-r--r--drivers/net/wireless/cnss2/pci.c5
-rw-r--r--drivers/net/wireless/cnss2/qmi.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c2
18 files changed, 444 insertions, 103 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 70da30095b89..a5e4b4b93d1b 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1583,6 +1583,11 @@ static int bgmac_probe(struct bcma_device *core)
dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
}
+ /* This (reset &) enable is not preset in specs or reference driver but
+ * Broadcom does it in arch PCI code when enabling fake PCI device.
+ */
+ bcma_core_enable(core, 0);
+
/* Allocation and references */
net_dev = alloc_etherdev(sizeof(*bgmac));
if (!net_dev)
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 84b9cca152eb..e83acc608678 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -907,7 +907,7 @@ static void decode_txts(struct dp83640_private *dp83640,
if (overflow) {
pr_debug("tx timestamp queue overflow, count %d\n", overflow);
while (skb) {
- skb_complete_tx_timestamp(skb, NULL);
+ kfree_skb(skb);
skb = skb_dequeue(&dp83640->tx_queue);
}
return;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index e13ad6cdcc22..c8b85f1069ff 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -539,6 +539,8 @@ static int ksz9031_read_status(struct phy_device *phydev)
if ((regval & 0xFF) == 0xFF) {
phy_init_hw(phydev);
phydev->link = 0;
+ if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
+ phydev->drv->config_intr(phydev);
}
return 0;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 349aecbc210a..ac945f8781ac 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -733,15 +733,15 @@ static int vrf_del_slave(struct net_device *dev, struct net_device *port_dev)
static void vrf_dev_uninit(struct net_device *dev)
{
struct net_vrf *vrf = netdev_priv(dev);
- struct slave_queue *queue = &vrf->queue;
- struct list_head *head = &queue->all_slaves;
- struct slave *slave, *next;
+// struct slave_queue *queue = &vrf->queue;
+// struct list_head *head = &queue->all_slaves;
+// struct slave *slave, *next;
vrf_rtable_destroy(vrf);
vrf_rt6_destroy(vrf);
- list_for_each_entry_safe(slave, next, head, list)
- vrf_del_slave(dev, slave->dev);
+// list_for_each_entry_safe(slave, next, head, list)
+// vrf_del_slave(dev, slave->dev);
free_percpu(dev->dstats);
dev->dstats = NULL;
@@ -914,6 +914,14 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[])
static void vrf_dellink(struct net_device *dev, struct list_head *head)
{
+ struct net_vrf *vrf = netdev_priv(dev);
+ struct slave_queue *queue = &vrf->queue;
+ struct list_head *all_slaves = &queue->all_slaves;
+ struct slave *slave, *next;
+
+ list_for_each_entry_safe(slave, next, all_slaves, list)
+ vrf_del_slave(dev, slave->dev);
+
unregister_netdevice_queue(dev, head);
}
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 10b33840e5e5..041d1d5eb718 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1924,6 +1924,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_hif_stop;
}
+ status = ath10k_pktlog_connect(ar);
+ if (status) {
+ ath10k_err(ar, "could not connect pktlog: %d\n", status);
+ goto err_hif_stop;
+ }
+
status = ath10k_htc_start(&ar->htc);
if (status) {
ath10k_err(ar, "failed to start htc: %d\n", status);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 8ddbae96794d..ffcf30756b9e 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -467,6 +467,7 @@ struct ath10k_debug {
u64 fw_dbglog_mask;
u32 fw_dbglog_level;
u32 pktlog_filter;
+ enum ath10k_htc_ep_id eid;
u32 reg_addr;
u32 nf_cal_period;
void *cal_data;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index ec8063e7986a..cb152bb4a222 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -25,6 +25,7 @@
#include "core.h"
#include "debug.h"
#include "hif.h"
+#include "htt.h"
#include "wmi-ops.h"
/* ms */
@@ -2617,6 +2618,138 @@ static const struct file_operations fops_fw_checksums = {
.llseek = default_llseek,
};
+static struct txctl_frm_hdr frm_hdr;
+
+static void ath10k_extract_frame_header(u8 *addr1, u8 *addr2, u8 *addr3)
+{
+ frm_hdr.bssid_tail = (addr1[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr1[IEEE80211_ADDR_LEN - 1]);
+ frm_hdr.sa_tail = (addr2[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr2[IEEE80211_ADDR_LEN - 1]);
+ frm_hdr.da_tail = (addr3[IEEE80211_ADDR_LEN - 2] << BITS_PER_BYTE)
+ | (addr3[IEEE80211_ADDR_LEN - 1]);
+}
+
+static void ath10k_process_ieee_hdr(void *data)
+{
+ u8 dir;
+ struct ieee80211_frame *wh;
+
+ if (!data)
+ return;
+
+ wh = (struct ieee80211_frame *)(data);
+ frm_hdr.framectrl = *(u_int16_t *)(wh->i_fc);
+ frm_hdr.seqctrl = *(u_int16_t *)(wh->i_seq);
+ dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK);
+
+ if (dir == IEEE80211_FC1_DIR_TODS)
+ ath10k_extract_frame_header(&wh->i_addr1, &wh->i_addr2,
+ &wh->i_addr3);
+ else if (dir == IEEE80211_FC1_DIR_FROMDS)
+ ath10k_extract_frame_header(&wh->i_addr2, &wh->i_addr3,
+ &wh->i_addr1);
+ else
+ ath10k_extract_frame_header(&wh->i_addr3, &wh->i_addr2,
+ &wh->i_addr1);
+}
+
+static void ath10k_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct ath10k_pktlog_hdr *hdr = (void *)skb->data;
+ struct ath_pktlog_txctl pktlog_tx_ctrl;
+
+ switch (hdr->log_type) {
+ case ATH10K_PKTLOG_TYPE_TX_CTRL: {
+ spin_lock_bh(&ar->htt.tx_lock);
+
+ memcpy((void *)(&pktlog_tx_ctrl.hdr), (void *)hdr,
+ sizeof(pktlog_tx_ctrl.hdr));
+ pktlog_tx_ctrl.frm_hdr = frm_hdr;
+ memcpy((void *)pktlog_tx_ctrl.txdesc_ctl, (void *)hdr->payload,
+ __le16_to_cpu(hdr->size));
+ pktlog_tx_ctrl.hdr.size = sizeof(pktlog_tx_ctrl) -
+ sizeof(pktlog_tx_ctrl.hdr);
+
+ spin_unlock_bh(&ar->htt.tx_lock);
+
+ trace_ath10k_htt_pktlog(ar, (void *)&pktlog_tx_ctrl,
+ sizeof(pktlog_tx_ctrl));
+ break;
+ }
+ case ATH10K_PKTLOG_TYPE_TX_MSDU_ID:
+ break;
+ case ATH10K_PKTLOG_TYPE_TX_FRM_HDR: {
+ ath10k_process_ieee_hdr((void *)(hdr->payload));
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ }
+ case ATH10K_PKTLOG_TYPE_RX_STAT:
+ case ATH10K_PKTLOG_TYPE_RC_FIND:
+ case ATH10K_PKTLOG_TYPE_RC_UPDATE:
+ case ATH10K_PKTLOG_TYPE_DBG_PRINT:
+ case ATH10K_PKTLOG_TYPE_TX_STAT:
+ case ATH10K_PKTLOG_TYPE_SW_EVENT:
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ case ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR: {
+ u32 desc_id = (u32)*((u32 *)(hdr->payload));
+ struct sk_buff *msdu;
+
+ spin_lock_bh(&ar->htt.tx_lock);
+ msdu = ath10k_htt_tx_find_msdu_by_id(&ar->htt, desc_id);
+
+ if (!msdu) {
+ ath10k_info(ar,
+ "Failed to get msdu, id: %d\n",
+ desc_id);
+ spin_unlock_bh(&ar->htt.tx_lock);
+ return;
+ }
+ ath10k_process_ieee_hdr((void *)msdu->data);
+ spin_unlock_bh(&ar->htt.tx_lock);
+ trace_ath10k_htt_pktlog(ar, hdr, sizeof(*hdr) +
+ __le16_to_cpu(hdr->size));
+ break;
+ }
+ }
+}
+
+static void ath10k_pktlog_htc_tx_complete(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ ath10k_info(ar, "PKTLOG htc completed\n");
+}
+
+int ath10k_pktlog_connect(struct ath10k *ar)
+{
+ int status;
+ struct ath10k_htc_svc_conn_req conn_req;
+ struct ath10k_htc_svc_conn_resp conn_resp;
+
+ memset(&conn_req, 0, sizeof(conn_req));
+ memset(&conn_resp, 0, sizeof(conn_resp));
+
+ conn_req.ep_ops.ep_tx_complete = ath10k_pktlog_htc_tx_complete;
+ conn_req.ep_ops.ep_rx_complete = ath10k_pktlog_process_rx;
+ conn_req.ep_ops.ep_tx_credits = NULL;
+
+ /* connect to control service */
+ conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_LOG_MSG;
+ status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
+ if (status) {
+ ath10k_warn(ar, "failed to connect to PKTLOG service: %d\n",
+ status);
+ return status;
+ }
+
+ ar->debug.eid = conn_resp.eid;
+
+ return 0;
+}
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index f963391e3544..f9e90e1227de 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -57,6 +57,84 @@ enum ath10k_dbg_aggr_mode {
ATH10K_DBG_AGGR_MODE_MAX,
};
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
+
+#define MAX_PKT_INFO_MSDU_ID 192
+#define MSDU_ID_INFO_ID_OFFSET \
+ ((MAX_PKT_INFO_MSDU_ID >> 3) + 4)
+
+#define PKTLOG_MAX_TXCTL_WORDS 57 /* +2 words for bitmap */
+#define HTT_TX_MSDU_LEN_MASK 0xffff
+
+struct txctl_frm_hdr {
+ __le16 framectrl; /* frame control field from header */
+ __le16 seqctrl; /* frame control field from header */
+ __le16 bssid_tail; /* last two octets of bssid */
+ __le16 sa_tail; /* last two octets of SA */
+ __le16 da_tail; /* last two octets of DA */
+ __le16 resvd;
+} __packed;
+
+struct ath_pktlog_hdr {
+ __le16 flags;
+ __le16 missed_cnt;
+ u8 log_type;
+ u8 macId;
+ __le16 size;
+ __le32 timestamp;
+ __le32 type_specific_data;
+} __packed;
+
+/* generic definitions for IEEE 802.11 frames */
+struct ieee80211_frame {
+ u8 i_fc[2];
+ u8 i_dur[2];
+ union {
+ struct {
+ u8 i_addr1[IEEE80211_ADDR_LEN];
+ u8 i_addr2[IEEE80211_ADDR_LEN];
+ u8 i_addr3[IEEE80211_ADDR_LEN];
+ };
+ u8 i_addr_all[3 * IEEE80211_ADDR_LEN];
+ };
+ u8 i_seq[2];
+} __packed;
+
+struct fw_pktlog_msdu_info {
+ __le32 num_msdu;
+ u8 bound_bmap[MAX_PKT_INFO_MSDU_ID >> 3];
+ __le16 id[MAX_PKT_INFO_MSDU_ID];
+} __packed;
+
+struct ath_pktlog_txctl {
+ struct ath_pktlog_hdr hdr;
+ struct txctl_frm_hdr frm_hdr;
+ __le32 txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS];
+} __packed;
+
+struct ath_pktlog_msdu_id {
+ struct ath_pktlog_hdr hdr;
+ struct fw_pktlog_msdu_info msdu_info;
+} __packed;
+
+struct ath_pktlog_rx_info {
+ struct ath_pktlog_hdr pl_hdr;
+ struct rx_attention attention;
+ struct rx_frag_info frag_info;
+ struct rx_mpdu_start mpdu_start;
+ struct rx_msdu_start msdu_start;
+ struct rx_msdu_end msdu_end;
+ struct rx_mpdu_end mpdu_end;
+ struct rx_ppdu_start ppdu_start;
+ struct rx_ppdu_end ppdu_end;
+ u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN];
+} __packed;
+
/* FIXME: How to calculate the buffer size sanely? */
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
#define ATH10K_DATAPATH_BUF_SIZE (1024 * 1024)
@@ -98,6 +176,7 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
struct ethtool_stats *stats, u64 *data);
void fill_datapath_stats(struct ath10k *ar, struct ieee80211_rx_status *status);
size_t get_datapath_stat(char *buf, struct ath10k *ar);
+int ath10k_pktlog_connect(struct ath10k *ar);
#else
static inline int ath10k_debug_start(struct ath10k *ar)
{
@@ -158,6 +237,10 @@ static inline size_t get_datapath_stat(char *buf, struct ath10k *ar)
return 0;
}
+static inline int ath10k_pktlog_connect(struct ath10k *ar)
+{
+ return 0;
+}
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index b0d6c2614731..2df7fcb4a5ea 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1847,5 +1847,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt,
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb);
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
+struct sk_buff *ath10k_htt_tx_find_msdu_by_id(struct ath10k_htt *htt,
+ u16 msdu_id);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 1b59721a91ac..6579eb2b410c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -218,6 +218,27 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
return ret;
}
+struct sk_buff *ath10k_htt_tx_find_msdu_by_id(struct ath10k_htt *htt,
+ u16 msdu_id)
+{
+ struct ath10k *ar;
+ struct sk_buff *ret;
+
+ if (!htt)
+ return NULL;
+
+ ar = htt->ar;
+
+ lockdep_assert_held(&htt->tx_lock);
+
+ ret = (struct sk_buff *)idr_find(&htt->pending_tx, msdu_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx find msdu by msdu_id %s\n",
+ !ret ? "Failed" : "Success");
+
+ return ret;
+}
+
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
{
struct ath10k *ar = htt->ar;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 0f2422480c4e..3e1917a6a8e8 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -984,4 +984,27 @@ struct ath10k_shadow_reg_address {
extern struct ath10k_shadow_reg_value wcn3990_shadow_reg_value;
extern struct ath10k_shadow_reg_address wcn3990_shadow_reg_address;
+enum ath10k_pktlog_type {
+ ATH10K_PKTLOG_TYPE_TX_CTRL = 1,
+ ATH10K_PKTLOG_TYPE_TX_STAT,
+ ATH10K_PKTLOG_TYPE_TX_MSDU_ID,
+ ATH10K_PKTLOG_TYPE_TX_FRM_HDR,
+ ATH10K_PKTLOG_TYPE_RX_STAT,
+ ATH10K_PKTLOG_TYPE_RC_FIND,
+ ATH10K_PKTLOG_TYPE_RC_UPDATE,
+ ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR,
+ ATH10K_PKTLOG_TYPE_DBG_PRINT,
+ ATH10K_PKTLOG_TYPE_SW_EVENT,
+ ATH10K_PKTLOG_TYPE_MAX,
+};
+
+struct ath10k_pktlog_hdr {
+ __le16 flags;
+ __le16 missed_cnt;
+ __le16 log_type;
+ __le16 size;
+ __le32 timestamp;
+ u8 payload[0];
+} __packed;
+
#endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 9e607b2fa2d4..ca77861c4320 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3139,7 +3139,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
(unsigned long)ar);
- if (QCA_REV_6174(ar))
+ if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
ath10k_pci_override_ce_config(ar);
ret = ath10k_pci_alloc_pipes(ar);
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 0c60a7baae82..13736750e463 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -775,9 +775,6 @@ static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
}
}
- if (WARN_ON(!ul_set || !dl_set))
- return -ENOENT;
-
return 0;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index 70a6985334d5..da5826d788d6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -4472,6 +4472,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
GFP_KERNEL);
} else if (ieee80211_is_action(mgmt->frame_control)) {
+ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
+ brcmf_err("invalid action frame length\n");
+ err = -EINVAL;
+ goto exit;
+ }
af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
if (af_params == NULL) {
brcmf_err("unable to allocate frame\n");
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index d150c2dd0f0f..af92f00ca56e 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -83,6 +83,7 @@
#define QCA6180_DEVICE_ID (0x0041)
#define QCA6180_REV_ID_OFFSET (0x08)
+#define WLAN_EN_VREG_NAME "vdd-wlan-en"
#define WLAN_VREG_NAME "vdd-wlan"
#define WLAN_VREG_IO_NAME "vdd-wlan-io"
#define WLAN_VREG_XTAL_NAME "vdd-wlan-xtal"
@@ -156,6 +157,7 @@ struct cnss_wlan_gpio_info {
};
struct cnss_wlan_vreg_info {
+ struct regulator *wlan_en_reg;
struct regulator *wlan_reg;
struct regulator *soc_swreg;
struct regulator *ant_switch;
@@ -238,6 +240,7 @@ static struct cnss_data {
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
struct cnss_wlan_vreg_info vreg_info;
+ bool wlan_en_vreg_support;
struct cnss_wlan_gpio_info gpio_info;
bool pcie_link_state;
bool pcie_link_down_ind;
@@ -293,6 +296,17 @@ module_param(pcie_link_down_panic, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(pcie_link_down_panic,
"Trigger kernel panic when PCIe link down is detected");
+static void cnss_put_wlan_enable_gpio(void)
+{
+ struct cnss_wlan_gpio_info *gpio_info = &penv->gpio_info;
+ struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info;
+
+ if (penv->wlan_en_vreg_support)
+ regulator_put(vreg_info->wlan_en_reg);
+ else
+ gpio_free(gpio_info->num);
+}
+
static int cnss_wlan_vreg_on(struct cnss_wlan_vreg_info *vreg_info)
{
int ret;
@@ -576,6 +590,25 @@ static void cnss_wlan_gpio_set(struct cnss_wlan_gpio_info *info, bool state)
info->name, info->state ? "enabled" : "disabled");
}
+static int cnss_configure_wlan_en_gpio(bool state)
+{
+ int ret = 0;
+ struct cnss_wlan_gpio_info *gpio_info = &penv->gpio_info;
+ struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info;
+
+ if (penv->wlan_en_vreg_support) {
+ if (state)
+ ret = regulator_enable(vreg_info->wlan_en_reg);
+ else
+ ret = regulator_disable(vreg_info->wlan_en_reg);
+ } else {
+ cnss_wlan_gpio_set(gpio_info, state);
+ }
+
+ msleep(WLAN_ENABLE_DELAY);
+ return ret;
+}
+
static int cnss_pinctrl_init(struct cnss_wlan_gpio_info *gpio_info,
struct platform_device *pdev)
{
@@ -682,14 +715,71 @@ end:
return ret;
}
+static int cnss_get_wlan_enable_gpio(
+ struct cnss_wlan_gpio_info *gpio_info,
+ struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device *dev = &pdev->dev;
+
+ if (!of_find_property(dev->of_node, gpio_info->name, NULL)) {
+ gpio_info->prop = false;
+ return -ENODEV;
+ }
+
+ gpio_info->prop = true;
+ ret = of_get_named_gpio(dev->of_node, gpio_info->name, 0);
+ if (ret >= 0) {
+ gpio_info->num = ret;
+ } else {
+ if (ret == -EPROBE_DEFER)
+ pr_debug("get WLAN_EN GPIO probe defer\n");
+ else
+ pr_err(
+ "can't get gpio %s ret %d", gpio_info->name, ret);
+ }
+
+ ret = cnss_pinctrl_init(gpio_info, pdev);
+ if (ret)
+ pr_debug("%s: pinctrl init failed!\n", __func__);
+
+ ret = cnss_wlan_gpio_init(gpio_info);
+ if (ret)
+ pr_err("gpio init failed\n");
+
+ return ret;
+}
+
+static int cnss_get_wlan_bootstrap_gpio(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device_node *node = (&pdev->dev)->of_node;
+
+ if (!of_find_property(node, WLAN_BOOTSTRAP_GPIO_NAME, NULL))
+ return ret;
+
+ penv->wlan_bootstrap_gpio =
+ of_get_named_gpio(node, WLAN_BOOTSTRAP_GPIO_NAME, 0);
+ if (penv->wlan_bootstrap_gpio > 0) {
+ ret = cnss_wlan_bootstrap_gpio_init();
+ } else {
+ ret = penv->wlan_bootstrap_gpio;
+ pr_err(
+ "%s: Can't get GPIO %s, ret = %d",
+ __func__, WLAN_BOOTSTRAP_GPIO_NAME, ret);
+ }
+
+ return ret;
+}
+
static int cnss_wlan_get_resources(struct platform_device *pdev)
{
int ret = 0;
struct cnss_wlan_gpio_info *gpio_info = &penv->gpio_info;
struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info;
+ struct device_node *node = pdev->dev.of_node;
- if (of_get_property(pdev->dev.of_node,
- WLAN_VREG_CORE_NAME"-supply", NULL)) {
+ if (of_get_property(node, WLAN_VREG_CORE_NAME "-supply", NULL)) {
vreg_info->wlan_reg_core = regulator_get(&pdev->dev,
WLAN_VREG_CORE_NAME);
if (IS_ERR(vreg_info->wlan_reg_core)) {
@@ -719,8 +809,7 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
}
}
- if (of_get_property(pdev->dev.of_node,
- WLAN_VREG_IO_NAME"-supply", NULL)) {
+ if (of_get_property(node, WLAN_VREG_IO_NAME "-supply", NULL)) {
vreg_info->wlan_reg_io = regulator_get(&pdev->dev,
WLAN_VREG_IO_NAME);
if (!IS_ERR(vreg_info->wlan_reg_io)) {
@@ -765,8 +854,7 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
goto err_reg_enable;
}
- if (of_get_property(pdev->dev.of_node,
- WLAN_VREG_SP2T_NAME"-supply", NULL)) {
+ if (of_get_property(node, WLAN_VREG_SP2T_NAME "-supply", NULL)) {
vreg_info->wlan_reg_sp2t =
regulator_get(&pdev->dev, WLAN_VREG_SP2T_NAME);
if (!IS_ERR(vreg_info->wlan_reg_sp2t)) {
@@ -787,8 +875,7 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
}
}
- if (of_get_property(pdev->dev.of_node,
- WLAN_ANT_SWITCH_NAME "-supply", NULL)) {
+ if (of_get_property(node, WLAN_ANT_SWITCH_NAME "-supply", NULL)) {
vreg_info->ant_switch =
regulator_get(&pdev->dev, WLAN_ANT_SWITCH_NAME);
if (!IS_ERR(vreg_info->ant_switch)) {
@@ -818,13 +905,10 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
}
}
- if (of_find_property((&pdev->dev)->of_node,
- "qcom,wlan-uart-access", NULL))
+ if (of_find_property(node, "qcom,wlan-uart-access", NULL))
penv->cap.cap_flag |= CNSS_HAS_UART_ACCESS;
- if (of_get_property(pdev->dev.of_node,
- WLAN_SWREG_NAME"-supply", NULL)) {
-
+ if (of_get_property(node, WLAN_SWREG_NAME "-supply", NULL)) {
vreg_info->soc_swreg = regulator_get(&pdev->dev,
WLAN_SWREG_NAME);
if (IS_ERR(vreg_info->soc_swreg)) {
@@ -847,68 +931,41 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
penv->cap.cap_flag |= CNSS_HAS_EXTERNAL_SWREG;
}
- vreg_info->state = VREG_ON;
-
- if (!of_find_property((&pdev->dev)->of_node, gpio_info->name, NULL)) {
- gpio_info->prop = false;
- goto end;
+ penv->wlan_en_vreg_support =
+ of_property_read_bool(node, "qcom,wlan-en-vreg-support");
+ if (penv->wlan_en_vreg_support) {
+ vreg_info->wlan_en_reg =
+ regulator_get(&pdev->dev, WLAN_EN_VREG_NAME);
+ if (IS_ERR(vreg_info->wlan_en_reg)) {
+ pr_err("%s:wlan_en vreg get failed\n", __func__);
+ ret = PTR_ERR(vreg_info->wlan_en_reg);
+ goto err_wlan_en_reg_get;
+ }
}
- gpio_info->prop = true;
- ret = of_get_named_gpio((&pdev->dev)->of_node,
- gpio_info->name, 0);
-
- if (ret >= 0) {
- gpio_info->num = ret;
- ret = 0;
- } else {
- if (ret == -EPROBE_DEFER)
- pr_debug("get WLAN_EN GPIO probe defer\n");
- else
- pr_err("can't get gpio %s ret %d",
- gpio_info->name, ret);
- goto err_get_gpio;
+ if (!penv->wlan_en_vreg_support) {
+ ret = cnss_get_wlan_enable_gpio(gpio_info, pdev);
+ if (ret) {
+ pr_err(
+ "%s:Failed to config the WLAN_EN gpio\n", __func__);
+ goto err_gpio_wlan_en;
+ }
}
+ vreg_info->state = VREG_ON;
- ret = cnss_pinctrl_init(gpio_info, pdev);
+ ret = cnss_get_wlan_bootstrap_gpio(pdev);
if (ret) {
- pr_err("%s: pinctrl init failed!\n", __func__);
- goto err_pinctrl_init;
+ pr_err("%s: Failed to enable wlan bootstrap gpio\n", __func__);
+ goto err_gpio_wlan_bootstrap;
}
- ret = cnss_wlan_gpio_init(gpio_info);
- if (ret) {
- pr_err("gpio init failed\n");
- goto err_gpio_init;
- }
-
- if (of_find_property((&pdev->dev)->of_node,
- WLAN_BOOTSTRAP_GPIO_NAME, NULL)) {
- penv->wlan_bootstrap_gpio =
- of_get_named_gpio((&pdev->dev)->of_node,
- WLAN_BOOTSTRAP_GPIO_NAME, 0);
- if (penv->wlan_bootstrap_gpio > 0) {
- ret = cnss_wlan_bootstrap_gpio_init();
- if (ret)
- goto err_gpio_init;
- } else {
- if (ret == -EPROBE_DEFER) {
- pr_debug("%s: Get GPIO %s probe defer\n",
- __func__, WLAN_BOOTSTRAP_GPIO_NAME);
- } else {
- pr_err("%s: Can't get GPIO %s, ret = %d",
- __func__, WLAN_BOOTSTRAP_GPIO_NAME,
- ret);
- }
- goto err_gpio_init;
- }
- }
-end:
return ret;
-err_gpio_init:
-err_pinctrl_init:
-err_get_gpio:
+err_gpio_wlan_bootstrap:
+ cnss_put_wlan_enable_gpio();
+err_gpio_wlan_en:
+err_wlan_en_reg_get:
+ vreg_info->wlan_en_reg = NULL;
if (vreg_info->soc_swreg)
regulator_disable(vreg_info->soc_swreg);
vreg_info->state = VREG_OFF;
@@ -967,7 +1024,7 @@ static void cnss_wlan_release_resources(void)
if (penv->wlan_bootstrap_gpio > 0)
gpio_free(penv->wlan_bootstrap_gpio);
- gpio_free(gpio_info->num);
+ cnss_put_wlan_enable_gpio();
gpio_info->state = WLAN_EN_LOW;
gpio_info->prop = false;
cnss_wlan_vreg_set(vreg_info, VREG_OFF);
@@ -1553,7 +1610,6 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
{
int ret = 0;
struct cnss_wlan_vreg_info *vreg_info = &penv->vreg_info;
- struct cnss_wlan_gpio_info *gpio_info = &penv->gpio_info;
void *cpu_addr;
dma_addr_t dma_handle;
struct codeswap_codeseg_info *cnss_seg_info = NULL;
@@ -1612,7 +1668,7 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
penv->pcie_link_state = PCIE_LINK_DOWN;
}
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
ret = cnss_wlan_vreg_set(vreg_info, VREG_OFF);
if (ret) {
@@ -2259,8 +2315,7 @@ again:
msleep(WLAN_BOOTSTRAP_DELAY);
}
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_HIGH);
- msleep(WLAN_ENABLE_DELAY);
+ cnss_configure_wlan_en_gpio(WLAN_EN_HIGH);
if (!pdev) {
pr_debug("%s: invalid pdev. register pci device\n", __func__);
@@ -2343,8 +2398,7 @@ again:
cnss_get_pci_dev_bus_number(pdev),
pdev, PM_OPTIONS);
penv->pcie_link_state = PCIE_LINK_DOWN;
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
- msleep(WLAN_ENABLE_DELAY);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
cnss_wlan_vreg_set(vreg_info, VREG_OFF);
msleep(POWER_ON_DELAY);
probe_again++;
@@ -2371,7 +2425,7 @@ err_pcie_link_up:
}
err_pcie_reg:
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
cnss_wlan_vreg_set(vreg_info, VREG_OFF);
if (penv->pdev) {
pr_err("%d: Unregistering PCI device\n", __LINE__);
@@ -2452,8 +2506,7 @@ void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver)
cut_power:
penv->driver = NULL;
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
-
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
if (cnss_wlan_vreg_set(vreg_info, VREG_OFF))
pr_err("wlan vreg OFF failed\n");
}
@@ -2565,8 +2618,7 @@ static int cnss_shutdown(const struct subsys_desc *subsys, bool force_stop)
}
cut_power:
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
-
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
if (cnss_wlan_vreg_set(vreg_info, VREG_OFF))
pr_err("cnss: Failed to set WLAN VREG_OFF!\n");
@@ -2599,8 +2651,7 @@ static int cnss_powerup(const struct subsys_desc *subsys)
}
msleep(POWER_ON_DELAY);
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_HIGH);
- msleep(WLAN_ENABLE_DELAY);
+ cnss_configure_wlan_en_gpio(WLAN_EN_HIGH);
if (!pdev) {
pr_err("%d: invalid pdev\n", __LINE__);
@@ -2660,7 +2711,7 @@ err_wlan_reinit:
penv->pcie_link_state = PCIE_LINK_DOWN;
err_pcie_link_up:
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
cnss_wlan_vreg_set(vreg_info, VREG_OFF);
if (penv->pdev) {
pr_err("%d: Unregistering pci device\n", __LINE__);
@@ -2848,8 +2899,11 @@ static int cnss_probe(struct platform_device *pdev)
if (ret)
goto err_get_wlan_res;
- cnss_wlan_gpio_set(&penv->gpio_info, WLAN_EN_HIGH);
- msleep(WLAN_ENABLE_DELAY);
+ ret = cnss_configure_wlan_en_gpio(WLAN_EN_HIGH);
+ if (ret) {
+ pr_err("%s: Failed to enable WLAN enable gpio\n", __func__);
+ goto err_get_rc;
+ }
ret = of_property_read_u32(dev->of_node, "qcom,wlan-rc-num", &rc_num);
if (ret) {
@@ -3044,7 +3098,7 @@ err_subsys_reg:
err_esoc_reg:
err_pcie_enumerate:
err_get_rc:
- cnss_wlan_gpio_set(&penv->gpio_info, WLAN_EN_LOW);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
cnss_wlan_release_resources();
err_get_wlan_res:
@@ -3055,8 +3109,6 @@ err_get_wlan_res:
static int cnss_remove(struct platform_device *pdev)
{
- struct cnss_wlan_gpio_info *gpio_info = &penv->gpio_info;
-
unregister_pm_notifier(&cnss_pm_notifier);
device_remove_file(&pdev->dev, &dev_attr_fw_image_setup);
@@ -3077,7 +3129,7 @@ static int cnss_remove(struct platform_device *pdev)
}
}
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
if (penv->wlan_bootstrap_gpio > 0)
gpio_set_value(penv->wlan_bootstrap_gpio, WLAN_BOOTSTRAP_LOW);
cnss_wlan_release_resources();
@@ -3578,8 +3630,7 @@ static int __cnss_pcie_power_up(struct device *dev)
msleep(WLAN_BOOTSTRAP_DELAY);
}
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_HIGH);
- msleep(WLAN_ENABLE_DELAY);
+ cnss_configure_wlan_en_gpio(WLAN_EN_HIGH);
return 0;
}
@@ -3592,8 +3643,7 @@ static int __cnss_pcie_power_down(struct device *dev)
vreg_info = &penv->vreg_info;
gpio_info = &penv->gpio_info;
- cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
-
+ cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
if (penv->wlan_bootstrap_gpio > 0)
gpio_set_value(penv->wlan_bootstrap_gpio, WLAN_BOOTSTRAP_LOW);
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index ce5a7b2bc88e..2c297fba5c34 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1463,6 +1463,11 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
cnss_pci_disable_msi(pci_priv);
goto disable_bus;
}
+ ret = cnss_suspend_pci_link(pci_priv);
+ if (ret)
+ cnss_pr_err("Failed to suspend PCI link, err = %d\n",
+ ret);
+ cnss_power_off_device(plat_priv);
break;
default:
cnss_pr_err("Unknown PCI device found: 0x%x\n",
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index d1c0423b4517..e010e2c39f02 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -39,7 +39,7 @@ static bool daemon_support;
module_param(daemon_support, bool, 0600);
MODULE_PARM_DESC(daemon_support, "User space has cnss-daemon support or not");
-static bool bdf_bypass = true;
+static bool bdf_bypass;
#ifdef CONFIG_CNSS2_DEBUG
module_param(bdf_bypass, bool, 0600);
MODULE_PARM_DESC(bdf_bypass, "If BDF is not found, send dummy BDF to FW");
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index d59769e858f4..019d7165a045 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2539,7 +2539,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
tasklet_hrtimer_init(&data->beacon_timer,
mac80211_hwsim_beacon,
- CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
spin_lock_bh(&hwsim_radio_lock);
list_add_tail(&data->list, &hwsim_radios);