diff options
Diffstat (limited to 'drivers/net')
21 files changed, 326 insertions, 232 deletions
diff --git a/drivers/net/can/spi/rh850.c b/drivers/net/can/spi/rh850.c index a93f979da9ed..d2b6e8caa112 100644 --- a/drivers/net/can/spi/rh850.c +++ b/drivers/net/can/spi/rh850.c @@ -1020,6 +1020,8 @@ static int rh850_create_netdev(struct spi_device *spi, return -ENOMEM; } + netdev->mtu = CANFD_MTU; + netdev_priv_data = netdev_priv(netdev); netdev_priv_data->rh850_can = priv_data; netdev_priv_data->netdev_index = index; diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index 2a9dd460a95f..e1f9e7cebf8f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -118,8 +118,13 @@ static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, if (!buf) return -ENOMEM; + if (offset_in_page(buf)) { + dma_free_coherent(dev, PAGE_SIZE << order, + buf, sg_dma_address(mem)); + return -ENOMEM; + } + sg_set_buf(mem, buf, PAGE_SIZE << order); - BUG_ON(mem->offset); sg_dma_len(mem) = PAGE_SIZE << order; return 0; } diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 79ef799f88ab..c5ea1018cb47 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -326,6 +326,7 @@ enum cfg_version { static const struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 480f3dae0780..4296066a7ad3 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -750,6 +750,7 @@ static struct sh_eth_cpu_data sh7734_data = { .tsu = 1, .hw_crc = 1, .select_mii = 1, + .shift_rd0 = 1, }; /* SH7763 */ diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0bfbabad4431..1d1e5f7723ab 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1442,7 +1442,7 @@ static struct phy_driver genphy_driver[] = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic PHY", - .soft_reset = genphy_soft_reset, + .soft_reset = genphy_no_soft_reset, .config_init = genphy_config_init, .features = PHY_GBIT_FEATURES | SUPPORTED_MII | SUPPORTED_AUI | SUPPORTED_FIBRE | diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index f64b25c221e8..cd93220c9b45 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1009,6 +1009,7 @@ static int kaweth_probe( struct net_device *netdev; const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; + int rv = -EIO; dev_dbg(dev, "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n", @@ -1029,6 +1030,7 @@ static int kaweth_probe( kaweth = netdev_priv(netdev); kaweth->dev = udev; kaweth->net = netdev; + kaweth->intf = intf; spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); @@ -1048,6 +1050,10 @@ static int kaweth_probe( /* Download the firmware */ dev_info(dev, "Downloading firmware...\n"); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); + if (!kaweth->firmware_buf) { + rv = -ENOMEM; + goto err_free_netdev; + } if ((result = kaweth_download_firmware(kaweth, "kaweth/new_code.bin", 100, @@ -1139,8 +1145,6 @@ err_fw: dev_dbg(dev, "Initializing net device.\n"); - kaweth->intf = intf; - kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_free_netdev; @@ -1204,7 +1208,7 @@ err_only_tx: err_free_netdev: free_netdev(netdev); - return -EIO; + return rv; } /**************************************************************** diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index cb152bb4a222..42aab9b86af3 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -2644,14 +2644,14 @@ static void ath10k_process_ieee_hdr(void *data) 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); + 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); + 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); + 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) @@ -2717,6 +2717,46 @@ static void ath10k_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb) } } +int ath10k_rx_record_pktlog(struct ath10k *ar, struct sk_buff *skb) +{ + struct sk_buff *pktlog_skb; + struct ath_pktlog_hdr *pl_hdr; + struct ath_pktlog_rx_info *pktlog_rx_info; + struct htt_rx_desc *rx_desc = (void *)skb->data - sizeof(*rx_desc); + + if (!ar->debug.pktlog_filter) + return 0; + + pktlog_skb = dev_alloc_skb(sizeof(struct ath_pktlog_hdr) + + sizeof(struct htt_rx_desc) - + sizeof(struct htt_host_fw_desc_base)); + if (!pktlog_skb) + return -ENOMEM; + + pktlog_rx_info = (struct ath_pktlog_rx_info *)pktlog_skb->data; + pl_hdr = &pktlog_rx_info->pl_hdr; + + pl_hdr->flags = (1 << ATH10K_PKTLOG_FLG_FRM_TYPE_REMOTE_S); + pl_hdr->missed_cnt = 0; + pl_hdr->mac_id = 0; + pl_hdr->log_type = ATH10K_PKTLOG_TYPE_RX_STAT; + pl_hdr->flags |= ATH10K_PKTLOG_HDR_SIZE_16; + pl_hdr->size = sizeof(*rx_desc) - + sizeof(struct htt_host_fw_desc_base); + + pl_hdr->timestamp = + cpu_to_le32(rx_desc->ppdu_end.wcn3990.rx_pkt_end.phy_timestamp_1); + + pl_hdr->type_specific_data = 0xDEADAA; + memcpy((void *)pktlog_rx_info + sizeof(struct ath_pktlog_hdr), + (void *)rx_desc + sizeof(struct htt_host_fw_desc_base), + pl_hdr->size); + + ath10k_pktlog_process_rx(ar, pktlog_skb); + dev_kfree_skb_any(pktlog_skb); + return 0; +} + static void ath10k_pktlog_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) { diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index f9e90e1227de..eb47720bbf91 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -84,7 +84,7 @@ struct ath_pktlog_hdr { __le16 flags; __le16 missed_cnt; u8 log_type; - u8 macId; + u8 mac_id; __le16 size; __le32 timestamp; __le32 type_specific_data; @@ -164,6 +164,7 @@ struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); +int ath10k_rx_record_pktlog(struct ath10k *ar, struct sk_buff *skb); #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, @@ -221,6 +222,12 @@ static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, { } +static inline int ath10k_rx_record_pktlog(struct ath10k *ar, + struct sk_buff *skb) +{ + return 0; +} + static inline struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) { diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 2df7fcb4a5ea..6377c4ef427c 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1745,16 +1745,21 @@ struct ath10k_htt { #define RX_HTT_HDR_STATUS_LEN 64 -/* This structure layout is programmed via rx ring setup - * so that FW knows how to transfer the rx descriptor to the host. - * Buffers like this are placed on the rx ring. */ -struct htt_rx_desc { +struct htt_host_fw_desc_base { union { /* This field is filled on the host using the msdu buffer * from htt_rx_indication */ struct fw_rx_desc_base fw_desc; u32 pad; } __packed; +}; + +/* This structure layout is programmed via rx ring setup + * so that FW knows how to transfer the rx descriptor to the host. + * Buffers like this are placed on the rx ring. + */ +struct htt_rx_desc { + struct htt_host_fw_desc_base fw_desc_base; struct { struct rx_attention attention; struct rx_frag_info frag_info; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 437ea2c192b3..635b8281b055 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -969,6 +969,7 @@ static void ath10k_process_rx(struct ath10k *ar, trace_ath10k_rx_hdr(ar, skb->data, skb->len); trace_ath10k_rx_payload(ar, skb->data, skb->len); + ath10k_rx_record_pktlog(ar, skb); ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi); } diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 3e1917a6a8e8..37479589b8e1 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -984,6 +984,16 @@ 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; +#define ATH10K_PKTLOG_HDR_SIZE_16 0x8000 + +enum { + ATH10k_PKTLOG_FLG_FRM_TYPE_LOCAL_S = 0, + ATH10K_PKTLOG_FLG_FRM_TYPE_REMOTE_S, + ATH10K_PKTLOG_FLG_FRM_TYPE_CLONE_S, + ATH10K_PKTLOG_FLG_FRM_TYPE_CBF_S, + ATH10K_PKTLOG_FLG_FRM_TYPE_UNKNOWN_S +}; + enum ath10k_pktlog_type { ATH10K_PKTLOG_TYPE_TX_CTRL = 1, ATH10K_PKTLOG_TYPE_TX_STAT, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index cce931e51d7e..ec86c837e60a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7822,10 +7822,6 @@ static const struct ieee80211_iface_limit ath10k_wcn3990_if_limit[] = { BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO), }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_DEVICE), - }, }; static const struct ieee80211_iface_limit ath10k_wcn3990_qcs_if_limit[] = { @@ -7845,10 +7841,6 @@ static const struct ieee80211_iface_limit ath10k_wcn3990_qcs_if_limit[] = { #endif BIT(NL80211_IFTYPE_P2P_GO), }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_DEVICE), - }, }; static const struct ieee80211_iface_limit ath10k_wcn3990_if_limit_ibss[] = { @@ -8022,6 +8014,10 @@ int ath10k_mac_register(struct ath10k *ar) BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); + if (QCA_REV_WCN3990(ar)) + ar->hw->wiphy->interface_modes &= + ~BIT(NL80211_IFTYPE_P2P_DEVICE); + ieee80211_hw_set(ar->hw, SIGNAL_DBM); ieee80211_hw_set(ar->hw, SUPPORTS_PS); ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS); diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index c3100fcd80f2..8bb01c1a35f7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -681,6 +681,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, struct sk_buff *skb; u32 cmd_id; + if (!ar->wmi.ops->gen_vdev_spectral_conf) + return -EOPNOTSUPP; + skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -696,6 +699,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, struct sk_buff *skb; u32 cmd_id; + if (!ar->wmi.ops->gen_vdev_spectral_enable) + return -EOPNOTSUPP; + skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger, enable); if (IS_ERR(skb)) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 201425e7f9cb..fbc8c9a9014b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1815,8 +1815,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) { REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); - REG_SET_BIT(ah, 0x9864, 0x7f000); - REG_SET_BIT(ah, 0x9924, 0x7f00fe); REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); REG_WRITE(ah, AR_CR, AR_CR_RXD); REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index ac4781f37e78..b4e6304afd40 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -190,22 +190,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, if (strtobool(buf, &start)) return -EINVAL; + mutex_lock(&sc->mutex); + if (start == sc->tx99_state) { if (!start) - return count; + goto out; ath_dbg(common, XMIT, "Resetting TX99\n"); ath9k_tx99_deinit(sc); } if (!start) { ath9k_tx99_deinit(sc); - return count; + goto out; } r = ath9k_tx99_init(sc); - if (r) + if (r) { + mutex_unlock(&sc->mutex); return r; - + } +out: + mutex_unlock(&sc->mutex); return count; } diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index c3bcb38f428f..c69f0a488c52 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -98,6 +98,10 @@ static int cnss_stats_show_state(struct seq_file *s, continue; case CNSS_DEV_ERR_NOTIFY: seq_puts(s, "DEV_ERR"); + continue; + case CNSS_DRIVER_DEBUG: + seq_puts(s, "DRIVER_DEBUG"); + continue; } seq_printf(s, "UNKNOWN-%d", i); @@ -149,10 +153,26 @@ static ssize_t cnss_dev_boot_debug_write(struct file *fp, if (sysfs_streq(cmd, "on")) { ret = cnss_power_on_device(plat_priv); + } else if (sysfs_streq(cmd, "off")) { + cnss_power_off_device(plat_priv); } else if (sysfs_streq(cmd, "enumerate")) { ret = cnss_pci_init(plat_priv); } else if (sysfs_streq(cmd, "download")) { ret = cnss_pci_start_mhi(plat_priv->bus_priv); + } else if (sysfs_streq(cmd, "linkup")) { + ret = cnss_resume_pci_link(plat_priv->bus_priv); + } else if (sysfs_streq(cmd, "linkdown")) { + ret = cnss_suspend_pci_link(plat_priv->bus_priv); + } else if (sysfs_streq(cmd, "powerup")) { + set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state); + ret = cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_POWER_UP, + true, NULL); + } else if (sysfs_streq(cmd, "shutdown")) { + ret = cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_POWER_DOWN, + true, NULL); + clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state); } else { cnss_pr_err("Device boot debugfs command is invalid\n"); ret = -EINVAL; @@ -169,8 +189,13 @@ static int cnss_dev_boot_debug_show(struct seq_file *s, void *data) seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/dev_boot\n"); seq_puts(s, "<action> can be one of below:\n"); seq_puts(s, "on: turn on device power, assert WLAN_EN\n"); + seq_puts(s, "off: de-assert WLAN_EN, turn off device power\n"); seq_puts(s, "enumerate: de-assert PERST, enumerate PCIe\n"); seq_puts(s, "download: download FW and do QMI handshake with FW\n"); + seq_puts(s, "linkup: bring up PCIe link\n"); + seq_puts(s, "linkdown: bring down PCIe link\n"); + seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n"); + seq_puts(s, "shutdown: full power off sequence to shutdown device\n"); return 0; } diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 8838a1319629..8277de861d63 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -1060,11 +1060,15 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) if (!pci_priv) return -ENODEV; + if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) + goto skip_driver_remove; + if (!plat_priv->driver_ops) return -EINVAL; cnss_driver_call_remove(plat_priv); +skip_driver_remove: cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); cnss_pci_set_monitor_wake_intr(pci_priv, false); cnss_pci_set_auto_suspended(pci_priv, 0); @@ -1162,7 +1166,8 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv) return -ENODEV; if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) || - test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state)) + test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) || + test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) goto skip_driver_remove; if (!plat_priv->driver_ops) diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index a2d9a02bde20..89ada0b2e1f0 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -142,6 +142,7 @@ enum cnss_driver_state { CNSS_DRIVER_RECOVERY, CNSS_FW_BOOT_RECOVERY, CNSS_DEV_ERR_NOTIFY, + CNSS_DRIVER_DEBUG, }; struct cnss_recovery_data { diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 44f059f7f34e..9ebe00ea8f81 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -71,7 +71,7 @@ * only support SPI for 12xx - this code should be reworked when 18xx * support is introduced */ -#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) +#define SPI_AGGR_BUFFER_SIZE (4 * SZ_4K) /* Maximum number of SPI write chunks */ #define WSPI_MAX_NUM_OF_CHUNKS \ diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c index d0a74744f70a..d94bd90f64da 100644 --- a/drivers/net/wireless/wcnss/wcnss_vreg.c +++ b/drivers/net/wireless/wcnss/wcnss_vreg.c @@ -71,23 +71,33 @@ static int is_power_on; struct vregs_info { const char * const name; + const char * const curr; + const char * const volt; int state; + bool required; struct regulator *regulator; }; /* IRIS regulators for Pronto hardware */ -static struct vregs_info iris_vregs_pronto[] = { - {"qcom,iris-vddxo", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vddrfa", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vddpa", VREG_NULL_CONFIG, NULL}, - {"qcom,iris-vdddig", VREG_NULL_CONFIG, NULL}, +static struct vregs_info iris_vregs[] = { + {"qcom,iris-vddxo", "qcom,iris-vddxo-current", + "qcom,iris-vddxo-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,iris-vddrfa", "qcom,iris-vddrfa-current", + "qcom,iris-vddrfa-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,iris-vddpa", "qcom,iris-vddpa-current", + "qcom,iris-vddpa-voltage-level", VREG_NULL_CONFIG, false, NULL}, + {"qcom,iris-vdddig", "qcom,iris-vdddig-current", + "qcom,iris-vdddig-voltage-level", VREG_NULL_CONFIG, true, NULL}, }; /* WCNSS regulators for Pronto hardware */ static struct vregs_info pronto_vregs[] = { - {"qcom,pronto-vddmx", VREG_NULL_CONFIG, NULL}, - {"qcom,pronto-vddcx", VREG_NULL_CONFIG, NULL}, - {"qcom,pronto-vddpx", VREG_NULL_CONFIG, NULL}, + {"qcom,pronto-vddmx", "qcom,pronto-vddmx-current", + "qcom,vddmx-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,pronto-vddcx", "qcom,pronto-vddcx-current", + "qcom,vddcx-voltage-level", VREG_NULL_CONFIG, true, NULL}, + {"qcom,pronto-vddpx", "qcom,pronto-vddpx-current", + "qcom,vddpx-voltage-level", VREG_NULL_CONFIG, true, NULL}, }; struct host_driver { @@ -184,6 +194,129 @@ int validate_iris_chip_id(u32 reg) } } +static void wcnss_free_regulator(void) +{ + int vreg_i; + + /* Free pronto voltage regulators from device node */ + for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) { + if (pronto_vregs[vreg_i].state) { + regulator_put(pronto_vregs[vreg_i].regulator); + pronto_vregs[vreg_i].state = VREG_NULL_CONFIG; + } + } + + /* Free IRIS voltage regulators from device node */ + for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) { + if (iris_vregs[vreg_i].state) { + regulator_put(iris_vregs[vreg_i].regulator); + iris_vregs[vreg_i].state = VREG_NULL_CONFIG; + } + } +} + +static int +wcnss_dt_parse_vreg_level(struct device *dev, int index, + const char *current_vreg_name, const char *vreg_name, + struct vregs_level *vlevel) +{ + int ret = 0; + /* array used to store nominal, low and high voltage values */ + u32 voltage_levels[3], current_vreg; + + ret = of_property_read_u32_array(dev->of_node, vreg_name, + voltage_levels, + ARRAY_SIZE(voltage_levels)); + if (ret) { + dev_err(dev, "error reading %s property\n", vreg_name); + return ret; + } + + vlevel[index].nominal_min = voltage_levels[0]; + vlevel[index].low_power_min = voltage_levels[1]; + vlevel[index].max_voltage = voltage_levels[2]; + + ret = of_property_read_u32(dev->of_node, current_vreg_name, + ¤t_vreg); + if (ret) { + dev_err(dev, "error reading %s property\n", current_vreg_name); + return ret; + } + + vlevel[index].uA_load = current_vreg; + + return ret; +} + +int +wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config, + struct device *dev) +{ + int rc, vreg_i; + + /* Parse pronto voltage regulators from device node */ + for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) { + pronto_vregs[vreg_i].regulator = + regulator_get(dev, pronto_vregs[vreg_i].name); + if (IS_ERR(pronto_vregs[vreg_i].regulator)) { + if (pronto_vregs[vreg_i].required) { + rc = PTR_ERR(pronto_vregs[vreg_i].regulator); + dev_err(dev, "regulator get of %s failed (%d)\n", + pronto_vregs[vreg_i].name, rc); + goto wcnss_vreg_get_err; + } else { + dev_dbg(dev, "Skip optional regulator configuration: %s\n", + pronto_vregs[vreg_i].name); + continue; + } + } + + pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK; + rc = wcnss_dt_parse_vreg_level(dev, vreg_i, + pronto_vregs[vreg_i].curr, + pronto_vregs[vreg_i].volt, + wlan_config->pronto_vlevel); + if (rc) { + dev_err(dev, "error reading voltage-level property\n"); + goto wcnss_vreg_get_err; + } + } + + /* Parse iris voltage regulators from device node */ + for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) { + iris_vregs[vreg_i].regulator = + regulator_get(dev, iris_vregs[vreg_i].name); + if (IS_ERR(iris_vregs[vreg_i].regulator)) { + if (iris_vregs[vreg_i].required) { + rc = PTR_ERR(iris_vregs[vreg_i].regulator); + dev_err(dev, "regulator get of %s failed (%d)\n", + iris_vregs[vreg_i].name, rc); + goto wcnss_vreg_get_err; + } else { + dev_dbg(dev, "Skip optional regulator configuration: %s\n", + iris_vregs[vreg_i].name); + continue; + } + } + + iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK; + rc = wcnss_dt_parse_vreg_level(dev, vreg_i, + iris_vregs[vreg_i].curr, + iris_vregs[vreg_i].volt, + wlan_config->iris_vlevel); + if (rc) { + dev_err(dev, "error reading voltage-level property\n"); + goto wcnss_vreg_get_err; + } + } + + return 0; + +wcnss_vreg_get_err: + wcnss_free_regulator(); + return rc; +} + void wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg) { /* Reset IRIS */ @@ -417,11 +550,6 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size, if (regulators[i].state == VREG_NULL_CONFIG) continue; - if (cfg->wcn_external_gpio_support) { - if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) - continue; - } - /* Remove PWM mode */ if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) { rc = regulator_set_load(regulators[i].regulator, 0); @@ -483,23 +611,10 @@ static int wcnss_vregs_on(struct device *dev, } for (i = 0; i < size; i++) { - if (cfg->wcn_external_gpio_support) { - if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) - continue; - } + if (regulators[i].state == VREG_NULL_CONFIG) + continue; - /* Get regulator source */ - regulators[i].regulator = - regulator_get(dev, regulators[i].name); - if (IS_ERR(regulators[i].regulator)) { - rc = PTR_ERR(regulators[i].regulator); - pr_err("regulator get of %s failed (%d)\n", - regulators[i].name, rc); - goto fail; - } - regulators[i].state |= VREG_GET_REGULATOR_MASK; reg_cnt = regulator_count_voltages(regulators[i].regulator); - /* Set voltage to nominal. Exclude swtiches e.g. LVS */ if ((voltage_level[i].nominal_min || voltage_level[i].max_voltage) && (reg_cnt > 0)) { @@ -561,8 +676,7 @@ static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type, { switch (hw_type) { case WCNSS_PRONTO_HW: - wcnss_vregs_off(iris_vregs_pronto, - ARRAY_SIZE(iris_vregs_pronto), + wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs), cfg->iris_vlevel); break; default: @@ -579,8 +693,7 @@ static int wcnss_iris_vregs_on(struct device *dev, switch (hw_type) { case WCNSS_PRONTO_HW: - ret = wcnss_vregs_on(dev, iris_vregs_pronto, - ARRAY_SIZE(iris_vregs_pronto), + ret = wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs), cfg->iris_vlevel); break; default: diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index e99d46ca51b0..b604f61e1a05 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -37,6 +37,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/pm_qos.h> #include <linux/bitops.h> +#include <soc/qcom/socinfo.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_notif.h> @@ -63,6 +64,21 @@ #define WCNSS_CONFIG_UNSPECIFIED (-1) #define UINT32_MAX (0xFFFFFFFFU) +#define SUBSYS_NOTIF_MIN_INDEX 0 +#define SUBSYS_NOTIF_MAX_INDEX 9 +char *wcnss_subsys_notif_type[] = { + "SUBSYS_BEFORE_SHUTDOWN", + "SUBSYS_AFTER_SHUTDOWN", + "SUBSYS_BEFORE_POWERUP", + "SUBSYS_AFTER_POWERUP", + "SUBSYS_RAMDUMP_NOTIFICATION", + "SUBSYS_POWERUP_FAILURE", + "SUBSYS_PROXY_VOTE", + "SUBSYS_PROXY_UNVOTE", + "SUBSYS_SOC_RESET", + "SUBSYS_NOTIF_TYPE_COUNT" +}; + static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED; module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present"); @@ -187,11 +203,9 @@ static DEFINE_SPINLOCK(reg_spinlock); #define WCNSS_MAX_BUILD_VER_LEN 256 #define WCNSS_MAX_CMD_LEN (128) #define WCNSS_MIN_CMD_LEN (3) -#define WCNSS_MIN_SERIAL_LEN (6) /* control messages from userspace */ #define WCNSS_USR_CTRL_MSG_START 0x00000000 -#define WCNSS_USR_SERIAL_NUM (WCNSS_USR_CTRL_MSG_START + 1) #define WCNSS_USR_HAS_CAL_DATA (WCNSS_USR_CTRL_MSG_START + 2) #define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3) @@ -482,34 +496,6 @@ static ssize_t wcnss_wlan_macaddr_show(struct device *dev, static DEVICE_ATTR(wcnss_mac_addr, S_IRUSR | S_IWUSR, wcnss_wlan_macaddr_show, wcnss_wlan_macaddr_store); -static ssize_t wcnss_serial_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - if (!penv) - return -ENODEV; - - return scnprintf(buf, PAGE_SIZE, "%08X\n", penv->serial_number); -} - -static ssize_t wcnss_serial_number_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int value; - - if (!penv) - return -ENODEV; - - if (sscanf(buf, "%08X", &value) != 1) - return -EINVAL; - - penv->serial_number = value; - return count; -} - -static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR, - wcnss_serial_number_show, wcnss_serial_number_store); - - static ssize_t wcnss_thermal_mitigation_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1178,13 +1164,9 @@ static int wcnss_create_sysfs(struct device *dev) if (!dev) return -ENODEV; - ret = device_create_file(dev, &dev_attr_serial_number); - if (ret) - return ret; - ret = device_create_file(dev, &dev_attr_thermal_mitigation); if (ret) - goto remove_serial; + return ret; ret = device_create_file(dev, &dev_attr_wcnss_version); if (ret) @@ -1200,8 +1182,6 @@ remove_version: device_remove_file(dev, &dev_attr_wcnss_version); remove_thermal: device_remove_file(dev, &dev_attr_thermal_mitigation); -remove_serial: - device_remove_file(dev, &dev_attr_serial_number); return ret; } @@ -1209,7 +1189,6 @@ remove_serial: static void wcnss_remove_sysfs(struct device *dev) { if (dev) { - device_remove_file(dev, &dev_attr_serial_number); device_remove_file(dev, &dev_attr_thermal_mitigation); device_remove_file(dev, &dev_attr_wcnss_version); device_remove_file(dev, &dev_attr_wcnss_mac_addr); @@ -1657,8 +1636,13 @@ EXPORT_SYMBOL(wcnss_unregister_thermal_mitigation); unsigned int wcnss_get_serial_number(void) { - if (penv) + if (penv) { + penv->serial_number = socinfo_get_serial_number(); + pr_info("%s: Device serial number: %u\n", + __func__, penv->serial_number); return penv->serial_number; + } + return 0; } EXPORT_SYMBOL(wcnss_get_serial_number); @@ -2648,15 +2632,6 @@ void process_usr_ctrl_cmd(u8 *buf, size_t len) switch (cmd) { - case WCNSS_USR_SERIAL_NUM: - if (WCNSS_MIN_SERIAL_LEN > len) { - pr_err("%s: Invalid serial number\n", __func__); - return; - } - penv->serial_number = buf[2] << 24 | buf[3] << 16 - | buf[4] << 8 | buf[5]; - break; - case WCNSS_USR_HAS_CAL_DATA: if (1 < buf[2]) pr_err("%s: Invalid data for cal %d\n", __func__, @@ -2714,50 +2689,15 @@ static struct miscdevice wcnss_usr_ctrl = { }; static int -wcnss_dt_parse_vreg_level(struct device *dev, int index, - const char *current_vreg_name, const char *vreg_name, - struct vregs_level *vlevel) -{ - int ret = 0; - /* array used to store nominal, low and high voltage values - */ - u32 voltage_levels[3], current_vreg; - - ret = of_property_read_u32_array(dev->of_node, vreg_name, - voltage_levels, - ARRAY_SIZE(voltage_levels)); - if (ret) { - dev_err(dev, "error reading %s property\n", vreg_name); - return ret; - } - - vlevel[index].nominal_min = voltage_levels[0]; - vlevel[index].low_power_min = voltage_levels[1]; - vlevel[index].max_voltage = voltage_levels[2]; - - ret = of_property_read_u32(dev->of_node, current_vreg_name, - ¤t_vreg); - if (ret) { - dev_err(dev, "error reading %s property\n", current_vreg_name); - return ret; - } - - vlevel[index].uA_load = current_vreg; - - return ret; -} - -static int wcnss_trigger_config(struct platform_device *pdev) { int ret; - int rc, index = 0; + int rc; struct qcom_wcnss_opts *pdata; struct resource *res; int is_pronto_vadc; int is_pronto_v3; int pil_retry = 0; - struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config; struct device_node *node = (&pdev->dev)->of_node; int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw"); @@ -2769,93 +2709,14 @@ wcnss_trigger_config(struct platform_device *pdev) penv->is_a2xb_split_reg = of_property_read_bool(node, "qcom,has-a2xb-split-reg"); - wlan_cfg->wcn_external_gpio_support = - of_property_read_bool(node, "qcom,wcn-external-gpio-support"); - if (of_property_read_u32(node, "qcom,wlan-rx-buff-count", &penv->wlan_rx_buff_count)) { penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT; } - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddmx-current", - "qcom,vddmx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddcx-current", - "qcom,vddcx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,pronto-vddpx-current", - "qcom,vddpx-voltage-level", - penv->wlan_config.pronto_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - /* assign 0 to index now onwards, index variable re used to - * represent iris regulator index - */ - index = 0; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vddxo-current", - "qcom,iris-vddxo-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vddrfa-current", - "qcom,iris-vddrfa-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; - } - - if (!wlan_cfg->wcn_external_gpio_support) { - index++; - ret = wcnss_dt_parse_vreg_level( - &pdev->dev, index, - "qcom,iris-vddpa-current", - "qcom,iris-vddpa-voltage-level", - penv->wlan_config.iris_vlevel); - if (ret) { - dev_err(&pdev->dev, - "error reading voltage-level property\n"); - goto fail; - } - } - - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vdddig-current", - "qcom,iris-vdddig-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); + rc = wcnss_parse_voltage_regulator(&penv->wlan_config, &pdev->dev); + if (rc) { + dev_err(&pdev->dev, "Failed to parse voltage regulators\n"); goto fail; } @@ -3201,7 +3062,7 @@ wcnss_trigger_config(struct platform_device *pdev) penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss"); if (IS_ERR(penv->vadc_dev)) { - pr_err("%s: vadc get failed\n", __func__); + pr_debug("%s: vadc get failed\n", __func__); penv->vadc_dev = NULL; } else { rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt); @@ -3477,7 +3338,15 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, struct notif_data *data = (struct notif_data *)ss_handle; int ret, xo_mode; - pr_info("%s: wcnss notification event: %lu\n", __func__, code); + if (!(code >= SUBSYS_NOTIF_MIN_INDEX) && + (code <= SUBSYS_NOTIF_MAX_INDEX)) { + pr_debug("%s: Invaild subsystem notification code: %lu\n", + __func__, code); + return NOTIFY_DONE; + } + + pr_debug("%s: wcnss notification event: %lu : %s\n", + __func__, code, wcnss_subsys_notif_type[code]); if (code == SUBSYS_PROXY_VOTE) { if (pdev && pwlanconfig) { |
