summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/msm/msm_rmnet_mhi.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c6
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c129
5 files changed, 104 insertions, 63 deletions
diff --git a/drivers/net/ethernet/msm/msm_rmnet_mhi.c b/drivers/net/ethernet/msm/msm_rmnet_mhi.c
index 015cb99d445b..60b7a64c2edb 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_mhi.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_mhi.c
@@ -983,14 +983,17 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info)
if (cb_info->chan == rmnet_mhi_ptr->rx_channel) {
rmnet_log(rmnet_mhi_ptr, MSG_INFO,
"Receive MHI_DISABLE notification for rx path\n");
- rmnet_mhi_disable(rmnet_mhi_ptr);
+ if (rmnet_mhi_ptr->dev)
+ rmnet_mhi_disable(rmnet_mhi_ptr);
} else {
rmnet_log(rmnet_mhi_ptr, MSG_INFO,
"Receive MHI_DISABLE notification for tx path\n");
rmnet_mhi_ptr->tx_enabled = 0;
- rmnet_mhi_internal_clean_unmap_buffers
- (rmnet_mhi_ptr->dev, &rmnet_mhi_ptr->tx_buffers,
- DMA_TO_DEVICE);
+ if (rmnet_mhi_ptr->dev)
+ rmnet_mhi_internal_clean_unmap_buffers(
+ rmnet_mhi_ptr->dev,
+ &rmnet_mhi_ptr->tx_buffers,
+ DMA_TO_DEVICE);
}
/* Remove all votes disabling low power mode */
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 6dd396430f19..b0d6c2614731 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -122,6 +122,19 @@ struct htt_msdu_ext_desc {
| HTT_MSDU_EXT_DESC_FLAG_TCP_IPV4_CSUM_ENABLE \
| HTT_MSDU_EXT_DESC_FLAG_TCP_IPV6_CSUM_ENABLE)
+#define HTT_TX_IPV4_CSUM_EN BIT(16)
+#define HTT_TX_UDP_IPV4_CSUM_EN BIT(17)
+#define HTT_TX_UDP_IPV6_CSUM_EN BIT(18)
+#define HTT_TX_TCP_IPV4_CSUM_EN BIT(19)
+#define HTT_TX_TCP_IPV6_CSUM_EN BIT(20)
+#define HTT_TX_PARTIAL_CSUM_EN BIT(21)
+
+#define HTT_TX_CHECKSUM_ENABLE (HTT_TX_IPV4_CSUM_EN \
+ | HTT_TX_UDP_IPV4_CSUM_EN \
+ | HTT_TX_UDP_IPV6_CSUM_EN \
+ | HTT_TX_TCP_IPV4_CSUM_EN \
+ | HTT_TX_TCP_IPV6_CSUM_EN)
+
enum htt_data_tx_desc_flags0 {
HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT = 1 << 0,
HTT_DATA_TX_DESC_FLAGS0_NO_AGGR = 1 << 1,
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 62e7f5e4b6fc..1b59721a91ac 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -1051,8 +1051,14 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
- if (ar->hw_params.continuous_frag_desc)
+ if (ar->hw_params.continuous_frag_desc) {
ext_desc->flags |= HTT_MSDU_CHECKSUM_ENABLE;
+ if (QCA_REV_WCN3990(ar)) {
+ memset(ext_desc->tso_flag, 0,
+ sizeof(ext_desc->tso_flag));
+ ext_desc->tso_flag[3] |= HTT_TX_CHECKSUM_ENABLE;
+ }
+ }
}
/* Prevent firmware from sending up tx inspection requests. There's
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index d1775748a7cd..b9d08b4b4cc5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7998,10 +7998,8 @@ int ath10k_mac_register(struct ath10k *ar)
goto err_free;
}
- if (!QCA_REV_WCN3990(ar)) {
- if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
- ar->hw->netdev_features = NETIF_F_HW_CSUM;
- }
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
+ ar->hw->netdev_features = NETIF_F_HW_CSUM;
if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
/* Init ath dfs pattern detector */
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 3f9eeabc5464..505a9e016777 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -192,6 +192,8 @@ static DEFINE_SPINLOCK(reg_spinlock);
#define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3)
#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define SHOW_MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x\n"
+#define WCNSS_USER_MAC_ADDR_LENGTH 18
/* message types */
#define WCNSS_CTRL_MSG_START 0x01000000
@@ -396,7 +398,6 @@ static struct {
int user_cal_available;
u32 user_cal_rcvd;
int user_cal_exp_size;
- int device_opened;
int iris_xo_mode_set;
int fw_vbatt_state;
char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE];
@@ -427,23 +428,28 @@ static struct {
static ssize_t wcnss_wlan_macaddr_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- char macAddr[WLAN_MAC_ADDR_SIZE];
+ int index;
+ int macAddr[WLAN_MAC_ADDR_SIZE];
if (!penv)
return -ENODEV;
- pr_debug("%s: Receive MAC Addr From user space: %s\n", __func__, buf);
+ if (strlen(buf) != WCNSS_USER_MAC_ADDR_LENGTH) {
+ dev_err(dev, "%s: Invalid MAC addr length\n", __func__);
+ return -EINVAL;
+ }
if (WLAN_MAC_ADDR_SIZE != sscanf(buf, MAC_ADDRESS_STR,
- (int *)&macAddr[0], (int *)&macAddr[1],
- (int *)&macAddr[2], (int *)&macAddr[3],
- (int *)&macAddr[4], (int *)&macAddr[5])) {
-
+ &macAddr[0], &macAddr[1], &macAddr[2],
+ &macAddr[3], &macAddr[4], &macAddr[5])) {
pr_err("%s: Failed to Copy MAC\n", __func__);
return -EINVAL;
}
- memcpy(penv->wlan_nv_macAddr, macAddr, sizeof(penv->wlan_nv_macAddr));
+ for (index = 0; index < WLAN_MAC_ADDR_SIZE; index++) {
+ memcpy(&penv->wlan_nv_macAddr[index],
+ (char *)&macAddr[index], sizeof(char));
+ }
pr_info("%s: Write MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
@@ -459,7 +465,7 @@ static ssize_t wcnss_wlan_macaddr_show(struct device *dev,
if (!penv)
return -ENODEV;
- return scnprintf(buf, PAGE_SIZE, MAC_ADDRESS_STR,
+ return scnprintf(buf, PAGE_SIZE, SHOW_MAC_ADDRESS_STR,
penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
@@ -2038,21 +2044,23 @@ void extract_cal_data(int len)
return;
}
+ mutex_lock(&penv->dev_lock);
rc = smd_read(penv->smd_ch, (unsigned char *)&calhdr,
sizeof(struct cal_data_params));
if (rc < sizeof(struct cal_data_params)) {
pr_err("wcnss: incomplete cal header read from smd\n");
+ mutex_unlock(&penv->dev_lock);
return;
}
if (penv->fw_cal_exp_frag != calhdr.frag_number) {
pr_err("wcnss: Invalid frgament");
- goto exit;
+ goto unlock_exit;
}
if (calhdr.frag_size > WCNSS_MAX_FRAME_SIZE) {
pr_err("wcnss: Invalid fragment size");
- goto exit;
+ goto unlock_exit;
}
if (penv->fw_cal_available) {
@@ -2061,8 +2069,9 @@ void extract_cal_data(int len)
penv->fw_cal_exp_frag++;
if (calhdr.msg_flags & LAST_FRAGMENT) {
penv->fw_cal_exp_frag = 0;
- goto exit;
+ goto unlock_exit;
}
+ mutex_unlock(&penv->dev_lock);
return;
}
@@ -2070,7 +2079,7 @@ void extract_cal_data(int len)
if (calhdr.total_size > MAX_CALIBRATED_DATA_SIZE) {
pr_err("wcnss: Invalid cal data size %d",
calhdr.total_size);
- goto exit;
+ goto unlock_exit;
}
kfree(penv->fw_cal_data);
penv->fw_cal_rcvd = 0;
@@ -2078,11 +2087,10 @@ void extract_cal_data(int len)
GFP_KERNEL);
if (penv->fw_cal_data == NULL) {
smd_read(penv->smd_ch, NULL, calhdr.frag_size);
- goto exit;
+ goto unlock_exit;
}
}
- mutex_lock(&penv->dev_lock);
if (penv->fw_cal_rcvd + calhdr.frag_size >
MAX_CALIBRATED_DATA_SIZE) {
pr_err("calibrated data size is more than expected %d",
@@ -2117,13 +2125,10 @@ void extract_cal_data(int len)
unlock_exit:
mutex_unlock(&penv->dev_lock);
-
-exit:
wcnss_send_cal_rsp(fw_status);
return;
}
-
static void wcnssctrl_rx_handler(struct work_struct *worker)
{
int len = 0;
@@ -3258,14 +3263,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file)
return -EFAULT;
}
- mutex_lock(&penv->dev_lock);
- penv->user_cal_rcvd = 0;
- penv->user_cal_read = 0;
- penv->user_cal_available = false;
- penv->user_cal_data = NULL;
- penv->device_opened = 1;
- mutex_unlock(&penv->dev_lock);
-
return rc;
}
@@ -3274,7 +3271,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user
{
int rc = 0;
- if (!penv || !penv->device_opened)
+ if (!penv)
return -EFAULT;
rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd
@@ -3311,55 +3308,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user
*user_buffer, size_t count, loff_t *position)
{
int rc = 0;
- u32 size = 0;
+ char *cal_data = NULL;
- if (!penv || !penv->device_opened || penv->user_cal_available)
+ if (!penv || penv->user_cal_available)
return -EFAULT;
- if (penv->user_cal_rcvd == 0 && count >= 4
- && !penv->user_cal_data) {
- rc = copy_from_user((void *)&size, user_buffer, 4);
- if (!size || size > MAX_CALIBRATED_DATA_SIZE) {
- pr_err(DEVICE " invalid size to write %d\n", size);
+ if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) {
+ mutex_lock(&penv->dev_lock);
+ rc = copy_from_user((void *)&penv->user_cal_exp_size,
+ user_buffer, 4);
+ if (!penv->user_cal_exp_size ||
+ penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) {
+ pr_err(DEVICE " invalid size to write %d\n",
+ penv->user_cal_exp_size);
+ penv->user_cal_exp_size = 0;
+ mutex_unlock(&penv->dev_lock);
return -EFAULT;
}
-
- rc += count;
- count -= 4;
- penv->user_cal_exp_size = size;
- penv->user_cal_data = kmalloc(size, GFP_KERNEL);
- if (penv->user_cal_data == NULL) {
- pr_err(DEVICE " no memory to write\n");
- return -ENOMEM;
- }
- if (0 == count)
- goto exit;
-
- } else if (penv->user_cal_rcvd == 0 && count < 4)
+ mutex_unlock(&penv->dev_lock);
+ return count;
+ } else if (!penv->user_cal_rcvd && count < 4) {
return -EFAULT;
+ }
+ mutex_lock(&penv->dev_lock);
if ((UINT32_MAX - count < penv->user_cal_rcvd) ||
(penv->user_cal_exp_size < count + penv->user_cal_rcvd)) {
pr_err(DEVICE " invalid size to write %zu\n", count +
penv->user_cal_rcvd);
- rc = -ENOMEM;
- goto exit;
+ mutex_unlock(&penv->dev_lock);
+ return -ENOMEM;
}
- rc = copy_from_user((void *)penv->user_cal_data +
- penv->user_cal_rcvd, user_buffer, count);
- if (0 == rc) {
+
+ cal_data = kmalloc(count, GFP_KERNEL);
+ if (!cal_data) {
+ mutex_unlock(&penv->dev_lock);
+ return -ENOMEM;
+ }
+
+ rc = copy_from_user(cal_data, user_buffer, count);
+ if (!rc) {
+ memcpy(penv->user_cal_data + penv->user_cal_rcvd,
+ cal_data, count);
penv->user_cal_rcvd += count;
rc += count;
}
+
+ kfree(cal_data);
if (penv->user_cal_rcvd == penv->user_cal_exp_size) {
penv->user_cal_available = true;
pr_info_ratelimited("wcnss: user cal written");
}
+ mutex_unlock(&penv->dev_lock);
-exit:
return rc;
}
+static int wcnss_node_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
void *ss_handle)
@@ -3418,6 +3426,7 @@ static const struct file_operations wcnss_node_fops = {
.open = wcnss_node_open,
.read = wcnss_wlan_read,
.write = wcnss_wlan_write,
+ .release = wcnss_node_release,
};
static struct miscdevice wcnss_misc = {
@@ -3445,6 +3454,13 @@ wcnss_wlan_probe(struct platform_device *pdev)
}
penv->pdev = pdev;
+ penv->user_cal_data =
+ devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL);
+ if (!penv->user_cal_data) {
+ dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n");
+ return -ENOMEM;
+ }
+
/* register sysfs entries */
ret = wcnss_create_sysfs(&pdev->dev);
if (ret) {
@@ -3465,6 +3481,11 @@ wcnss_wlan_probe(struct platform_device *pdev)
mutex_init(&penv->pm_qos_mutex);
init_waitqueue_head(&penv->read_wait);
+ penv->user_cal_rcvd = 0;
+ penv->user_cal_read = 0;
+ penv->user_cal_exp_size = 0;
+ penv->user_cal_available = false;
+
/* Since we were built into the kernel we'll be called as part
* of kernel initialization. We don't know if userspace
* applications are available to service PIL at this time