mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 16:16:15 -04:00
Merge f3f68f9615 on remote branch
Change-Id: Ic162f491a5bce4793b25a54cf56256963c819495
This commit is contained in:
commit
ea45b4c722
67 changed files with 2283 additions and 217 deletions
|
|
@ -1 +1 @@
|
|||
LTS_5.4.147_983a7e7c981b
|
||||
LTS_5.4.147_f2bbf1b7baa5
|
||||
|
|
|
|||
|
|
@ -810,9 +810,7 @@ CONFIG_SND_DYNAMIC_MINORS=y
|
|||
# CONFIG_SND_AUDIO_GRAPH_CARD is not set
|
||||
# CONFIG_HID_PRODIKEYS is not set
|
||||
# CONFIG_USB_CONFIGFS_F_AUDIO_SRC is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC1 is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC2 is not set
|
||||
# CONFIG_USB_CONFIGFS_F_MIDI is not set
|
||||
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
|
||||
CONFIG_MFD_SPMI_PMIC=y
|
||||
|
|
|
|||
4
arch/arm/configs/vendor/sdxnightjar.config
vendored
4
arch/arm/configs/vendor/sdxnightjar.config
vendored
|
|
@ -850,12 +850,12 @@ CONFIG_SND_DYNAMIC_MINORS=y
|
|||
# CONFIG_SND_AUDIO_GRAPH_CARD is not set
|
||||
# CONFIG_HID_PRODIKEYS is not set
|
||||
# CONFIG_USB_CONFIGFS_F_AUDIO_SRC is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC1 is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
|
||||
# CONFIG_USB_CONFIGFS_F_UAC2 is not set
|
||||
# CONFIG_USB_CONFIGFS_F_MIDI is not set
|
||||
# CONFIG_MEDIA_SUPPORT is not set
|
||||
# CONFIG_SND_SOC_TLV320AIC3X is not set
|
||||
CONFIG_USB_CONFIGFS_F_UAC1=y
|
||||
CONFIG_USB_CONFIGFS_F_UAC2=y
|
||||
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
|
||||
CONFIG_MFD_SPMI_PMIC=y
|
||||
# CONFIG_QCOM_COINCELL is not set
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ static acpi_status find_mboard_resource(acpi_handle handle, u32 lvl,
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
static bool is_acpi_reserved(u64 start, u64 end, unsigned not_used)
|
||||
static bool is_acpi_reserved(u64 start, u64 end, enum e820_type not_used)
|
||||
{
|
||||
struct resource mcfg_res;
|
||||
|
||||
|
|
@ -442,7 +442,7 @@ static bool is_acpi_reserved(u64 start, u64 end, unsigned not_used)
|
|||
return mcfg_res.flags;
|
||||
}
|
||||
|
||||
typedef bool (*check_reserved_t)(u64 start, u64 end, unsigned type);
|
||||
typedef bool (*check_reserved_t)(u64 start, u64 end, enum e820_type type);
|
||||
|
||||
static bool __ref is_mmconf_reserved(check_reserved_t is_reserved,
|
||||
struct pci_mmcfg_region *cfg,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static ssize_t active_time_ms_show(struct device *dev,
|
|||
ktime_t active_time =
|
||||
ws->active ? ktime_sub(ktime_get(), ws->last_time) : 0;
|
||||
|
||||
return sprintf(buf, "%lld\n", ktime_to_ms(active_time));
|
||||
return sysfs_emit(buf, "%lld\n", ktime_to_ms(active_time));
|
||||
}
|
||||
static DEVICE_ATTR_RO(active_time_ms);
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ static ssize_t total_time_ms_show(struct device *dev,
|
|||
active_time = ktime_sub(ktime_get(), ws->last_time);
|
||||
total_time = ktime_add(total_time, active_time);
|
||||
}
|
||||
return sprintf(buf, "%lld\n", ktime_to_ms(total_time));
|
||||
return sysfs_emit(buf, "%lld\n", ktime_to_ms(total_time));
|
||||
}
|
||||
static DEVICE_ATTR_RO(total_time_ms);
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ static ssize_t max_time_ms_show(struct device *dev,
|
|||
if (active_time > max_time)
|
||||
max_time = active_time;
|
||||
}
|
||||
return sprintf(buf, "%lld\n", ktime_to_ms(max_time));
|
||||
return sysfs_emit(buf, "%lld\n", ktime_to_ms(max_time));
|
||||
}
|
||||
static DEVICE_ATTR_RO(max_time_ms);
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ static ssize_t last_change_ms_show(struct device *dev,
|
|||
{
|
||||
struct wakeup_source *ws = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%lld\n", ktime_to_ms(ws->last_time));
|
||||
return sysfs_emit(buf, "%lld\n", ktime_to_ms(ws->last_time));
|
||||
}
|
||||
static DEVICE_ATTR_RO(last_change_ms);
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
struct wakeup_source *ws = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", ws->name);
|
||||
return sysfs_emit(buf, "%s\n", ws->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ static ssize_t prevent_suspend_time_ms_show(struct device *dev,
|
|||
prevent_sleep_time = ktime_add(prevent_sleep_time,
|
||||
ktime_sub(ktime_get(), ws->start_prevent_time));
|
||||
}
|
||||
return sprintf(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
|
||||
return sysfs_emit(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
|
||||
}
|
||||
static DEVICE_ATTR_RO(prevent_suspend_time_ms);
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,17 @@ bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie)
|
|||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
int i;
|
||||
bool result = false;
|
||||
struct {
|
||||
char *name;
|
||||
u32 offset;
|
||||
} error_reg[] = {
|
||||
{ "ERROR_DBG1", BHI_ERRDBG1 },
|
||||
{ "ERROR_DBG2", BHI_ERRDBG2 },
|
||||
{ "ERROR_DBG3", BHI_ERRDBG3 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
if (!mhi_cntrl->rddm_supported || !cookie)
|
||||
return false;
|
||||
|
|
@ -152,15 +163,23 @@ bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie)
|
|||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
|
||||
return false;
|
||||
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_ERRDBG2, &val);
|
||||
if (ret)
|
||||
return false;
|
||||
/* look for an RDDM cookie match in any of the error debug registers */
|
||||
for (i = 0; error_reg[i].name; i++) {
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi,
|
||||
error_reg[i].offset, &val);
|
||||
if (ret)
|
||||
break;
|
||||
MHI_CNTRL_LOG("reg:%s value:0x%x\n", error_reg[i].name, val);
|
||||
|
||||
MHI_CNTRL_LOG("BHI_ERRDBG2 value:0x%x\n", val);
|
||||
if (val == cookie)
|
||||
return true;
|
||||
if (!(val ^ cookie)) {
|
||||
MHI_CNTRL_ERR("RDDM cookie found in %s\n",
|
||||
error_reg[i].name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
MHI_CNTRL_ERR("RDDM cookie not found\n");
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_scan_rddm_cookie);
|
||||
|
||||
|
|
|
|||
|
|
@ -5350,6 +5350,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s%s%s%s%s\n", single_line, single_line,
|
||||
single_line, single_line, single_line);
|
||||
spin_lock(&me->hlock);
|
||||
hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n",
|
||||
|
|
@ -5357,18 +5358,21 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
(uint32_t)gmaps->size,
|
||||
gmaps->va);
|
||||
}
|
||||
spin_unlock(&me->hlock);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20s|%-20s|%-20s|%-20s\n",
|
||||
"len", "refs", "raddr", "flags");
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s%s%s%s%s\n", single_line, single_line,
|
||||
single_line, single_line, single_line);
|
||||
spin_lock(&me->hlock);
|
||||
hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"0x%-18X|%-20d|%-20lu|%-20u\n",
|
||||
(uint32_t)gmaps->len, gmaps->refs,
|
||||
gmaps->raddr, gmaps->flags);
|
||||
}
|
||||
spin_unlock(&me->hlock);
|
||||
} else {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"\n%s %13s %d\n", "cid", ":", fl->cid);
|
||||
|
|
@ -5410,12 +5414,14 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
"%s%s%s%s%s\n",
|
||||
single_line, single_line, single_line,
|
||||
single_line, single_line);
|
||||
mutex_lock(&fl->map_mutex);
|
||||
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"0x%-20lX|0x%-20llX|0x%-20zu\n\n",
|
||||
map->va, map->phys,
|
||||
map->size);
|
||||
}
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20s|%-20s|%-20s|%-20s\n",
|
||||
"len", "refs",
|
||||
|
|
@ -5424,24 +5430,27 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
"%s%s%s%s%s\n",
|
||||
single_line, single_line, single_line,
|
||||
single_line, single_line);
|
||||
mutex_lock(&fl->map_mutex);
|
||||
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20zu|%-20d|0x%-20lX|%-20d\n\n",
|
||||
map->len, map->refs, map->raddr,
|
||||
map->uncached);
|
||||
}
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20s|%-20s\n", "secure", "attr");
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s%s%s%s%s\n",
|
||||
single_line, single_line, single_line,
|
||||
single_line, single_line);
|
||||
mutex_lock(&fl->map_mutex);
|
||||
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%-20d|0x%-20lX\n\n",
|
||||
map->secure, map->attr);
|
||||
}
|
||||
|
||||
mutex_unlock(&fl->map_mutex);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"\n======%s %s %s======\n", title,
|
||||
" LIST OF BUFS ", title);
|
||||
|
|
|
|||
|
|
@ -776,7 +776,7 @@ static int cpu_power_select(struct cpuidle_device *dev,
|
|||
}
|
||||
|
||||
done_select:
|
||||
trace_cpu_power_select(best_level, sleep_us, latency_us, 0);
|
||||
trace_cpu_power_select(best_level, sleep_us, latency_us, cpu->bias);
|
||||
|
||||
trace_cpu_pred_select(idx_restrict_time ? 2 : (ipi_predicted ?
|
||||
3 : (predicted ? 1 : 0)), predicted, htime);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/component.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -3131,12 +3132,14 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
|
|||
unsigned int status, i;
|
||||
const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||
unsigned int reg_offset = gpudev->reg_offsets[offset];
|
||||
u64 ts1, ts2;
|
||||
|
||||
adreno_writereg(adreno_dev, offset, val);
|
||||
|
||||
if (!gmu_core_isenabled(KGSL_DEVICE(adreno_dev)))
|
||||
return 0;
|
||||
|
||||
ts1 = gpudev->read_alwayson(adreno_dev);
|
||||
for (i = 0; i < GMU_CORE_LONG_WAKEUP_RETRY_LIMIT; i++) {
|
||||
/*
|
||||
* Make sure the previous register write is posted before
|
||||
|
|
@ -3165,10 +3168,10 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
|
|||
return 0;
|
||||
|
||||
if (i == GMU_CORE_LONG_WAKEUP_RETRY_LIMIT) {
|
||||
ts2 = gpudev->read_alwayson(adreno_dev);
|
||||
dev_err(adreno_dev->dev.dev,
|
||||
"Timed out waiting %d usecs to write fenced register 0x%x\n",
|
||||
i * GMU_CORE_WAKEUP_DELAY_US,
|
||||
reg_offset);
|
||||
"Timed out waiting %d usecs to write fenced register 0x%x, timestamps: %llx %llx\n",
|
||||
i * GMU_CORE_WAKEUP_DELAY_US, reg_offset, ts1, ts2);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <uapi/linux/msm_ion.h>
|
||||
|
|
@ -2517,6 +2518,15 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, unsigned long useraddr)
|
|||
|
||||
ret = sg_alloc_table_from_pages(memdesc->sgt, pages, npages,
|
||||
0, memdesc->size, GFP_KERNEL);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = kgsl_cache_range_op(memdesc, 0, memdesc->size,
|
||||
KGSL_CACHE_OP_FLUSH);
|
||||
|
||||
if (ret)
|
||||
sg_free_table(memdesc->sgt);
|
||||
out:
|
||||
if (ret) {
|
||||
for (i = 0; i < npages; i++)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
|
|
@ -890,7 +891,12 @@ static int haptics_get_status_data(struct haptics_chip *chip,
|
|||
mod_sel_val[0] = sel & 0xff;
|
||||
mod_sel_val[1] = (sel >> 8) & 0xff;
|
||||
rc = haptics_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_MOD_STATUS_SEL_REG, mod_sel_val, 2);
|
||||
HAP_CFG_MOD_STATUS_XT_V2_REG, &mod_sel_val[1], 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = haptics_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_MOD_STATUS_SEL_REG, mod_sel_val, 1);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1919,10 +1925,17 @@ static int haptics_toggle_module_enable(struct haptics_chip *chip)
|
|||
{
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Updating HAPTICS_EN would vote hBoost enable status. Add 100us
|
||||
* delay before updating HAPTICS_EN for hBoost to have enough time
|
||||
* to handle its power transition.
|
||||
*/
|
||||
usleep_range(100, 101);
|
||||
rc = haptics_module_enable(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
usleep_range(100, 101);
|
||||
return haptics_module_enable(chip, true);
|
||||
}
|
||||
|
||||
|
|
@ -2064,22 +2077,11 @@ static int haptics_load_predefined_effect(struct haptics_chip *chip,
|
|||
return -EINVAL;
|
||||
|
||||
play->effect = effect;
|
||||
if (play->pattern_src == FIFO) {
|
||||
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */
|
||||
rc = haptics_toggle_module_enable(chip);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Clamp VMAX for different vibration strength */
|
||||
rc = haptics_set_vmax_mv(chip, play->vmax_mv);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = haptics_enable_autores(chip, !play->effect->auto_res_disable);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
play->pattern_src = play->effect->src;
|
||||
if (play->pattern_src != PATTERN1 &&
|
||||
play->pattern_src != PATTERN2 &&
|
||||
|
|
@ -2089,6 +2091,17 @@ static int haptics_load_predefined_effect(struct haptics_chip *chip,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (play->pattern_src == FIFO) {
|
||||
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */
|
||||
rc = haptics_toggle_module_enable(chip);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = haptics_enable_autores(chip, !play->effect->auto_res_disable);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
play->brake = play->effect->brake;
|
||||
/* Config brake settings if it's necessary */
|
||||
if (play->brake) {
|
||||
|
|
@ -2252,12 +2265,12 @@ static int haptics_load_custom_effect(struct haptics_chip *chip,
|
|||
play->effect = chip->custom_effect;
|
||||
play->brake = NULL;
|
||||
play->vmax_mv = (magnitude * chip->custom_effect->vmax_mv) / 0x7fff;
|
||||
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */
|
||||
rc = haptics_toggle_module_enable(chip);
|
||||
rc = haptics_set_vmax_mv(chip, play->vmax_mv);
|
||||
if (rc < 0)
|
||||
goto cleanup;
|
||||
|
||||
rc = haptics_set_vmax_mv(chip, play->vmax_mv);
|
||||
/* Toggle HAPTICS_EN for a clear start point of FIFO playing */
|
||||
rc = haptics_toggle_module_enable(chip);
|
||||
if (rc < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
|
@ -2374,6 +2387,46 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip)
|
|||
return (u8)amplitude;
|
||||
}
|
||||
|
||||
static int haptics_stop_fifo_play(struct haptics_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 val;
|
||||
|
||||
if (atomic_read(&chip->play.fifo_status.is_busy) == 0) {
|
||||
dev_dbg(chip->dev, "FIFO playing is not in progress\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = haptics_enable_play(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* restore FIFO play rate back to T_LRA */
|
||||
rc = haptics_set_fifo_playrate(chip, T_LRA);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
haptics_fifo_empty_irq_config(chip, false);
|
||||
kvfree(chip->custom_effect->fifo->samples);
|
||||
chip->custom_effect->fifo->samples = NULL;
|
||||
|
||||
atomic_set(&chip->play.fifo_status.is_busy, 0);
|
||||
|
||||
/*
|
||||
* All other playing modes would use AUTO mode RC
|
||||
* calibration except FIFO streaming mode, so restore
|
||||
* back to AUTO RC calibration after FIFO playing.
|
||||
*/
|
||||
val = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT;
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
dev_dbg(chip->dev, "stopped FIFO playing successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int haptics_upload_effect(struct input_dev *dev,
|
||||
struct ff_effect *effect, struct ff_effect *old)
|
||||
{
|
||||
|
|
@ -2443,46 +2496,21 @@ static int haptics_upload_effect(struct input_dev *dev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
return haptics_wait_hboost_ready(chip);
|
||||
}
|
||||
|
||||
static int haptics_stop_fifo_play(struct haptics_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
u8 val;
|
||||
|
||||
if (atomic_read(&chip->play.fifo_status.is_busy) == 0) {
|
||||
dev_dbg(chip->dev, "FIFO playing is not in progress\n");
|
||||
return 0;
|
||||
rc = haptics_wait_hboost_ready(chip);
|
||||
if (rc < 0 && chip->play.pattern_src == FIFO) {
|
||||
/*
|
||||
* Call haptics_stop_fifo_play(chip) explicitly if hBoost is
|
||||
* not ready for the FIFO play. This drops current FIFO play
|
||||
* but it restores the SW back to initial status so that the
|
||||
* following FIFO play requests can still be served.
|
||||
*/
|
||||
dev_dbg(chip->dev, "stop FIFO play explicitly to restore SW status\n");
|
||||
mutex_lock(&chip->play.lock);
|
||||
haptics_stop_fifo_play(chip);
|
||||
mutex_unlock(&chip->play.lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = haptics_enable_play(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* restore FIFO play rate back to T_LRA */
|
||||
rc = haptics_set_fifo_playrate(chip, T_LRA);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
haptics_fifo_empty_irq_config(chip, false);
|
||||
kvfree(chip->custom_effect->fifo->samples);
|
||||
chip->custom_effect->fifo->samples = NULL;
|
||||
|
||||
atomic_set(&chip->play.fifo_status.is_busy, 0);
|
||||
|
||||
/*
|
||||
* All other playing modes would use AUTO mode RC
|
||||
* calibration except FIFO streaming mode, so restore
|
||||
* back to AUTO RC calibration after FIFO playing.
|
||||
*/
|
||||
val = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT;
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
dev_dbg(chip->dev, "stopped FIFO playing successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -821,9 +821,22 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
|
|||
int err = 0;
|
||||
struct ubi_ainf_peb *aeb, *tmp_aeb;
|
||||
|
||||
if (!list_empty(&ai->free)) {
|
||||
aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list);
|
||||
list_for_each_entry_safe(aeb, tmp_aeb, &ai->free, u.list) {
|
||||
|
||||
list_del(&aeb->u.list);
|
||||
if (aeb->ec == UBI_UNKNOWN) {
|
||||
ubi_err(ubi, "PEB %d in freelist has unknown EC",
|
||||
aeb->pnum);
|
||||
aeb->ec = ai->mean_ec;
|
||||
}
|
||||
err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1);
|
||||
if (err) {
|
||||
ubi_err(ubi, "Erase failed for PEB %d in freelist",
|
||||
aeb->pnum);
|
||||
list_add(&aeb->u.list, &ai->erase);
|
||||
continue;
|
||||
}
|
||||
aeb->ec += 1;
|
||||
dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec);
|
||||
return aeb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ static int __init ubiblock_set_param(const char *val,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
strcpy(buf, val);
|
||||
strlcpy(buf, val, sizeof(buf));
|
||||
|
||||
/* Get rid of the final newline */
|
||||
if (buf[len - 1] == '\n')
|
||||
|
|
@ -141,12 +141,12 @@ static int __init ubiblock_set_param(const char *val,
|
|||
ret = kstrtoint(tokens[1], 10, ¶m->vol_id);
|
||||
if (ret < 0) {
|
||||
param->vol_id = -1;
|
||||
strcpy(param->name, tokens[1]);
|
||||
strlcpy(param->name, tokens[1], UBIBLOCK_PARAM_LEN+1);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* One parameter: must be device path */
|
||||
strcpy(param->name, tokens[0]);
|
||||
strlcpy(param->name, tokens[0], UBIBLOCK_PARAM_LEN+1);
|
||||
param->ubi_num = -1;
|
||||
param->vol_id = -1;
|
||||
}
|
||||
|
|
@ -412,7 +412,8 @@ int ubiblock_create(struct ubi_volume_info *vi)
|
|||
goto out_put_disk;
|
||||
}
|
||||
gd->private_data = dev;
|
||||
sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
|
||||
scnprintf(gd->disk_name, DISK_NAME_LEN, "ubiblock%d_%d",
|
||||
dev->ubi_num, dev->vol_id);
|
||||
set_capacity(gd, disk_capacity);
|
||||
dev->gd = gd;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static DEFINE_SPINLOCK(ubi_devices_lock);
|
|||
static ssize_t version_show(struct class *class, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", UBI_VERSION);
|
||||
return scnprintf(buf, sizeof(int), "%d\n", UBI_VERSION);
|
||||
}
|
||||
static CLASS_ATTR_RO(version);
|
||||
|
||||
|
|
@ -114,6 +114,9 @@ struct class ubi_class = {
|
|||
|
||||
static ssize_t dev_attribute_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
static ssize_t dev_attribute_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
|
||||
/* UBI device attributes (correspond to files in '/<sysfs>/class/ubi/ubiX') */
|
||||
static struct device_attribute dev_eraseblock_size =
|
||||
|
|
@ -140,6 +143,13 @@ static struct device_attribute dev_mtd_num =
|
|||
__ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
|
||||
static struct device_attribute dev_ro_mode =
|
||||
__ATTR(ro_mode, S_IRUGO, dev_attribute_show, NULL);
|
||||
static struct device_attribute dev_mtd_trigger_scrub =
|
||||
__ATTR(scrub_all, 0644,
|
||||
dev_attribute_show, dev_attribute_store);
|
||||
static struct device_attribute dev_mtd_max_scrub_sqnum =
|
||||
__ATTR(scrub_max_sqnum, 0444, dev_attribute_show, NULL);
|
||||
static struct device_attribute dev_mtd_min_scrub_sqnum =
|
||||
__ATTR(scrub_min_sqnum, 0444, dev_attribute_show, NULL);
|
||||
|
||||
/**
|
||||
* ubi_volume_notify - send a volume change notification.
|
||||
|
|
@ -332,6 +342,17 @@ int ubi_major2num(int major)
|
|||
return ubi_num;
|
||||
}
|
||||
|
||||
static unsigned long long get_max_sqnum(struct ubi_device *ubi)
|
||||
{
|
||||
unsigned long long max_sqnum;
|
||||
|
||||
spin_lock(&ubi->ltree_lock);
|
||||
max_sqnum = ubi->global_sqnum - 1;
|
||||
spin_unlock(&ubi->ltree_lock);
|
||||
|
||||
return max_sqnum;
|
||||
}
|
||||
|
||||
/* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */
|
||||
static ssize_t dev_attribute_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
|
@ -355,29 +376,50 @@ static ssize_t dev_attribute_show(struct device *dev,
|
|||
return -ENODEV;
|
||||
|
||||
if (attr == &dev_eraseblock_size)
|
||||
ret = sprintf(buf, "%d\n", ubi->leb_size);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->leb_size);
|
||||
else if (attr == &dev_avail_eraseblocks)
|
||||
ret = sprintf(buf, "%d\n", ubi->avail_pebs);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->avail_pebs);
|
||||
else if (attr == &dev_total_eraseblocks)
|
||||
ret = sprintf(buf, "%d\n", ubi->good_peb_count);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->good_peb_count);
|
||||
else if (attr == &dev_volumes_count)
|
||||
ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->vol_count - UBI_INT_VOL_COUNT);
|
||||
else if (attr == &dev_max_ec)
|
||||
ret = sprintf(buf, "%d\n", ubi->max_ec);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->max_ec);
|
||||
else if (attr == &dev_reserved_for_bad)
|
||||
ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->beb_rsvd_pebs);
|
||||
else if (attr == &dev_bad_peb_count)
|
||||
ret = sprintf(buf, "%d\n", ubi->bad_peb_count);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->bad_peb_count);
|
||||
else if (attr == &dev_max_vol_count)
|
||||
ret = sprintf(buf, "%d\n", ubi->vtbl_slots);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->vtbl_slots);
|
||||
else if (attr == &dev_min_io_size)
|
||||
ret = sprintf(buf, "%d\n", ubi->min_io_size);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->min_io_size);
|
||||
else if (attr == &dev_bgt_enabled)
|
||||
ret = sprintf(buf, "%d\n", ubi->thread_enabled);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->thread_enabled);
|
||||
else if (attr == &dev_mtd_num)
|
||||
ret = sprintf(buf, "%d\n", ubi->mtd->index);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->mtd->index);
|
||||
else if (attr == &dev_ro_mode)
|
||||
ret = sprintf(buf, "%d\n", ubi->ro_mode);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
ubi->ro_mode);
|
||||
else if (attr == &dev_mtd_trigger_scrub)
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
atomic_read(&ubi->scrub_work_count));
|
||||
else if (attr == &dev_mtd_max_scrub_sqnum)
|
||||
ret = scnprintf(buf, sizeof(unsigned long long), "%llu\n",
|
||||
get_max_sqnum(ubi));
|
||||
else if (attr == &dev_mtd_min_scrub_sqnum)
|
||||
ret = scnprintf(buf, sizeof(unsigned long long), "%llu\n",
|
||||
ubi_wl_scrub_get_min_sqnum(ubi));
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
|
|
@ -398,10 +440,46 @@ static struct attribute *ubi_dev_attrs[] = {
|
|||
&dev_bgt_enabled.attr,
|
||||
&dev_mtd_num.attr,
|
||||
&dev_ro_mode.attr,
|
||||
&dev_mtd_trigger_scrub.attr,
|
||||
&dev_mtd_max_scrub_sqnum.attr,
|
||||
&dev_mtd_min_scrub_sqnum.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ubi_dev);
|
||||
|
||||
static ssize_t dev_attribute_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ubi_device *ubi;
|
||||
unsigned long long scrub_sqnum;
|
||||
|
||||
ubi = container_of(dev, struct ubi_device, dev);
|
||||
ubi = ubi_get_device(ubi->ubi_num);
|
||||
if (!ubi)
|
||||
return -ENODEV;
|
||||
|
||||
if (attr == &dev_mtd_trigger_scrub) {
|
||||
if (kstrtoull(buf, 10, &scrub_sqnum)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!ubi->lookuptbl) {
|
||||
pr_err("lookuptbl is null\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
ret = ubi_wl_scrub_all(ubi, scrub_sqnum);
|
||||
if (ret == 0)
|
||||
ret = count;
|
||||
}
|
||||
|
||||
out:
|
||||
ubi_put_device(ubi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dev_release(struct device *dev)
|
||||
{
|
||||
struct ubi_device *ubi = container_of(dev, struct ubi_device, dev);
|
||||
|
|
@ -438,7 +516,8 @@ static int uif_init(struct ubi_device *ubi)
|
|||
int i, err;
|
||||
dev_t dev;
|
||||
|
||||
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
|
||||
scnprintf(ubi->ubi_name, sizeof(UBI_NAME_STR) + 5,
|
||||
UBI_NAME_STR "%d", ubi->ubi_num);
|
||||
|
||||
/*
|
||||
* Major numbers for the UBI character devices are allocated
|
||||
|
|
@ -1376,7 +1455,7 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
strcpy(buf, val);
|
||||
strlcpy(buf, val, sizeof(buf));
|
||||
|
||||
/* Get rid of the final newline */
|
||||
if (buf[len - 1] == '\n')
|
||||
|
|
@ -1391,7 +1470,7 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
|
|||
}
|
||||
|
||||
p = &mtd_dev_param[mtd_devs];
|
||||
strcpy(&p->name[0], tokens[0]);
|
||||
strlcpy(&p->name[0], tokens[0], MTD_PARAM_LEN_MAX);
|
||||
|
||||
token = tokens[1];
|
||||
if (token) {
|
||||
|
|
|
|||
|
|
@ -1056,6 +1056,15 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
dbg_io("write VID header to PEB %d", pnum);
|
||||
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
|
||||
|
||||
/*
|
||||
* Re-erase the PEB before using it. This should minimize any issues
|
||||
* from decay of charge in this block.
|
||||
*/
|
||||
if (ubi->wl_is_inited) {
|
||||
err = ubi_wl_re_erase_peb(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = self_check_peb_ec_hdr(ubi, pnum);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -1074,6 +1083,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
|||
|
||||
err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
|
||||
ubi->vid_hdr_alsize);
|
||||
if (!err && ubi->wl_is_inited)
|
||||
ubi_wl_update_peb_sqnum(ubi, pnum, vid_hdr);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,8 @@ struct ubi_vid_io_buf {
|
|||
* @u.list: link in the protection queue
|
||||
* @ec: erase counter
|
||||
* @pnum: physical eraseblock number
|
||||
* @tagged_scrub_all: if the entry is tagged for scrub all
|
||||
* @sqnum: The sequence number of the vol header.
|
||||
*
|
||||
* This data structure is used in the WL sub-system. Each physical eraseblock
|
||||
* has a corresponding &struct wl_entry object which may be kept in different
|
||||
|
|
@ -182,6 +184,8 @@ struct ubi_wl_entry {
|
|||
} u;
|
||||
int ec;
|
||||
int pnum;
|
||||
unsigned int tagged_scrub_all:1;
|
||||
unsigned long long sqnum;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -625,6 +629,9 @@ struct ubi_device {
|
|||
struct task_struct *bgt_thread;
|
||||
int thread_enabled;
|
||||
char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
|
||||
bool scrub_in_progress;
|
||||
atomic_t scrub_work_count;
|
||||
int wl_is_inited;
|
||||
|
||||
/* I/O sub-system's stuff */
|
||||
long long flash_size;
|
||||
|
|
@ -919,7 +926,12 @@ int ubi_is_erase_work(struct ubi_work *wrk);
|
|||
void ubi_refill_pools(struct ubi_device *ubi);
|
||||
int ubi_ensure_anchor_pebs(struct ubi_device *ubi);
|
||||
int ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force_scrub);
|
||||
|
||||
ssize_t ubi_wl_scrub_all(struct ubi_device *ubi,
|
||||
unsigned long long scrub_sqnum);
|
||||
void ubi_wl_update_peb_sqnum(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr);
|
||||
unsigned long long ubi_wl_scrub_get_min_sqnum(struct ubi_device *ubi);
|
||||
int ubi_wl_re_erase_peb(struct ubi_device *ubi, int pnum);
|
||||
/* io.c */
|
||||
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
||||
int len);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ static struct device_attribute attr_vol_upd_marker =
|
|||
static ssize_t vol_attribute_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
int ret, size;
|
||||
struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
|
||||
struct ubi_device *ubi;
|
||||
|
||||
|
|
@ -73,27 +73,36 @@ static ssize_t vol_attribute_show(struct device *dev,
|
|||
spin_unlock(&ubi->volumes_lock);
|
||||
|
||||
if (attr == &attr_vol_reserved_ebs)
|
||||
ret = sprintf(buf, "%d\n", vol->reserved_pebs);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n", vol->reserved_pebs);
|
||||
else if (attr == &attr_vol_type) {
|
||||
const char *tp;
|
||||
|
||||
if (vol->vol_type == UBI_DYNAMIC_VOLUME)
|
||||
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
|
||||
tp = "dynamic";
|
||||
else
|
||||
size = 8;
|
||||
} else {
|
||||
tp = "static";
|
||||
ret = sprintf(buf, "%s\n", tp);
|
||||
size = 7;
|
||||
}
|
||||
ret = scnprintf(buf, size, "%s\n", tp);
|
||||
} else if (attr == &attr_vol_name)
|
||||
ret = sprintf(buf, "%s\n", vol->name);
|
||||
ret = scnprintf(buf, vol->name_len + 1, "%s\n",
|
||||
vol->name);
|
||||
else if (attr == &attr_vol_corrupted)
|
||||
ret = sprintf(buf, "%d\n", vol->corrupted);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
vol->corrupted);
|
||||
else if (attr == &attr_vol_alignment)
|
||||
ret = sprintf(buf, "%d\n", vol->alignment);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
vol->alignment);
|
||||
else if (attr == &attr_vol_usable_eb_size)
|
||||
ret = sprintf(buf, "%d\n", vol->usable_leb_size);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
vol->usable_leb_size);
|
||||
else if (attr == &attr_vol_data_bytes)
|
||||
ret = sprintf(buf, "%lld\n", vol->used_bytes);
|
||||
ret = scnprintf(buf, sizeof(unsigned long long), "%lld\n",
|
||||
vol->used_bytes);
|
||||
else if (attr == &attr_vol_upd_marker)
|
||||
ret = sprintf(buf, "%d\n", vol->upd_marker);
|
||||
ret = scnprintf(buf, sizeof(int), "%d\n",
|
||||
vol->upd_marker);
|
||||
else
|
||||
/* This must be a bug */
|
||||
ret = -EINVAL;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
#include <linux/crc32.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#include "ubi.h"
|
||||
#include "wl.h"
|
||||
|
||||
|
|
@ -488,6 +489,42 @@ out_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
int ubi_wl_re_erase_peb(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int err;
|
||||
struct ubi_wl_entry *e;
|
||||
struct ubi_ec_hdr *ec_hdr;
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
e = ubi->lookuptbl[pnum];
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
dbg_wl("Re-erase PEB %d, EC %u", e->pnum, e->ec);
|
||||
|
||||
err = self_check_ec(ubi, e->pnum, e->ec);
|
||||
if (err)
|
||||
return -EINVAL;
|
||||
|
||||
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
|
||||
if (!ec_hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
err = ubi_io_sync_erase(ubi, e->pnum, 0);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
|
||||
dbg_wl("re-erased PEB %d, EC %u", e->pnum, e->ec);
|
||||
|
||||
ec_hdr->ec = cpu_to_be64(e->ec);
|
||||
|
||||
err = ubi_io_write_ec_hdr(ubi, e->pnum, ec_hdr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
out_free:
|
||||
kfree(ec_hdr);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* serve_prot_queue - check if it is time to stop protecting PEBs.
|
||||
* @ubi: UBI device description object
|
||||
|
|
@ -863,9 +900,19 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|||
}
|
||||
|
||||
/* The PEB has been successfully moved */
|
||||
if (scrubbing)
|
||||
ubi_msg(ubi, "scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
|
||||
e1->pnum, vol_id, lnum, e2->pnum);
|
||||
if (scrubbing) {
|
||||
spin_lock(&ubi->wl_lock);
|
||||
if (e1->tagged_scrub_all) {
|
||||
WARN_ON(atomic_read(&ubi->scrub_work_count) <= 0);
|
||||
atomic_dec(&ubi->scrub_work_count);
|
||||
e1->tagged_scrub_all = 0;
|
||||
e2->tagged_scrub_all = 0;
|
||||
} else {
|
||||
ubi_msg(ubi, "scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
|
||||
e1->pnum, vol_id, lnum, e2->pnum);
|
||||
}
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
}
|
||||
ubi_free_vid_buf(vidb);
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
|
|
@ -1233,6 +1280,7 @@ int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
|
|||
retry:
|
||||
spin_lock(&ubi->wl_lock);
|
||||
e = ubi->lookuptbl[pnum];
|
||||
e->sqnum = UBI_UNKNOWN;
|
||||
if (e == ubi->move_from) {
|
||||
/*
|
||||
* User is putting the physical eraseblock which was selected to
|
||||
|
|
@ -1269,6 +1317,20 @@ retry:
|
|||
} else if (in_wl_tree(e, &ubi->scrub)) {
|
||||
self_check_in_wl_tree(ubi, e, &ubi->scrub);
|
||||
rb_erase(&e->u.rb, &ubi->scrub);
|
||||
|
||||
/*
|
||||
* Since this PEB has been put we dont need to worry
|
||||
* about it anymore
|
||||
*/
|
||||
if (e->tagged_scrub_all) {
|
||||
int wrk_count;
|
||||
|
||||
wrk_count = atomic_read(&ubi->scrub_work_count);
|
||||
WARN_ON(wrk_count <= 0);
|
||||
|
||||
atomic_dec(&ubi->scrub_work_count);
|
||||
e->tagged_scrub_all = 0;
|
||||
}
|
||||
} else if (in_wl_tree(e, &ubi->erroneous)) {
|
||||
self_check_in_wl_tree(ubi, e, &ubi->erroneous);
|
||||
rb_erase(&e->u.rb, &ubi->erroneous);
|
||||
|
|
@ -1300,6 +1362,197 @@ retry:
|
|||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_scrub_get_min_sqnum - Return the minimum sqnum of the used/pq/scrub.
|
||||
* @ubi: UBI device description object
|
||||
*
|
||||
* This function returns the minimum sqnum of the PEB that are currently in use.
|
||||
*
|
||||
* Return the min sqnum if there are any used PEB's otherwise return ~(0)
|
||||
*
|
||||
*/
|
||||
unsigned long long ubi_wl_scrub_get_min_sqnum(struct ubi_device *ubi)
|
||||
{
|
||||
int i;
|
||||
struct ubi_wl_entry *e, *tmp;
|
||||
struct rb_node *node;
|
||||
unsigned long long min_sqnum = ~0;
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
|
||||
/* Go through the pq list */
|
||||
for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) {
|
||||
list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) {
|
||||
if (e->sqnum < min_sqnum)
|
||||
min_sqnum = e->sqnum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go through used PEB tree */
|
||||
for (node = rb_first(&ubi->used); node; node = rb_next(node)) {
|
||||
e = rb_entry(node, struct ubi_wl_entry, u.rb);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
if (e->sqnum < min_sqnum)
|
||||
min_sqnum = e->sqnum;
|
||||
}
|
||||
/* Go through scrub PEB tree */
|
||||
for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
|
||||
e = rb_entry(node, struct ubi_wl_entry, u.rb);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->scrub);
|
||||
if (e->sqnum < min_sqnum)
|
||||
min_sqnum = e->sqnum;
|
||||
}
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
return min_sqnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_update_peb_sqnum - Update the vol hdr sqnum of the PEB.
|
||||
* @pnum: The PEB number.
|
||||
* @vid_hdr: The vol hdr being written to the PEB.
|
||||
*
|
||||
*/
|
||||
void ubi_wl_update_peb_sqnum(struct ubi_device *ubi, int pnum,
|
||||
struct ubi_vid_hdr *vid_hdr)
|
||||
{
|
||||
struct ubi_wl_entry *e;
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
e = ubi->lookuptbl[pnum];
|
||||
e->sqnum = be64_to_cpu(vid_hdr->sqnum);
|
||||
e->tagged_scrub_all = 0;
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
}
|
||||
|
||||
static int is_ubi_readonly(struct ubi_device *ubi)
|
||||
{
|
||||
int is_readonly = 0;
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
if (ubi->ro_mode || !ubi->thread_enabled ||
|
||||
ubi_dbg_is_bgt_disabled(ubi))
|
||||
is_readonly = 1;
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
return is_readonly;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_scan_all - Scan all PEB's
|
||||
* @ubi: UBI device description object
|
||||
* @scrub_sqnum: The max seqnum of the PEB to scrub from the used/pq lists
|
||||
*
|
||||
* This function schedules all device PEBs for scrubbing if the sqnum of the
|
||||
* vol hdr is less than the sqnum in the trigger.
|
||||
*
|
||||
* Return 0 in case of success, (negative) error code otherwise
|
||||
*
|
||||
*/
|
||||
ssize_t ubi_wl_scrub_all(struct ubi_device *ubi, unsigned long long scrub_sqnum)
|
||||
{
|
||||
struct rb_node *node;
|
||||
struct ubi_wl_entry *e, *tmp;
|
||||
int scrub_count = 0;
|
||||
int total_scrub_count = 0;
|
||||
int err, i;
|
||||
|
||||
if (!ubi->lookuptbl) {
|
||||
ubi_err(ubi, "lookuptbl is null");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (is_ubi_readonly(ubi)) {
|
||||
ubi_err(ubi, "Cannot *Initiate* scrub:background thread disabled or readonly!");
|
||||
return -EROFS;
|
||||
}
|
||||
|
||||
/* Wait for all currently running work to be done! */
|
||||
down_write(&ubi->work_sem);
|
||||
spin_lock(&ubi->wl_lock);
|
||||
ubi_msg(ubi, "Scrub triggered sqnum = %llu!", scrub_sqnum);
|
||||
|
||||
if (ubi->scrub_in_progress) {
|
||||
ubi_err(ubi, "Scrub already in progress, ignoring the trigger");
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
up_write(&ubi->work_sem); /* Allow new work to start. */
|
||||
return -EBUSY;
|
||||
}
|
||||
ubi->scrub_in_progress = true;
|
||||
|
||||
/* Go through scrub PEB tree and count pending */
|
||||
for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
|
||||
e = rb_entry(node, struct ubi_wl_entry, u.rb);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->scrub);
|
||||
e->tagged_scrub_all = 1;
|
||||
total_scrub_count++;
|
||||
}
|
||||
|
||||
/* Move all used pebs to scrub tree */
|
||||
node = rb_first(&ubi->used);
|
||||
while (node != NULL) {
|
||||
e = rb_entry(node, struct ubi_wl_entry, u.rb);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->used);
|
||||
node = rb_next(node);
|
||||
|
||||
if (e->sqnum > scrub_sqnum)
|
||||
continue;
|
||||
rb_erase(&e->u.rb, &ubi->used);
|
||||
wl_tree_add(e, &ubi->scrub);
|
||||
e->tagged_scrub_all = 1;
|
||||
scrub_count++;
|
||||
total_scrub_count++;
|
||||
}
|
||||
|
||||
/* Move all protected pebs to scrub tree */
|
||||
for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) {
|
||||
list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) {
|
||||
|
||||
if (e->sqnum > scrub_sqnum)
|
||||
continue;
|
||||
|
||||
list_del(&e->u.list);
|
||||
wl_tree_add(e, &ubi->scrub);
|
||||
e->tagged_scrub_all = 1;
|
||||
scrub_count++;
|
||||
total_scrub_count++;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&ubi->scrub_work_count, total_scrub_count);
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
up_write(&ubi->work_sem); /* Allow new work to start. */
|
||||
|
||||
/*
|
||||
* Technically scrubbing is the same as wear-leveling, so it is done
|
||||
* by the WL worker.
|
||||
*/
|
||||
err = ensure_wear_leveling(ubi, 0);
|
||||
if (err) {
|
||||
ubi_err(ubi, "Failed to start the WL worker err =%d", err);
|
||||
return err;
|
||||
}
|
||||
ubi_msg(ubi, "Scheduled %d PEB's for scrubbing!", scrub_count);
|
||||
ubi_msg(ubi, "Total PEB's for scrub = %d", total_scrub_count);
|
||||
|
||||
/* Wait for scrub to finish */
|
||||
while (atomic_read(&ubi->scrub_work_count) > 0) {
|
||||
/* Poll every second to check if the scrub work is done */
|
||||
msleep(1000);
|
||||
|
||||
if (is_ubi_readonly(ubi)) {
|
||||
ubi_err(ubi, "Cannot *Complete* scrub:background thread disabled or readonly!");
|
||||
return -EROFS;
|
||||
}
|
||||
wake_up_process(ubi->bgt_thread);
|
||||
}
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
ubi->scrub_in_progress = false;
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
ubi_msg(ubi, "Done scrubbing %d PEB's!", scrub_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubi_wl_scrub_peb - schedule a physical eraseblock for scrubbing.
|
||||
* @ubi: UBI device description object
|
||||
|
|
@ -1753,7 +2006,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|||
ubi->max_ec = ai->max_ec;
|
||||
INIT_LIST_HEAD(&ubi->works);
|
||||
|
||||
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
|
||||
scnprintf(ubi->bgt_name, sizeof(UBI_BGT_NAME_PATTERN)+2,
|
||||
UBI_BGT_NAME_PATTERN, ubi->ubi_num);
|
||||
|
||||
err = -ENOMEM;
|
||||
ubi->lookuptbl = kcalloc(ubi->peb_count, sizeof(void *), GFP_KERNEL);
|
||||
|
|
@ -1786,6 +2040,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|||
|
||||
e->pnum = aeb->pnum;
|
||||
e->ec = aeb->ec;
|
||||
e->tagged_scrub_all = 0;
|
||||
e->sqnum = aeb->sqnum;
|
||||
ubi_assert(e->ec >= 0);
|
||||
|
||||
wl_tree_add(e, &ubi->free);
|
||||
|
|
@ -1808,6 +2064,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|||
|
||||
e->pnum = aeb->pnum;
|
||||
e->ec = aeb->ec;
|
||||
e->tagged_scrub_all = 0;
|
||||
e->sqnum = aeb->sqnum;
|
||||
ubi->lookuptbl[e->pnum] = e;
|
||||
|
||||
if (!aeb->scrub) {
|
||||
|
|
@ -1891,6 +2149,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
|
|||
#ifdef CONFIG_MTD_UBI_FASTMAP
|
||||
ubi_ensure_anchor_pebs(ubi);
|
||||
#endif
|
||||
ubi->wl_is_inited = 1;
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
|
|
|
|||
|
|
@ -973,6 +973,15 @@ int atl2_fw_init(struct atl_hw *hw)
|
|||
|
||||
atl2_get_fw_version(hw);
|
||||
|
||||
/* Warn if FW is lower than 1.3.1 */
|
||||
if (((mcp->fw_rev >> 24) < 1) ||
|
||||
(((mcp->fw_rev >> 16) & 0xFFU) < 3) ||
|
||||
((mcp->fw_rev & 0xFFFFU) < 1))
|
||||
atl_dev_warn("FW_version: %u.%u.%u, is not stable version",
|
||||
(mcp->fw_rev >> 24),
|
||||
((mcp->fw_rev >> 16) & 0xFFU),
|
||||
(mcp->fw_rev & 0xFFFFU));
|
||||
|
||||
mcp->ops = &atl2_fw_ops;
|
||||
atl_dev_dbg("Detect ATL2FW %x\n", mcp->fw_rev);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#define ATL_VERSION "1.1.18"
|
||||
#define ATL_VERSION "1.1.23"
|
||||
|
||||
struct atl_nic;
|
||||
|
||||
|
|
@ -32,8 +32,6 @@ struct atl_nic;
|
|||
|
||||
#define ATL_MAX_QUEUES 8
|
||||
|
||||
#include "atl_fwd.h"
|
||||
|
||||
struct atl_ptp;
|
||||
|
||||
enum {
|
||||
|
|
@ -414,6 +412,7 @@ void atl_update_global_stats(struct atl_nic *nic);
|
|||
void atl_set_loopback(struct atl_nic *nic, int idx, bool on);
|
||||
void atl_set_intr_mod(struct atl_nic *nic);
|
||||
void atl_update_ntuple_flt(struct atl_nic *nic, int idx);
|
||||
int atl_vlan_promisc_status(struct net_device *ndev);
|
||||
void atl_set_vlan_promisc(struct atl_hw *hw, int promisc);
|
||||
int atl_hwsem_get(struct atl_hw *hw, int idx);
|
||||
void atl_hwsem_put(struct atl_hw *hw, int idx);
|
||||
|
|
@ -424,18 +423,6 @@ int atl_msm_write(struct atl_hw *hw, uint32_t addr, uint32_t val);
|
|||
int atl_update_eth_stats(struct atl_nic *nic);
|
||||
void atl_adjust_eth_stats(struct atl_ether_stats *stats,
|
||||
struct atl_ether_stats *base, bool add);
|
||||
void atl_fwd_release_rings(struct atl_nic *nic);
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
enum atl_fwd_notify;
|
||||
int atl_fwd_suspend_rings(struct atl_nic *nic);
|
||||
int atl_fwd_resume_rings(struct atl_nic *nic);
|
||||
void atl_fwd_notify(struct atl_nic *nic, enum atl_fwd_notify notif, void *data);
|
||||
#else
|
||||
static inline int atl_fwd_suspend_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline int atl_fwd_resume_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline void atl_fwd_notify(struct atl_nic *nic,
|
||||
enum atl_fwd_notify notif, void *data) {}
|
||||
#endif
|
||||
int atl_get_lpi_timer(struct atl_nic *nic, uint32_t *lpi_delay);
|
||||
void atl_refresh_rxfs(struct atl_nic *nic);
|
||||
void atl_schedule_work(struct atl_nic *nic);
|
||||
|
|
|
|||
123
drivers/net/ethernet/aquantia/atlantic-fwd/atl_dump.h
Normal file
123
drivers/net/ethernet/aquantia/atlantic-fwd/atl_dump.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Atlantic Network Driver
|
||||
*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ATL_DUMP_H_
|
||||
#define _ATL_DUMP_H_
|
||||
|
||||
enum atl_crash_dump_types {
|
||||
atl_crash_dump_type_regs = 0,
|
||||
atl_crash_dump_type_fwiface = 1,
|
||||
atl_crash_dump_type_act_res = 2,
|
||||
atl_crash_dump_type_ring = 3,
|
||||
};
|
||||
|
||||
/** Some of the registers we can not read safely from the device.
|
||||
* Those will not be read, with value 0xFFFFFFFF stored instead.
|
||||
*/
|
||||
struct atl_crash_dump_regs {
|
||||
u32 type;
|
||||
u32 length;
|
||||
union {
|
||||
u32 regs_data[0x9000/4];
|
||||
struct{
|
||||
u32 mif[0x1000/4];
|
||||
u32 pci[0x1000/4];
|
||||
u32 itr[0x1000/4];
|
||||
u32 com[0x1000/4];
|
||||
u32 mac_phy[0x1000/4];
|
||||
union {
|
||||
u32 rx[0x2000/4];
|
||||
struct{
|
||||
u32 res1[0x700/4];
|
||||
u32 pb_ctrl;
|
||||
u32 res2;
|
||||
u32 pb_status;
|
||||
u32 res3;
|
||||
/* 0x5710 */
|
||||
struct{
|
||||
u32 pb_reg1;
|
||||
u32 pb_reg2;
|
||||
u32 pb_reg3;
|
||||
} pb[8];
|
||||
u32 res4[0x100]; /* TODO */
|
||||
/* 0x5B00 */
|
||||
struct{
|
||||
u32 base_lo;
|
||||
u32 base_hi;
|
||||
u32 ctrl;
|
||||
u32 head;
|
||||
u32 tail;
|
||||
u32 status;
|
||||
u32 size;
|
||||
u32 threshold;
|
||||
} dma_desc[32];
|
||||
} layout;
|
||||
};
|
||||
u32 tx[0x2000/4];
|
||||
} layout;
|
||||
};
|
||||
};
|
||||
|
||||
struct atl_crash_dump_fwiface {
|
||||
u32 type;
|
||||
u32 length;
|
||||
/* struct fw_interface_in */
|
||||
u32 fw_interface_in[0x1000/4];
|
||||
/* struct fw_interface_out */
|
||||
u32 fw_interface_out[0x1000/4];
|
||||
};
|
||||
|
||||
/* Record table size of 128 with each entry holding (tag, mask, action) */
|
||||
#define ATL_ACT_RES_TABLE_SIZE 384
|
||||
struct atl_crash_dump_act_res {
|
||||
u32 type;
|
||||
u32 length;
|
||||
u32 act_res_data[ATL_ACT_RES_TABLE_SIZE];
|
||||
};
|
||||
|
||||
/* max_size = 'ring_size * (tx + rx) * 16 byte raw descriptor data' */
|
||||
#define ATL_MAX_RING_DESC_SIZE ATL_MAX_RING_SIZE * 32
|
||||
struct atl_crash_dump_ring {
|
||||
u32 type;
|
||||
u32 length;
|
||||
u32 index;
|
||||
u32 rx_head;
|
||||
u32 rx_tail;
|
||||
u32 tx_head;
|
||||
u32 tx_tail;
|
||||
u32 rx_ring_size;
|
||||
u32 tx_ring_size;
|
||||
u8 ring_data[ATL_MAX_RING_DESC_SIZE];
|
||||
};
|
||||
|
||||
/* This is an extensible structure to collect various debug data from
|
||||
* AQC device
|
||||
*/
|
||||
struct atl_crash_dump {
|
||||
u32 length; /* total crash structure length, in bytes */
|
||||
u32 sections_count; /* number of sections of type atl_crash_dump* following */
|
||||
u8 drv_version[16];
|
||||
u8 fw_version[16];
|
||||
union {
|
||||
struct {
|
||||
struct atl_crash_dump_regs regs;
|
||||
struct atl_crash_dump_fwiface fwiface;
|
||||
struct atl_crash_dump_act_res act_res;
|
||||
struct atl_crash_dump_ring ring[ATL_MAX_QUEUES];
|
||||
} antigua;
|
||||
struct {
|
||||
struct atl_crash_dump_regs regs;
|
||||
struct atl_crash_dump_ring ring[ATL_MAX_QUEUES];
|
||||
} atlantic;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
The tool atl_dump_parser is used to parse the register/device dump collected
|
||||
using "ethtool -d" command. Parser accepts dump in the binary format, hence the
|
||||
dump must be collected using 'raw' option i.e., 'ethtool -d <device> raw on'
|
||||
|
||||
Use gcc to build the binary from sources,
|
||||
gcc -o atl_dump_parser atl_dump_parser.c
|
||||
|
||||
Example:
|
||||
--------
|
||||
1. Collect ethtool dump from SUT machine
|
||||
#ethtool -d enp1s0 raw on > ethd_dump
|
||||
|
||||
2. Parse the dump
|
||||
#ls
|
||||
atl_dump_parser ethd_dump
|
||||
#./atl_dump_parser ethd_dump
|
||||
Parsing is completed successfully
|
||||
#ls ethd_dump_parsed
|
||||
action_resolver.txt atl_dump_parser ethd_dump fw_interface.txt registers.txt rings.txt
|
||||
#
|
||||
Parsed data will be copied to the text files under <input_file>_parsed folder.
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Atlantic Network Driver
|
||||
*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "atl_dump_parser.h"
|
||||
#include "../atl_dump.h"
|
||||
|
||||
#define DEV_FILE "device.txt"
|
||||
#define REG_FILE "registers.txt"
|
||||
#define FW_IFACE_FILE "fw_interface.txt"
|
||||
#define ACT_RES_FILE "action_resolver.txt"
|
||||
#define RING_FILE "rings.txt"
|
||||
|
||||
struct section_header {
|
||||
u32 type;
|
||||
u32 length;
|
||||
};
|
||||
|
||||
char out_folder[64];
|
||||
|
||||
int dump_device_info(struct atl_crash_dump *crash_dump)
|
||||
{
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, DEV_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "Driver version: %s\n", crash_dump->drv_version);
|
||||
fprintf(file, "FW version: %s\n", crash_dump->fw_version);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_registers(struct atl_crash_dump_regs *reg)
|
||||
{
|
||||
int block = 0x1000/4, i, offset;
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, REG_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Skip MIF block */
|
||||
|
||||
offset = block * 4;
|
||||
fprintf(file, "PCI Registers\n");
|
||||
fprintf(file, "=============\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.pci[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nInterrupt Registers\n");
|
||||
fprintf(file, "=====================\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.itr[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nCOM Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.com[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nMac Phy Registers\n");
|
||||
fprintf(file, "=====================\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.mac_phy[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nRx Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
/* Rx block size is 0x2000 */
|
||||
for (i = 0; i < block * 2; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.rx[i]);
|
||||
|
||||
offset += block * 2 * 4;
|
||||
fprintf(file, "\n\nTx Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
/* Tx block size is 0x2000 */
|
||||
for (i = 0; i < block * 2; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.tx[i]);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_fwiface(struct atl_crash_dump_fwiface *fwiface)
|
||||
{
|
||||
int block = 0x1000/4, i;
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, FW_IFACE_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "FW input interface\n");
|
||||
fprintf(file, "==================\n");
|
||||
for (i = 0; i < block; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i,
|
||||
fwiface->fw_interface_in[i], fwiface->fw_interface_in[i + 1],
|
||||
fwiface->fw_interface_in[i + 2], fwiface->fw_interface_in[i + 3]);
|
||||
|
||||
fprintf(file, "\n\nFW output interface\n");
|
||||
fprintf(file, "=======================\n");
|
||||
for (i = 0; i < block; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i,
|
||||
fwiface->fw_interface_out[i], fwiface->fw_interface_out[i + 1],
|
||||
fwiface->fw_interface_out[i + 2], fwiface->fw_interface_out[i + 3]);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_act_res(struct atl_crash_dump_act_res *act_res)
|
||||
{
|
||||
char file_name[64];
|
||||
int i, idx;
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, ACT_RES_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "RECORD RESOLVER TAG TAG Mask Action\n");
|
||||
fprintf(file, "==================================================\n");
|
||||
for (i = 0, idx = 0; i < ATL_ACT_RES_TABLE_SIZE / 3; i++) {
|
||||
fprintf(file, "%d\t0x%08x\t0x%08x\t0x%08x\n", i, act_res->act_res_data[idx++],
|
||||
act_res->act_res_data[idx++], act_res->act_res_data[idx++]);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_ring(struct atl_crash_dump_ring *ring)
|
||||
{
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
u32 *data;
|
||||
int i;
|
||||
|
||||
/* Assumption - file 'rings.txt' shouldn't exists */
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, RING_FILE);
|
||||
file = fopen(file_name, "a+");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "Ring Index %d\n", ring->index);
|
||||
fprintf(file, "==============\n");
|
||||
fprintf(file, "Rx head = 0x%08x tail = 0x%08x\n", ring->rx_head, ring->rx_tail);
|
||||
fprintf(file, "Tx head = 0x%08x tail = 0x%08x\n", ring->tx_head, ring->tx_tail);
|
||||
fprintf(file, "HW Ring rx_size = %d tx_size = %d\n", ring->rx_ring_size, ring->tx_ring_size);
|
||||
fprintf(file, "Rx Ring descriptor:\n");
|
||||
fprintf(file, "-------------------\n");
|
||||
data = (u32 *)ring->ring_data;
|
||||
for (i = 0; i < ring->rx_ring_size; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i, data[i], data[i + 1],
|
||||
data[i + 2], data[i + 3]);
|
||||
fprintf(file, "Tx Ring descriptor:\n");
|
||||
fprintf(file, "-------------------\n");
|
||||
data = (u32 *)ring->ring_data + ring->rx_ring_size;
|
||||
for (i = 0; i < ring->tx_ring_size; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i, data[i], data[i + 1],
|
||||
data[i + 2], data[i + 3]);
|
||||
fprintf(file, "\n");
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct atl_crash_dump *crash_dump;
|
||||
struct section_header *header;
|
||||
int i, offset, ret = 0;
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm_val;
|
||||
FILE *input_file;
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No intput file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stat(argv[1], &st) == -1) {
|
||||
printf("File stat error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = malloc(st.st_size);
|
||||
if (!buffer) {
|
||||
printf("Mem alloc error\n");
|
||||
return -1;
|
||||
}
|
||||
/* open the source file for reading */
|
||||
input_file = fopen(argv[1],"rb");
|
||||
if (input_file == NULL) {
|
||||
ret = -1;
|
||||
printf("Error opening file %s\n", argv[1]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fread(buffer, sizeof(char), st.st_size, input_file);
|
||||
fclose(input_file);
|
||||
|
||||
tm_val = localtime(&t);
|
||||
tm_val = NULL;
|
||||
if (tm_val)
|
||||
snprintf(out_folder, 64, "%s_%02d-%02d-%02d_%02d-%02d-%02d", argv[1],
|
||||
tm_val->tm_mon + 1, (int) tm_val->tm_mday, 1900 + tm_val->tm_year,
|
||||
tm_val->tm_hour, tm_val->tm_min, tm_val->tm_sec);
|
||||
else
|
||||
snprintf(out_folder, 64, "%s_parsed", argv[1]);
|
||||
if (stat(out_folder, &st) == -1) {
|
||||
if (mkdir(out_folder, 0644) == -1) {
|
||||
ret = -1;
|
||||
printf("Failed to creat folder` %s\n", out_folder);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
crash_dump = (struct atl_crash_dump *)buffer;
|
||||
ret = dump_device_info(crash_dump);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
offset = offsetof(struct atl_crash_dump, antigua);
|
||||
for (i = 0; i < crash_dump->sections_count; i++) {
|
||||
header = (struct section_header *)(buffer + offset);
|
||||
switch (header->type) {
|
||||
case atl_crash_dump_type_regs:
|
||||
ret = dump_registers((struct atl_crash_dump_regs *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_fwiface:
|
||||
ret = dump_fwiface((struct atl_crash_dump_fwiface *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_act_res:
|
||||
ret = dump_act_res((struct atl_crash_dump_act_res *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_ring:
|
||||
ret = dump_ring((struct atl_crash_dump_ring *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
printf("Parsing Error - invalid section\n");
|
||||
goto err;
|
||||
}
|
||||
offset += header->length;
|
||||
}
|
||||
|
||||
err:
|
||||
free(buffer);
|
||||
if (ret)
|
||||
printf("Failed to parse the dump\n");
|
||||
else
|
||||
printf("Parsing is completed successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Atlantic Network Driver
|
||||
*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __ATL_DUMP_PARSER
|
||||
#define __ATL_DUMP_PARSER
|
||||
|
||||
#define ATL_MAX_RING_SIZE (8192 - 8)
|
||||
#define ATL_MAX_QUEUES 8
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#endif
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "atl_fwdnl.h"
|
||||
#include "atl_macsec.h"
|
||||
#include "atl_ptp.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
static uint32_t atl_ethtool_get_link(struct net_device *ndev)
|
||||
{
|
||||
|
|
@ -633,8 +634,8 @@ static const struct atl_stat_desc eth_stat_descs[] = {
|
|||
ATL_ETH_STAT(tx_pause, tx_pause),
|
||||
ATL_ETH_STAT(tx_ether_pkts, tx_ether_pkts),
|
||||
ATL_ETH_STAT(tx_ether_octets, tx_ether_octets),
|
||||
ATL_ETH_STAT(tx_errors, tx_errors),
|
||||
ATL_ETH_STAT(rx_pause, rx_pause),
|
||||
ATL_ETH_STAT(rx_ether_drops, rx_ether_drops),
|
||||
ATL_ETH_STAT(rx_ether_octets, rx_ether_octets),
|
||||
ATL_ETH_STAT(rx_ether_pkts, rx_ether_pkts),
|
||||
ATL_ETH_STAT(rx_ether_broacasts, rx_ether_broacasts),
|
||||
|
|
@ -642,6 +643,13 @@ static const struct atl_stat_desc eth_stat_descs[] = {
|
|||
ATL_ETH_STAT(rx_ether_crc_align_errs, rx_ether_crc_align_errs),
|
||||
ATL_ETH_STAT(rx_filter_host, rx_filter_host),
|
||||
ATL_ETH_STAT(rx_filter_lost, rx_filter_lost),
|
||||
ATL_ETH_STAT(rx_errors, rx_errors),
|
||||
ATL_ETH_STAT(rx_drops, rx_drops),
|
||||
ATL_ETH_STAT(rx_dma_packets, rx_dma_packets),
|
||||
ATL_ETH_STAT(rx_dma_octets, rx_dma_octets),
|
||||
ATL_ETH_STAT(rx_dma_drops, rx_dma_drops),
|
||||
ATL_ETH_STAT(tx_dma_packets, tx_dma_packets),
|
||||
ATL_ETH_STAT(tx_dma_octets, tx_dma_octets),
|
||||
};
|
||||
|
||||
#define ATL_PRIV_FLAG(_name, _bit) \
|
||||
|
|
@ -1173,8 +1181,15 @@ static int atl_set_priv_flags(struct net_device *ndev, uint32_t flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
|
||||
static int atl_get_coalesce(struct net_device *ndev,
|
||||
struct ethtool_coalesce *ec,
|
||||
struct kernel_ethtool_coalesce *kec,
|
||||
struct netlink_ext_ack *extack)
|
||||
#else
|
||||
static int atl_get_coalesce(struct net_device *ndev,
|
||||
struct ethtool_coalesce *ec)
|
||||
#endif
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
|
|
@ -1185,8 +1200,15 @@ static int atl_get_coalesce(struct net_device *ndev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
static int atl_set_coalesce(struct net_device *ndev,
|
||||
struct ethtool_coalesce *ec,
|
||||
struct kernel_ethtool_coalesce *kec,
|
||||
struct netlink_ext_ack *extack)
|
||||
#else
|
||||
static int atl_set_coalesce(struct net_device *ndev,
|
||||
struct ethtool_coalesce *ec)
|
||||
#endif
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
|
|
@ -2711,9 +2733,7 @@ static void atl_refresh_rxf_desc(struct atl_nic *nic,
|
|||
atl_for_each_rxf_idx(desc, idx)
|
||||
desc->update_rxf(nic, idx);
|
||||
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
}
|
||||
|
||||
void atl_refresh_rxfs(struct atl_nic *nic)
|
||||
|
|
@ -2723,9 +2743,7 @@ void atl_refresh_rxfs(struct atl_nic *nic)
|
|||
atl_for_each_rxf_desc(desc)
|
||||
atl_refresh_rxf_desc(nic, desc);
|
||||
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
}
|
||||
|
||||
static bool atl_vlan_pull_from_promisc(struct atl_nic *nic, uint32_t idx)
|
||||
|
|
@ -2765,9 +2783,8 @@ static bool atl_vlan_pull_from_promisc(struct atl_nic *nic, uint32_t idx)
|
|||
} while (idx & ATL_VIDX_FREE);
|
||||
|
||||
kfree(map);
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2955,9 +2972,7 @@ int atl_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
|||
vlan->promisc_count++;
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
(ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2984,9 +2999,8 @@ update_vlan:
|
|||
atl_rxf_update_vlan(nic, idx);
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
(nic->ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3027,9 +3041,9 @@ int atl_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
|||
|
||||
update_vlan_promisc:
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw, (ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3086,6 +3100,18 @@ static void atl_ethtool_complete(struct net_device *ndev)
|
|||
pm_runtime_put(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static int atl_ethool_get_regs_len(struct net_device *ndev)
|
||||
{
|
||||
return atl_get_crash_dump(ndev, NULL);
|
||||
}
|
||||
|
||||
static void atl_ethool_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *buf)
|
||||
{
|
||||
regs->version = 0;
|
||||
memset(buf, 0, regs->len);
|
||||
atl_get_crash_dump(ndev, buf);
|
||||
}
|
||||
|
||||
const struct ethtool_ops atl_ethtool_ops = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
|
||||
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
|
||||
|
|
@ -3128,4 +3154,6 @@ const struct ethtool_ops atl_ethtool_ops = {
|
|||
.set_wol = atl_set_wol,
|
||||
.begin = atl_ethtool_begin,
|
||||
.complete = atl_ethtool_complete,
|
||||
.get_regs_len = atl_ethool_get_regs_len,
|
||||
.get_regs = atl_ethool_get_regs,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1172,6 +1172,39 @@ int atl_update_thermal_flag(struct atl_hw *hw, int bit, bool val)
|
|||
static unsigned int atl_wdog_period = 1100;
|
||||
module_param_named(wdog_period, atl_wdog_period, uint, 0644);
|
||||
|
||||
static int atl_fw_rev_check_and_warn(int fw_rev)
|
||||
{
|
||||
int major = (fw_rev >> 24) & 0xFFU;
|
||||
bool ret = true;
|
||||
|
||||
switch (major) {
|
||||
case 2:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 12) &&
|
||||
((fw_rev & 0xFFFFU) < 12))
|
||||
ret = false;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 1) &&
|
||||
((fw_rev & 0xFFFFU) < 102))
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 2) &&
|
||||
((fw_rev & 0xFFFFU) < 37))
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atl_fw_init(struct atl_hw *hw)
|
||||
{
|
||||
uint32_t tries, reg, major;
|
||||
|
|
@ -1186,6 +1219,13 @@ int atl_fw_init(struct atl_hw *hw)
|
|||
atl_dev_dbg("FW startup took %d ms\n", tries);
|
||||
|
||||
major = (reg >> 24) & 0xff;
|
||||
|
||||
/* Warn if FW is lower than 2.12.12, 3.1.102 and 4.2.37 */
|
||||
if (!atl_fw_rev_check_and_warn(reg))
|
||||
atl_dev_warn("FW_version: %u.%u.%u, is not stable version",
|
||||
(reg >> 24), ((reg >> 16) & 0xFFU),
|
||||
(reg & 0xFFFFU));
|
||||
|
||||
if (!major || major > 3) {
|
||||
atl_dev_err("Unsupported FW major version: %u\n", major);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,46 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include "atl_common.h"
|
||||
#include "atl_desc.h"
|
||||
#include "atl_fwd.h"
|
||||
#include "atl_ring.h"
|
||||
|
||||
static u32 atl_skip_reglist[] = {
|
||||
/* PCIE */
|
||||
0x1030, 0x1200, 0x1514, 0x1F00, 0x1F04, 0x1F20, 0x1F24,
|
||||
|
||||
/* INTR Registers */
|
||||
0x21A0, 0x21A4, 0x21A8,
|
||||
|
||||
/* COM Registers */
|
||||
0x30A0, 0x30A8, 0x3900, 0x3920,
|
||||
|
||||
/* MAC PHY Registers */
|
||||
0x4058, 0x4060, 0x4064, 0x40B0, 0x40B4, 0x40B8, 0x40BC,
|
||||
0x4120, 0x4140, 0x4144, 0x4190, 0x419C, 0x41A0, 0x41A4,
|
||||
0x41A8, 0x4270, 0x4288, 0x428C, 0x4290, 0x4294, 0x42E8,
|
||||
0x42EC, 0x434C, 0x4378, 0x4380, 0x4384, 0x4440, 0x4444,
|
||||
0x4970, 0x4B40, 0x4B44, 0x4B48, 0x4B4C,
|
||||
|
||||
/* RX Registers */
|
||||
0x5108, 0x54CC, 0x55B0, 0x55B4, 0x55C0, 0x55E0, 0x55E4,
|
||||
0x5640, 0x5718, 0x5728, 0x5738, 0x5748, 0x5758, 0x5768,
|
||||
0x5778, 0x5788, 0x5808, 0x580C, 0x5A10, 0x5B14, 0x5B34,
|
||||
0x5B54, 0x5B74, 0x5B94, 0x5BB4, 0x5BD4, 0x5BF4, 0x5C14,
|
||||
0x5C34, 0x5C54, 0x5C74, 0x5C94, 0x5CB4, 0x5CD4, 0x5CF4,
|
||||
0x5D14, 0x5D34, 0x5D54, 0x5D74, 0x5D94, 0x5DB4, 0x5DD4,
|
||||
0x5DF4, 0x5E14, 0x5E34, 0x5E54, 0x5E74, 0x5E94, 0x5EB4,
|
||||
0x5ED4, 0x5EF4, 0x6900, 0x6F00, 0x6F20,
|
||||
|
||||
/* TX Registers */
|
||||
0x7808, 0x7848, 0x784C, 0x78B0, 0x78B4, 0x7918, 0x7928,
|
||||
0x7938, 0x7948, 0x7958, 0x7968, 0x7978, 0x7988, 0x7A34,
|
||||
0x7B10, 0x7B14, 0x7B18, 0x7C14, 0x7C54, 0x7C94, 0x7CD4,
|
||||
0x7D14, 0x7D54, 0x7D94, 0x7DD4, 0x7E14, 0x7E54, 0x7E94,
|
||||
0x7ED4, 0x7F14, 0x7F54, 0x7F94, 0x7FD4, 0x8014, 0x8054,
|
||||
0x8094, 0x80D4, 0x8114, 0x8154, 0x8194, 0x81D4, 0x8214,
|
||||
0x8254, 0x8294, 0x82D4, 0x8314, 0x8354, 0x8394, 0x83D4,
|
||||
0x8900, 0x8904, 0x8F00, 0x8F20,
|
||||
};
|
||||
|
||||
static const char *atl_fwd_dir_str(struct atl_fwd_ring *ring)
|
||||
{
|
||||
|
|
@ -903,3 +943,178 @@ int atl_fwd_resume_rings(struct atl_nic *nic)
|
|||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atl_get_ext_stats(struct net_device *ndev, struct atl_ext_stats *stats)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
if (!stats)
|
||||
return -EINVAL;
|
||||
|
||||
atl_update_eth_stats(nic);
|
||||
atl_update_global_stats(nic);
|
||||
|
||||
memcpy(&stats->rx, &nic->stats.rx, sizeof(stats->rx));
|
||||
memcpy(&stats->tx, &nic->stats.tx, sizeof(stats->tx));
|
||||
memcpy(&stats->rx_fwd, &nic->stats.rx_fwd, sizeof(stats->rx_fwd));
|
||||
memcpy(&stats->eth, &nic->stats.eth, sizeof(stats->eth));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atl_get_ext_stats);
|
||||
|
||||
static bool atl_skip_register(u32 reg)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = sizeof(atl_skip_reglist) / sizeof(u32);
|
||||
for (i = 0; i < count; i++)
|
||||
if (atl_skip_reglist[i] == reg)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_regs(struct atl_hw *hw, struct atl_crash_dump_regs *section)
|
||||
{
|
||||
int addr, index;
|
||||
|
||||
section->type = atl_crash_dump_type_regs;
|
||||
section->length = sizeof(struct atl_crash_dump_regs);
|
||||
|
||||
/* prefill with 'skip' value */
|
||||
for (addr = 0; addr < sizeof(section->regs_data); addr++)
|
||||
section->regs_data[addr] = 0xFFFFFFFF;
|
||||
|
||||
for (addr = 0x1000, index = 0x1000 / 4; addr < 0x9000; addr += 4, index++) {
|
||||
if (atl_skip_register(addr))
|
||||
continue;
|
||||
section->regs_data[index] = atl_read(hw, addr);
|
||||
}
|
||||
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_fwiface(struct atl_hw *hw, struct atl_crash_dump_fwiface *section)
|
||||
{
|
||||
int i;
|
||||
|
||||
section->type = atl_crash_dump_type_fwiface;
|
||||
section->length = sizeof(struct atl_crash_dump_fwiface);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(section->fw_interface_in); i++)
|
||||
section->fw_interface_in[i] = atl_read(hw, ATL2_MIF_SHARED_BUFFER_IN(i));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(section->fw_interface_out); i++)
|
||||
section->fw_interface_out[i] = atl_read(hw, ATL2_MIF_SHARED_BUFFER_OUT(i));
|
||||
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_act_res(struct atl_hw *hw, struct atl_crash_dump_act_res *section)
|
||||
{
|
||||
int i, idx, err;
|
||||
|
||||
section->type = atl_crash_dump_type_act_res;
|
||||
section->length = sizeof(struct atl_crash_dump_act_res);
|
||||
|
||||
err = atl_hwsem_get(hw, ATL2_MCP_SEM_ACT_RSLVR);
|
||||
if (err) {
|
||||
printk("Failed to aquire act_res semaphore\n");
|
||||
goto ret;
|
||||
}
|
||||
|
||||
for (i = 0, idx = 0; i < ATL_ACT_RES_TABLE_SIZE / 3; i++) {
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_REQ_TAG(i));
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_TAG_MASK(i));
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_ACTN(i));
|
||||
}
|
||||
|
||||
atl_hwsem_put(hw, ATL2_MCP_SEM_ACT_RSLVR);
|
||||
|
||||
ret:
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_ring(struct atl_nic *nic, int idx,
|
||||
struct atl_crash_dump_ring *section)
|
||||
{
|
||||
int size = sizeof(struct atl_crash_dump_ring), offset;
|
||||
struct atl_queue_vec *qvec = &nic->qvecs[idx];
|
||||
struct atl_hw_ring *hwring;
|
||||
|
||||
if (!test_bit(ATL_ST_UP, &nic->hw.state)) {
|
||||
memset(section, 0, size);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
section->type = atl_crash_dump_type_ring;
|
||||
section->index = qvec->idx;
|
||||
section->length = size;
|
||||
section->rx_head = qvec->rx.head;
|
||||
section->rx_tail = qvec->rx.tail;
|
||||
section->tx_head = qvec->tx.head;
|
||||
section->tx_tail = qvec->tx.tail;
|
||||
hwring = &qvec->rx.hw;
|
||||
section->rx_ring_size = hwring->size;
|
||||
memcpy(section->ring_data, hwring->descs, hwring->size * sizeof(*hwring->descs));
|
||||
offset = hwring->size * sizeof(*hwring->descs);
|
||||
hwring = &qvec->tx.hw;
|
||||
section->tx_ring_size = hwring->size;
|
||||
memcpy(section->ring_data + offset, hwring->descs, hwring->size * sizeof(*hwring->descs));
|
||||
|
||||
ret:
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
int atl_get_crash_dump(struct net_device *ndev, struct atl_crash_dump *crash_dump)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
u32 fw_rev = nic->hw.mcp.fw_rev;
|
||||
int recorded_sz = 0, i, nvecs;
|
||||
u8 *section;
|
||||
|
||||
if (!crash_dump)
|
||||
return sizeof(struct atl_crash_dump);
|
||||
|
||||
crash_dump->length = sizeof(*crash_dump);
|
||||
crash_dump->sections_count = 0;
|
||||
|
||||
strlcpy(crash_dump->drv_version, ATL_VERSION, sizeof(crash_dump->drv_version));
|
||||
snprintf(crash_dump->fw_version, sizeof(crash_dump->fw_version),
|
||||
"%d.%d.%d", fw_rev >> 24, fw_rev >> 16 & 0xff, fw_rev & 0xffff);
|
||||
|
||||
if (nic->hw.chip_id == ATL_ANTIGUA)
|
||||
section = (void *)&crash_dump->antigua.regs;
|
||||
else
|
||||
section = (void *)&crash_dump->atlantic.regs;
|
||||
|
||||
recorded_sz = atl_get_crash_dump_regs(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
|
||||
if (nic->hw.chip_id == ATL_ANTIGUA) {
|
||||
recorded_sz = atl_get_crash_dump_fwiface(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
|
||||
recorded_sz = atl_get_crash_dump_act_res(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
}
|
||||
|
||||
nvecs = min_t(int, nic->nvecs, ATL_MAX_QUEUES);
|
||||
for (i = 0; i < nvecs; i++) {
|
||||
recorded_sz = atl_get_crash_dump_ring(nic, i, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
}
|
||||
|
||||
return crash_dump->length;
|
||||
}
|
||||
EXPORT_SYMBOL(atl_get_crash_dump);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
#define _ATL_FWD_H_
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_dump.h"
|
||||
|
||||
/* Each incompatible API change bumps the API version */
|
||||
#define ATL_FWD_API_VERSION 3
|
||||
#define ATL_FWD_API_VERSION 4
|
||||
|
||||
struct atl_fwd_event;
|
||||
|
||||
|
|
@ -405,4 +406,40 @@ enum atl_fwd_ring_state {
|
|||
ATL_FWR_ST_EVT_ENABLED = BIT(1),
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
enum atl_fwd_notify;
|
||||
void atl_fwd_release_rings(struct atl_nic *nic);
|
||||
int atl_fwd_suspend_rings(struct atl_nic *nic);
|
||||
int atl_fwd_resume_rings(struct atl_nic *nic);
|
||||
void atl_fwd_notify(struct atl_nic *nic, enum atl_fwd_notify notif, void *data);
|
||||
#else
|
||||
static inline void atl_fwd_release_rings(struct atl_nic *nic) {}
|
||||
static inline int atl_fwd_suspend_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline int atl_fwd_resume_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline void atl_fwd_notify(struct atl_nic *nic,
|
||||
enum atl_fwd_notify notif, void *data) {}
|
||||
#endif
|
||||
|
||||
struct atl_ext_stats {
|
||||
struct atl_rx_ring_stats rx;
|
||||
struct atl_tx_ring_stats tx;
|
||||
struct atl_rx_fwd_ring_stats rx_fwd;
|
||||
|
||||
struct atl_ether_stats eth;
|
||||
};
|
||||
|
||||
/**
|
||||
* Direct statistics fetch call for the device
|
||||
*/
|
||||
int atl_get_ext_stats(struct net_device *ndev, struct atl_ext_stats *stats);
|
||||
|
||||
/**
|
||||
* Get the register and other crash related information from the device
|
||||
* If @crash_dump is NULL, function will return the requested length of the buffer to
|
||||
* store dump, in bytes
|
||||
* if @crash_dump is not null, function will fill the buffer with crashdump
|
||||
* sections filled, up to crash_dump->length
|
||||
*/
|
||||
int atl_get_crash_dump(struct net_device *ndev, struct atl_crash_dump *crash_dump);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "atl_fwdnl.h"
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
#include "atl_fwdnl_params.h"
|
||||
#include "atl_ring.h"
|
||||
#include "atl_trace.h"
|
||||
|
|
@ -1742,7 +1743,9 @@ static const struct nla_policy atlfwd_nl_policy[NUM_ATL_FWD_ATTR] = {
|
|||
[ATL_FWD_ATTR_QUEUE_INDEX] = { .type = NLA_S32 },
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) && \
|
||||
RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 0)
|
||||
#define ATLFWD_NL_OP_POLICY(op_policy) .policy = op_policy
|
||||
#else
|
||||
#define ATLFWD_NL_OP_POLICY(op_policy)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
unsigned int atlfwd_nl_tx_clean_threshold_msec = 200;
|
||||
unsigned int atlfwd_nl_tx_clean_threshold_frac = 8;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,16 @@ static void atl_set_promisc(struct atl_hw *hw, bool enabled, bool allmulti)
|
|||
}
|
||||
}
|
||||
|
||||
int atl_vlan_promisc_status(struct net_device *ndev)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
return ndev->flags & IFF_PROMISC ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active ||
|
||||
!(ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER);
|
||||
}
|
||||
|
||||
void atl_set_vlan_promisc(struct atl_hw *hw, int promisc)
|
||||
{
|
||||
atl_write_bit(hw, ATL_RX_VLAN_FLT_CTRL1, 1, !!promisc);
|
||||
|
|
@ -746,7 +756,7 @@ void atl_start_hw_global(struct atl_nic *nic)
|
|||
(tpb_size * 32 * 66 / 100) << 16 |
|
||||
(tpb_size * 32 * 50 / 100));
|
||||
/* 4-TC | Enable TPB */
|
||||
atl_set_bits(hw, ATL_TX_PBUF_CTRL1, BIT(8) | BIT(0));
|
||||
atl_set_bits(hw, ATL_TX_PBUF_CTRL1, BIT(8) | BIT(2) | BIT(0));
|
||||
/* TX Buffer clk gate off */
|
||||
if (hw->chip_id == ATL_ANTIGUA)
|
||||
atl_clear_bits(hw, ATL_TX_PBUF_CTRL1, BIT(5));
|
||||
|
|
@ -910,9 +920,7 @@ void atl_set_rx_mode(struct net_device *ndev)
|
|||
/* Enable promisc VLAN mode if IFF_PROMISC explicitly
|
||||
* requested or too many VIDs registered
|
||||
*/
|
||||
atl_set_vlan_promisc(hw,
|
||||
ndev->flags & IFF_PROMISC || nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(hw, atl_vlan_promisc_status(ndev));
|
||||
|
||||
atl_set_promisc(hw, promisc_needed,
|
||||
is_multicast_enabled && all_multi_needed);
|
||||
|
|
@ -1319,6 +1327,14 @@ static int __atl_fetch_msm2_stats(struct atl_hw *hw,
|
|||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->tx_errors = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->tx_errors += ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, ®2, hwsem_put);
|
||||
stats->rx_pause = ((uint64_t)reg2 << 32) | reg;
|
||||
|
|
@ -1346,6 +1362,13 @@ static int __atl_fetch_msm2_stats(struct atl_hw *hw,
|
|||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_crc_align_errs += ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->rx_errors = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_HI, ®2, hwsem_put);
|
||||
stats->rx_drops = ((uint64_t)reg2 << 32) | reg;
|
||||
hwsem_put:
|
||||
atl_hwsem_put(hw, ATL_MCP_SEM_MSM);
|
||||
return ret;
|
||||
|
|
@ -1373,7 +1396,19 @@ int atl_update_eth_stats(struct atl_nic *nic)
|
|||
if (ret)
|
||||
goto unlock_fw;
|
||||
|
||||
stats.rx_ether_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7);
|
||||
stats.rx_dma_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7);
|
||||
|
||||
stats.rx_dma_packets = atl_read(hw, ATL_RX_DMA_STATS_CNT1);
|
||||
stats.rx_dma_packets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT2) << 32;
|
||||
|
||||
stats.rx_dma_octets = atl_read(hw, ATL_RX_DMA_STATS_CNT3);
|
||||
stats.rx_dma_octets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT4) << 32;
|
||||
|
||||
stats.tx_dma_packets = atl_read(hw, ATL_TX_DMA_STATS_CNT1);
|
||||
stats.tx_dma_packets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT2) << 32;
|
||||
|
||||
stats.tx_dma_octets = atl_read(hw, ATL_TX_DMA_STATS_CNT3);
|
||||
stats.tx_dma_octets += (uint64_t)atl_read(hw, ATL_TX_DMA_STATS_CNT4) << 32;
|
||||
|
||||
/* capture debug counters*/
|
||||
atl_write_bit(hw, ATL_RX_RPF_DBG_CNT_CTRL, 0x1f, 1);
|
||||
|
|
@ -1685,4 +1720,3 @@ static void atl2_hw_new_rx_filter_promisc(struct atl_hw *hw, bool promisc,
|
|||
off_action);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,8 @@ void hw_atl_extract_hwts(struct atl_hw *hw, struct atl_rx_desc_hwts_wb *hwts_wb,
|
|||
sec += tmp;
|
||||
tmp = (u64)((hwts_wb->sec_hw >> 22) & 0x3ff) << 38;
|
||||
sec += tmp;
|
||||
if (sec == 0xffffffffffff && hwts_wb->ns == 0xffffffff)
|
||||
return;
|
||||
ns = sec * NSEC_PER_SEC + hwts_wb->ns;
|
||||
if (timestamp)
|
||||
*timestamp = ns + hw->ptp_clk_offset;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "atl_macsec.h"
|
||||
#if IS_ENABLED(CONFIG_MACSEC) && defined(NETIF_F_HW_MACSEC)
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "macsec/macsec_api.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include "atl_macsec.h"
|
||||
#include "atl_ptp.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
const char atl_driver_name[] = "atlantic-fwd";
|
||||
|
||||
|
|
@ -384,7 +385,7 @@ int atl_do_reset(struct atl_nic *nic)
|
|||
|
||||
hw->mcp.ops->dump_cfg(hw);
|
||||
|
||||
atl_stop(nic, true);
|
||||
atl_stop(nic, false);
|
||||
|
||||
atl_fwd_suspend_rings(nic);
|
||||
|
||||
|
|
@ -765,9 +766,7 @@ static void atl_remove(struct pci_dev *pdev)
|
|||
atl_ptp_unregister(nic);
|
||||
unregister_netdev(nic->ndev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
atl_fwd_release_rings(nic);
|
||||
#endif
|
||||
|
||||
atl_clear_datapath(nic);
|
||||
|
||||
|
|
@ -948,6 +947,47 @@ static int atl_pm_runtime_idle(struct device *dev)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 0))
|
||||
static void atl_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct atl_nic *nic = pci_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&nic->hw.pdev->dev);
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(nic->ndev))
|
||||
atl_stop(nic, false);
|
||||
|
||||
rtnl_unlock();
|
||||
pm_runtime_put_sync(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static void atl_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct atl_nic *nic = pci_get_drvdata(pdev);
|
||||
|
||||
if (!nic) {
|
||||
dev_err(&pdev->dev, "%s failed, device is unrecoverable\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&nic->hw.pdev->dev);
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(nic->ndev))
|
||||
atl_start(nic);
|
||||
|
||||
rtnl_unlock();
|
||||
pm_runtime_put_sync(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers atl_err_handlers = {
|
||||
.reset_prepare = atl_reset_prepare,
|
||||
.reset_done = atl_reset_done,
|
||||
};
|
||||
#endif
|
||||
|
||||
const struct dev_pm_ops atl_pm_ops = {
|
||||
.suspend = atl_suspend_poweroff,
|
||||
.poweroff = atl_suspend_poweroff,
|
||||
|
|
@ -968,6 +1008,11 @@ static struct pci_driver atl_pci_ops = {
|
|||
#ifdef CONFIG_PM
|
||||
.driver.pm = &atl_pm_ops,
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 0))
|
||||
.err_handler = &atl_err_handlers,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct atl_thermal atl_def_thermal;
|
||||
|
|
|
|||
|
|
@ -893,8 +893,13 @@ void atl_ptp_tx_hwtstamp(struct atl_nic *nic, u64 timestamp)
|
|||
return;
|
||||
}
|
||||
|
||||
timestamp += atomic_read(&ptp->offset_egress);
|
||||
atl_ptp_convert_to_hwtstamp(&hwtstamp, timestamp);
|
||||
if (!timestamp) {
|
||||
atl_nic_err("ptp timestamp all-F from FW\n");
|
||||
memset(&hwtstamp, 0, sizeof(hwtstamp));
|
||||
} else {
|
||||
timestamp += atomic_read(&ptp->offset_egress);
|
||||
atl_ptp_convert_to_hwtstamp(&hwtstamp, timestamp);
|
||||
}
|
||||
do {
|
||||
skb_tstamp_tx(skb, &hwtstamp);
|
||||
dev_kfree_skb_any(skb);
|
||||
|
|
|
|||
|
|
@ -176,8 +176,17 @@ enum mcp_scratchpad {
|
|||
#define ATL_RX_RING_BUF_SIZE(ring) ATL_RING_OFFT(ring, 0x18)
|
||||
#define ATL_RX_RING_THRESH(ring) ATL_RING_OFFT(ring, 0x1c)
|
||||
|
||||
#define ATL_RX_DMA_STATS_CNT1 0x6800
|
||||
#define ATL_RX_DMA_STATS_CNT2 0x6804
|
||||
#define ATL_RX_DMA_STATS_CNT3 0x6808
|
||||
#define ATL_RX_DMA_STATS_CNT4 0x680C
|
||||
#define ATL_RX_DMA_STATS_CNT7 0x6818
|
||||
|
||||
#define ATL_TX_DMA_STATS_CNT1 0x8800
|
||||
#define ATL_TX_DMA_STATS_CNT2 0x8804
|
||||
#define ATL_TX_DMA_STATS_CNT3 0x8808
|
||||
#define ATL_TX_DMA_STATS_CNT4 0x880C
|
||||
|
||||
/* TX @ 0x7000 */
|
||||
#define ATL_TX_CTRL1 0x7000
|
||||
#define ATL_TX_PO_CTRL1 0x7800
|
||||
|
|
@ -224,6 +233,10 @@ enum mcp_scratchpad {
|
|||
#define ATL_MSM_CTR_RX_ERRS 0x120
|
||||
|
||||
|
||||
#define ATL_MSM2_CTR_RX_DROP_CNTR_LO 0x158
|
||||
#define ATL_MSM2_CTR_RX_DROP_CNTR_HI 0x15C
|
||||
#define ATL_MSM2_CTR_RX_ERRS_CNTR_LO 0x138
|
||||
#define ATL_MSM2_CTR_RX_ERRS_CNTR_HI 0x13C
|
||||
#define ATL_MSM2_CTR_RX_OCTETS_LO 0x100
|
||||
#define ATL_MSM2_CTR_RX_OCTETS_HI 0x104
|
||||
#define ATL_MSM2_CTR_RX_ALIGN_ERRS_LO 0x110
|
||||
|
|
@ -245,5 +258,9 @@ enum mcp_scratchpad {
|
|||
#define ATL_MSM2_CTR_TX_PKTS_LO 0x220
|
||||
#define ATL_MSM2_CTR_TX_PKTS_HI 0x224
|
||||
|
||||
#define ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_LO 0x228
|
||||
#define ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_HI 0x22C
|
||||
#define ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_LO 0x238
|
||||
#define ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_HI 0x23C
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -244,6 +244,14 @@ static uint32_t atl_insert_context(struct atl_txbuf *txbuf,
|
|||
return tx_cmd;
|
||||
}
|
||||
|
||||
static bool atl_ptp_udp(struct sk_buff *skb)
|
||||
{
|
||||
return (ip_hdr(skb)->version == 4) &&
|
||||
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
|
||||
((udp_hdr(skb)->dest == htons(319)) ||
|
||||
(udp_hdr(skb)->dest == htons(320)));
|
||||
}
|
||||
|
||||
netdev_tx_t atl_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
|
@ -257,12 +265,9 @@ netdev_tx_t atl_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
* and hardware PTP design of the chip. Otherwise ptp stream
|
||||
* will fail to sync
|
||||
*/
|
||||
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||
unlikely((ip_hdr(skb)->version == 4) &&
|
||||
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
|
||||
((udp_hdr(skb)->dest == htons(319)) ||
|
||||
(udp_hdr(skb)->dest == htons(320)))) ||
|
||||
unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
|
||||
if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||
atl_ptp_udp(skb) ||
|
||||
(eth_hdr(skb)->h_proto == htons(ETH_P_1588))))
|
||||
return atl_ptp_start_xmit(nic, skb);
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +453,7 @@ static bool atl_checksum_workaround(struct sk_buff *skb,
|
|||
|
||||
if (((desc->pkt_type & atl_rx_pkt_type_vlan_msk) ==
|
||||
atl_rx_pkt_type_vlan) &&
|
||||
!(desc->rx_estat & atl_rx_estat_vlan_stripped))
|
||||
!(desc->rx_estat & atl_rx_estat_vlan_stripped))
|
||||
ip_header_offset += sizeof(struct vlan_hdr);
|
||||
|
||||
if ((desc->pkt_type & atl_rx_pkt_type_vlan_msk) ==
|
||||
|
|
@ -773,6 +778,9 @@ static int atl_fill_hwts_rx(struct atl_desc_ring *ring, uint32_t count, bool ato
|
|||
count--;
|
||||
}
|
||||
|
||||
wmb();
|
||||
atl_write(ring_hw(ring), ATL_RX_RING_TAIL(ring), ring->tail);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1208,7 +1216,7 @@ int atl_clean_hwts_rx(struct atl_desc_ring *ring, int budget)
|
|||
uint32_t space = ring_space(ring);
|
||||
struct atl_rx_desc_hwts_wb *wb;
|
||||
struct atl_rxbuf *rxbuf;
|
||||
u64 ns;
|
||||
u64 ns = 0;
|
||||
DECLARE_SCRATCH_DESC(scratch);
|
||||
|
||||
if (space >= refill_batch)
|
||||
|
|
@ -1389,7 +1397,11 @@ static void atl_calc_affinities(struct atl_nic *nic)
|
|||
int i;
|
||||
unsigned int cpu;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||
cpus_read_lock();
|
||||
#else
|
||||
get_online_cpus();
|
||||
#endif
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
|
||||
for (i = 0; i < nic->nvecs; i++) {
|
||||
|
|
@ -1406,7 +1418,11 @@ static void atl_calc_affinities(struct atl_nic *nic)
|
|||
cpumask_set_cpu(cpu, cpumask);
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||
cpus_read_unlock();
|
||||
#else
|
||||
put_online_cpus();
|
||||
#endif
|
||||
}
|
||||
|
||||
void atl_init_qvec(struct atl_nic *nic, struct atl_queue_vec *qvec, int idx)
|
||||
|
|
@ -2104,9 +2120,15 @@ void atl_stop_rings(struct atl_nic *nic)
|
|||
int atl_set_features(struct net_device *ndev, netdev_features_t features)
|
||||
{
|
||||
netdev_features_t changed = ndev->features ^ features;
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
ndev->features = features;
|
||||
|
||||
if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
atl_vlan_promisc_status(ndev));
|
||||
}
|
||||
|
||||
if (changed & NETIF_F_LRO)
|
||||
atl_set_lro(netdev_priv(ndev));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct atl_rx_fwd_ring_stats {
|
|||
struct atl_tx_ring_stats {
|
||||
uint64_t packets;
|
||||
uint64_t bytes;
|
||||
uint64_t tx_busy;
|
||||
uint64_t tx_busy; /* number of times ring was full and tx failed */
|
||||
uint64_t tx_restart;
|
||||
uint64_t dma_map_failed;
|
||||
};
|
||||
|
|
@ -55,8 +55,8 @@ struct atl_ether_stats {
|
|||
uint64_t tx_pause;
|
||||
uint64_t tx_ether_pkts;
|
||||
uint64_t tx_ether_octets;
|
||||
uint64_t tx_errors; /* from MSM block */
|
||||
uint64_t rx_pause;
|
||||
uint64_t rx_ether_drops;
|
||||
uint64_t rx_ether_octets;
|
||||
uint64_t rx_ether_pkts;
|
||||
uint64_t rx_ether_broacasts;
|
||||
|
|
@ -64,6 +64,13 @@ struct atl_ether_stats {
|
|||
uint64_t rx_ether_crc_align_errs;
|
||||
uint64_t rx_filter_host;
|
||||
uint64_t rx_filter_lost;
|
||||
uint64_t rx_errors; /* from MSM block */
|
||||
uint64_t rx_drops; /* from MSM block */
|
||||
uint64_t rx_dma_packets;
|
||||
uint64_t rx_dma_octets;
|
||||
uint64_t rx_dma_drops; /* DMA level RX drops */
|
||||
uint64_t tx_dma_packets;
|
||||
uint64_t tx_dma_octets;
|
||||
};
|
||||
|
||||
struct atl_global_stats {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,45 @@
|
|||
Version 1.1.23
|
||||
Date 02/11/2021
|
||||
==============
|
||||
- Add License headers to atl_dump parser files
|
||||
- Fixed cpus_read lock/unlock apis for latest kernel
|
||||
- Fixed the coalescing APIs for the latest kernel
|
||||
|
||||
Version 1.1.22
|
||||
Date 11/10/2021
|
||||
==============
|
||||
- Fixed header file and warning complains
|
||||
|
||||
Version 1.1.21
|
||||
Date 29/09/2021
|
||||
==============
|
||||
- Atl-fwd: Fix name string for mac_phy stats in ethtool-dump
|
||||
- Atl-fwd: Minor additions to ethtool dump implementation
|
||||
- Atl-fwd: Add ethtool-dump parser
|
||||
- ATLDRV-1776: Fix for link flip during IPA ring reconfig
|
||||
- Atl-fwd: Update crash-dump structure to fixed size structure
|
||||
|
||||
Version 1.1.20
|
||||
Date 23/08/2021
|
||||
==============
|
||||
- Atl-fwd: Correct driver README file and export couple of APIs
|
||||
- Atl-fwd: Populate Action resolve table and Ring data in the ethtool-dump
|
||||
- ATLDRV-1766: Fix to update HWTS ring tail value to HW
|
||||
- Fix error in populating the extended stats
|
||||
- AQC113 register dump support
|
||||
- stats+crashdump implementation draft
|
||||
- Statistics and crash dump API proposal
|
||||
- factor out fwd stuff to drop headers dependencies
|
||||
|
||||
Version 1.1.19
|
||||
Date 12/07/2021
|
||||
==============
|
||||
[ATLDRV-1744] - Add FW version check in Atl-fwd driver
|
||||
- Move check for PTP UDP packets to separate function, Enable TX pad insert and Handle all FFs in ptp tx TS
|
||||
[ATLDRV-1582] - Link not Up after FLR reset
|
||||
[ATLDRV-1653] - Packet with vlan id 1 doesn't get received when rx vlan filter is disabled
|
||||
[ATLDRV-1659] - Failed to compile with CONFIG_ATLFWD_FWD=y flag on RHEL 8.3 kernel
|
||||
|
||||
Version 1.1.18
|
||||
Date 21/02/2021
|
||||
==============
|
||||
|
|
|
|||
|
|
@ -1421,7 +1421,6 @@ void cnss_schedule_recovery(struct device *dev,
|
|||
{
|
||||
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
||||
struct cnss_recovery_data *data;
|
||||
int gfp = GFP_KERNEL;
|
||||
|
||||
if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
|
||||
cnss_bus_update_status(plat_priv, CNSS_FW_DOWN);
|
||||
|
|
@ -1432,10 +1431,11 @@ void cnss_schedule_recovery(struct device *dev,
|
|||
return;
|
||||
}
|
||||
|
||||
if (in_interrupt() || irqs_disabled())
|
||||
gfp = GFP_ATOMIC;
|
||||
|
||||
data = kzalloc(sizeof(*data), gfp);
|
||||
/* Allocating memory always with GFP_ATOMIC flag inside
|
||||
* cnss_schedule_recovery(). Because there is a chance for
|
||||
* this api to be invoked in atomic context on some platforms.
|
||||
*/
|
||||
data = kzalloc(sizeof(*data), GFP_ATOMIC);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1392,7 +1392,7 @@ static const struct msm_pingroup blair_groups[] = {
|
|||
[26] = PINGROUP(26, qup13_f1, qup13_f2, NA, NA, NA, NA, NA, NA, NA, 0, -1),
|
||||
[27] = PINGROUP(27, qup11_f1, qup11_f2, MDP_VSYNC, PLL_BIST, NA, qdss_gpio14,
|
||||
NA, NA, NA, 0x9C010, 0),
|
||||
[28] = PINGROUP(28, qup11_f2, qup11_f2, MDP_VSYNC, NA, qdss_gpio15, NA, NA,
|
||||
[28] = PINGROUP(28, qup11_f1, qup11_f2, MDP_VSYNC, NA, qdss_gpio15, NA, NA,
|
||||
NA, NA, 0x9C010, 1),
|
||||
[29] = PINGROUP(29, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1),
|
||||
[30] = PINGROUP(30, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev)
|
|||
"PCIe V%d: PHY V%d: Initializing 7nm QMP phy - 100MHz\n",
|
||||
dev->rev, dev->phy_rev);
|
||||
break;
|
||||
case 7:
|
||||
EP_PCIE_DBG(dev,
|
||||
"PCIe V%d: PHY V%d: Initializing 5nm QMP phy - 100MHz\n",
|
||||
dev->rev, dev->phy_rev);
|
||||
break;
|
||||
default:
|
||||
EP_PCIE_ERR(dev,
|
||||
"PCIe V%d: Unexpected phy version %d is caught\n",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/ipa_fmwk.h>
|
||||
|
|
@ -318,6 +319,35 @@ struct ipa_fmwk_contex {
|
|||
|
||||
bool (*ipa_wdi_is_tx1_used)(void);
|
||||
|
||||
int (*ipa_wdi_get_capabilities)(struct ipa_wdi_capabilities_out_params *out);
|
||||
|
||||
int (*ipa_wdi_init_per_inst)(struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out);
|
||||
|
||||
int (*ipa_wdi_cleanup_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_reg_intf_per_inst)(
|
||||
struct ipa_wdi_reg_intf_in_params *in);
|
||||
|
||||
int (*ipa_wdi_dereg_intf_per_inst)(const char *netdev_name, u32 hdl);
|
||||
|
||||
int (*ipa_wdi_conn_pipes_per_inst)(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out);
|
||||
|
||||
int (*ipa_wdi_disconn_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_enable_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_disable_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_set_perf_profile_per_inst)(u32 hdl, struct ipa_wdi_perf_profile *profile);
|
||||
|
||||
int (*ipa_wdi_create_smmu_mapping_per_inst)(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
int (*ipa_wdi_release_smmu_mapping_per_inst)(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
/* ipa_gsb APIs*/
|
||||
int (*ipa_bridge_init)(struct ipa_bridge_init_params *params, u32 *hdl);
|
||||
|
||||
|
|
@ -1248,7 +1278,19 @@ int ipa_fmwk_register_ipa_wdi3(const struct ipa_wdi3_data *in)
|
|||
|| ipa_fmwk_ctx->ipa_wdi_get_stats
|
||||
|| ipa_fmwk_ctx->ipa_get_wdi_version
|
||||
|| ipa_fmwk_ctx->ipa_wdi_sw_stats
|
||||
|| ipa_fmwk_ctx->ipa_wdi_is_tx1_used) {
|
||||
|| ipa_fmwk_ctx->ipa_wdi_is_tx1_used
|
||||
|| ipa_fmwk_ctx->ipa_wdi_get_capabilities
|
||||
|| ipa_fmwk_ctx->ipa_wdi_init_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_cleanup_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_reg_intf_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_dereg_intf_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_conn_pipes_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_disconn_pipes_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_enable_pipes_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_disable_pipes_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_set_perf_profile_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_create_smmu_mapping_per_inst
|
||||
|| ipa_fmwk_ctx->ipa_wdi_release_smmu_mapping_per_inst) {
|
||||
pr_err("ipa_wdi3 APIs were already initialized\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
|
@ -1271,7 +1313,26 @@ int ipa_fmwk_register_ipa_wdi3(const struct ipa_wdi3_data *in)
|
|||
ipa_fmwk_ctx->ipa_wdi_sw_stats = in->ipa_wdi_sw_stats;
|
||||
ipa_fmwk_ctx->ipa_get_wdi_version = in->ipa_get_wdi_version;
|
||||
ipa_fmwk_ctx->ipa_wdi_is_tx1_used = in->ipa_wdi_is_tx1_used;
|
||||
|
||||
ipa_fmwk_ctx->ipa_wdi_get_capabilities = in->ipa_wdi_get_capabilities;
|
||||
ipa_fmwk_ctx->ipa_wdi_init_per_inst = in->ipa_wdi_init_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_cleanup_per_inst = in->ipa_wdi_cleanup_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_reg_intf_per_inst = in->ipa_wdi_reg_intf_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_dereg_intf_per_inst =
|
||||
in->ipa_wdi_dereg_intf_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_conn_pipes_per_inst =
|
||||
in->ipa_wdi_conn_pipes_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_disconn_pipes_per_inst =
|
||||
in->ipa_wdi_disconn_pipes_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_enable_pipes_per_inst =
|
||||
in->ipa_wdi_enable_pipes_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_disable_pipes_per_inst =
|
||||
in->ipa_wdi_disable_pipes_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_set_perf_profile_per_inst =
|
||||
in->ipa_wdi_set_perf_profile_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_create_smmu_mapping_per_inst =
|
||||
in->ipa_wdi_create_smmu_mapping_per_inst;
|
||||
ipa_fmwk_ctx->ipa_wdi_release_smmu_mapping_per_inst =
|
||||
in->ipa_wdi_release_smmu_mapping_per_inst;
|
||||
pr_info("ipa_wdi3 registered successfully\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -1411,6 +1472,139 @@ int ipa_wdi_release_smmu_mapping(u32 num_buffers,
|
|||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_release_smmu_mapping);
|
||||
|
||||
int ipa_wdi_get_capabilities(struct ipa_wdi_capabilities_out_params *out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_get_capabilities, out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_get_capabilities);
|
||||
|
||||
int ipa_wdi_init_per_inst(struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_init_per_inst,
|
||||
in, out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_init_per_inst);
|
||||
|
||||
int ipa_wdi_cleanup_per_inst(u32 hdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_cleanup_per_inst, hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_cleanup_per_inst);
|
||||
|
||||
int ipa_wdi_reg_intf_per_inst(
|
||||
struct ipa_wdi_reg_intf_in_params *in)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_reg_intf_per_inst,
|
||||
in);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_reg_intf_per_inst);
|
||||
|
||||
int ipa_wdi_dereg_intf_per_inst(const char *netdev_name, u32 hdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_dereg_intf_per_inst,
|
||||
netdev_name, hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_dereg_intf_per_inst);
|
||||
|
||||
int ipa_wdi_conn_pipes_per_inst(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_conn_pipes_per_inst,
|
||||
in, out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_conn_pipes_per_inst);
|
||||
|
||||
int ipa_wdi_disconn_pipes_per_inst(u32 hdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_disconn_pipes_per_inst, hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_disconn_pipes_per_inst);
|
||||
|
||||
int ipa_wdi_enable_pipes_per_inst(u32 hdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_enable_pipes_per_inst, hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_enable_pipes_per_inst);
|
||||
|
||||
int ipa_wdi_disable_pipes_per_inst(u32 hdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_disable_pipes_per_inst, hdl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_disable_pipes_per_inst);
|
||||
|
||||
int ipa_wdi_set_perf_profile_per_inst(u32 hdl,
|
||||
struct ipa_wdi_perf_profile *profile)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN(ipa_wdi_set_perf_profile_per_inst,
|
||||
hdl, profile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_set_perf_profile_per_inst);
|
||||
|
||||
int ipa_wdi_create_smmu_mapping_per_inst(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN_DP(ipa_wdi_create_smmu_mapping_per_inst,
|
||||
hdl, num_buffers, info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_create_smmu_mapping_per_inst);
|
||||
|
||||
int ipa_wdi_release_smmu_mapping_per_inst(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPA_FMWK_DISPATCH_RETURN_DP(ipa_wdi_release_smmu_mapping_per_inst,
|
||||
hdl, num_buffers, info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa_wdi_release_smmu_mapping_per_inst);
|
||||
|
||||
int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ static void mhi_dev_event_msi_cb(void *req)
|
|||
ch->pend_flush_cnt = 0;
|
||||
mhi = ch->ring->mhi_dev;
|
||||
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI completed for flush req %d\n",
|
||||
ereq->flush_num);
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI completed for %s flush req %d\n",
|
||||
ereq->is_stale ? "stale" : "", ereq->flush_num);
|
||||
|
||||
/* Add back the flushed events space to the event buffer */
|
||||
ch->evt_buf_wp = ereq->start + ereq->num_events;
|
||||
|
|
@ -383,8 +383,11 @@ static void mhi_dev_event_msi_cb(void *req)
|
|||
spin_lock_irqsave(&mhi->lock, flags);
|
||||
if (ch->curr_ereq == NULL)
|
||||
ch->curr_ereq = ereq;
|
||||
else
|
||||
else {
|
||||
if (ereq->is_stale)
|
||||
ereq->is_stale = false;
|
||||
list_add_tail(&ereq->list, &ch->event_req_buffers);
|
||||
}
|
||||
spin_unlock_irqrestore(&mhi->lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -3256,6 +3259,7 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle)
|
|||
struct mhi_dev_channel *ch;
|
||||
int count = 0;
|
||||
int rc = 0;
|
||||
struct event_req *itr, *tmp;
|
||||
if (!handle) {
|
||||
mhi_log(MHI_MSG_ERROR, "Invalid channel access:%d\n", -ENODEV);
|
||||
return;
|
||||
|
|
@ -3291,20 +3295,14 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle)
|
|||
"Trying to close an active channel (%d)\n",
|
||||
ch->ch_id);
|
||||
|
||||
if (!list_empty(&ch->flush_event_req_buffers)) {
|
||||
list_for_each_entry_safe(itr, tmp, &ch->flush_event_req_buffers, list) {
|
||||
itr->is_stale = true;
|
||||
}
|
||||
}
|
||||
|
||||
ch->state = MHI_DEV_CH_CLOSED;
|
||||
ch->active_client = NULL;
|
||||
kfree(ch->ereqs);
|
||||
mhi_log(MHI_MSG_INFO,
|
||||
"MEM_DEALLOC:ch:%d size:%d EREQ\n",
|
||||
ch->ch_id, ch->evt_req_size);
|
||||
kfree(ch->tr_events);
|
||||
mhi_log(MHI_MSG_INFO,
|
||||
"MEM_DEALLOC:ch:%d size:%d TR_EVENTS\n",
|
||||
ch->ch_id, ch->evt_buf_size);
|
||||
ch->evt_buf_size = 0;
|
||||
ch->evt_req_size = 0;
|
||||
ch->ereqs = NULL;
|
||||
ch->tr_events = NULL;
|
||||
kfree(handle);
|
||||
mhi_log(MHI_MSG_INFO,
|
||||
"MEM_ALLOC:ch:%d size:%d CLNT_HANDLE\n",
|
||||
|
|
@ -3535,13 +3533,16 @@ int mhi_dev_write_channel(struct mhi_req *wreq)
|
|||
* Expected usage is when there is a write
|
||||
* to the MHI core -> notify SM.
|
||||
*/
|
||||
mutex_lock(&mhi_ctx->mhi_lock);
|
||||
mhi_log(MHI_MSG_CRITICAL, "Wakeup by chan:%d\n", ch->ch_id);
|
||||
rc = mhi_dev_notify_sm_event(MHI_DEV_EVENT_CORE_WAKEUP);
|
||||
if (rc) {
|
||||
pr_err("error sending core wakeup event\n");
|
||||
mutex_unlock(&mhi_ctx->mhi_lock);
|
||||
mutex_unlock(&mhi_ctx->mhi_write_test);
|
||||
return rc;
|
||||
}
|
||||
mutex_unlock(&mhi_ctx->mhi_lock);
|
||||
}
|
||||
|
||||
while (atomic_read(&mhi_ctx->is_suspended) &&
|
||||
|
|
|
|||
|
|
@ -452,6 +452,7 @@ struct event_req {
|
|||
struct list_head list;
|
||||
u32 flush_num;
|
||||
bool is_cmd_cpl;
|
||||
bool is_stale;
|
||||
};
|
||||
|
||||
struct mhi_cmd_cmpl_ctx {
|
||||
|
|
|
|||
|
|
@ -334,9 +334,15 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
|||
memset_io(data_buf->base, 0, data_buf->size);
|
||||
data_buf->iova = dma_map_resource(dev, data_buf->phys_base,
|
||||
data_buf->size, DMA_BIDIRECTIONAL, 0);
|
||||
if (dma_mapping_error(dev, data_buf->iova))
|
||||
if (dma_mapping_error(dev, data_buf->iova)) {
|
||||
log_event_err("%s(): oci_mem: err mapping data_buf\n",
|
||||
__func__);
|
||||
iounmap(data_buf->base);
|
||||
data_buf->base = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
log_event_dbg("%s: data_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
|
||||
__func__, dev_name(dev), data_buf->base,
|
||||
(unsigned long)data_buf->phys_base, data_buf->iova);
|
||||
|
|
@ -348,7 +354,11 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
|||
if (!desc_buf->base) {
|
||||
log_event_err("%s: ioremap failed for desc fifo\n",
|
||||
__func__);
|
||||
dma_unmap_resource(dev, data_buf->iova,
|
||||
data_buf->size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
iounmap(data_buf->base);
|
||||
data_buf->base = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
|
@ -356,9 +366,19 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
|
|||
desc_buf->iova = dma_map_resource(dev, desc_buf->phys_base,
|
||||
desc_buf->size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
if (dma_mapping_error(dev, desc_buf->iova))
|
||||
if (dma_mapping_error(dev, desc_buf->iova)) {
|
||||
log_event_err("%s(): oci_mem: err mapping desc_buf\n",
|
||||
__func__);
|
||||
dma_unmap_resource(dev, data_buf->iova,
|
||||
data_buf->size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
iounmap(data_buf->base);
|
||||
data_buf->base = NULL;
|
||||
iounmap(desc_buf->base);
|
||||
desc_buf->base = NULL;
|
||||
ret = -ENOMEM;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
log_event_dbg("%s: desc_buf:%s virt:%pK, phys:%lx, iova:%lx\n",
|
||||
__func__, dev_name(dev), desc_buf->base,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ static bool enable_dump =
|
|||
IS_ENABLED(CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT);
|
||||
static enum qcom_download_mode current_download_mode = QCOM_DOWNLOAD_NODUMP;
|
||||
static enum qcom_download_mode dump_mode = QCOM_DOWNLOAD_FULLDUMP;
|
||||
static bool early_pcie_init_enable;
|
||||
|
||||
static int set_download_mode(enum qcom_download_mode mode)
|
||||
{
|
||||
|
|
@ -262,8 +263,10 @@ static int qcom_dload_reboot(struct notifier_block *this, unsigned long event,
|
|||
set_download_mode(QCOM_DOWNLOAD_NODUMP);
|
||||
|
||||
if (cmd) {
|
||||
if (!strcmp(cmd, "edl"))
|
||||
set_download_mode(QCOM_DOWNLOAD_EDL);
|
||||
if (!strcmp(cmd, "edl")) {
|
||||
early_pcie_init_enable ? set_download_mode(QCOM_EDLOAD_PCI_MODE)
|
||||
: set_download_mode(QCOM_DOWNLOAD_EDL);
|
||||
}
|
||||
else if (!strcmp(cmd, "qcom_dload"))
|
||||
msm_enable_dump_mode(true);
|
||||
}
|
||||
|
|
@ -311,6 +314,33 @@ static void store_kaslr_offset(void)
|
|||
static void store_kaslr_offset(void) {}
|
||||
#endif /* CONFIG_RANDOMIZE_BASE */
|
||||
|
||||
static void check_pci_edl(struct device_node *np)
|
||||
{
|
||||
void __iomem *mem;
|
||||
uint32_t read_val;
|
||||
int ret_l, ret_h, l, h, mask_value;
|
||||
|
||||
mem = of_iomap(np, 0);
|
||||
if (!mem) {
|
||||
pr_info("Unable to map memory for DT property: %s\n", np->name);
|
||||
return;
|
||||
}
|
||||
|
||||
read_val = __raw_readl(mem);
|
||||
ret_l = of_property_read_u32_index(np, "qcom,boot-config-shift", 0, &l);
|
||||
ret_h = of_property_read_u32_index(np, "qcom,boot-config-shift", 1, &h);
|
||||
|
||||
if (!ret_l && !ret_h) {
|
||||
mask_value = (read_val >> l) & GENMASK(h - l, 0);
|
||||
if (mask_value == 5 || mask_value == 7) {
|
||||
early_pcie_init_enable = true;
|
||||
pr_info("Setting up EDL mode to PCIE\n");
|
||||
}
|
||||
}
|
||||
|
||||
iounmap(mem);
|
||||
}
|
||||
|
||||
static int qcom_dload_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_dload *poweroff;
|
||||
|
|
@ -340,6 +370,7 @@ static int qcom_dload_probe(struct platform_device *pdev)
|
|||
|
||||
poweroff->dload_dest_addr = map_prop_mem("qcom,msm-imem-dload-type");
|
||||
store_kaslr_offset();
|
||||
check_pci_edl(pdev->dev.of_node);
|
||||
|
||||
msm_enable_dump_mode(enable_dump);
|
||||
if (!enable_dump)
|
||||
|
|
|
|||
|
|
@ -1778,14 +1778,17 @@ static int msm_serial_probe(struct platform_device *pdev)
|
|||
struct uart_port *port;
|
||||
const struct of_device_id *id;
|
||||
int irq, line;
|
||||
bool flag = false;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
line = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
else
|
||||
line = pdev->id;
|
||||
|
||||
if (line < 0)
|
||||
if (line < 0) {
|
||||
flag = true;
|
||||
line = atomic_inc_return(&msm_uart_next_id) - 1;
|
||||
}
|
||||
|
||||
if (unlikely(line < 0 || line >= UART_NR))
|
||||
return -ENXIO;
|
||||
|
|
@ -1803,26 +1806,40 @@ static int msm_serial_probe(struct platform_device *pdev)
|
|||
msm_port->is_uartdm = 0;
|
||||
|
||||
msm_port->clk = devm_clk_get(&pdev->dev, "core");
|
||||
if (IS_ERR(msm_port->clk))
|
||||
if (IS_ERR(msm_port->clk)) {
|
||||
if (flag)
|
||||
atomic_dec(&msm_uart_next_id);
|
||||
return PTR_ERR(msm_port->clk);
|
||||
}
|
||||
|
||||
if (msm_port->is_uartdm) {
|
||||
msm_port->pclk = devm_clk_get(&pdev->dev, "iface");
|
||||
if (IS_ERR(msm_port->pclk))
|
||||
if (IS_ERR(msm_port->pclk)) {
|
||||
if (flag)
|
||||
atomic_dec(&msm_uart_next_id);
|
||||
return PTR_ERR(msm_port->pclk);
|
||||
}
|
||||
}
|
||||
|
||||
port->uartclk = clk_get_rate(msm_port->clk);
|
||||
dev_info(&pdev->dev, "uartclk = %d\n", port->uartclk);
|
||||
|
||||
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(!resource))
|
||||
if (unlikely(!resource)) {
|
||||
if (flag)
|
||||
atomic_dec(&msm_uart_next_id);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
port->mapbase = resource->start;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (unlikely(irq < 0))
|
||||
if (unlikely(irq < 0)) {
|
||||
if (flag)
|
||||
atomic_dec(&msm_uart_next_id);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
port->irq = irq;
|
||||
|
||||
platform_set_drvdata(pdev, port);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,16 @@ int set_qdss_data_connection(struct f_qdss *qdss, int enable)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
usb_bam_alloc_fifos(usb_bam_type, idx);
|
||||
ret = usb_bam_alloc_fifos(usb_bam_type, idx);
|
||||
if (ret) {
|
||||
pr_err("%s: usb_bam_alloc_fifos failed(%d)\n",
|
||||
__func__, ret);
|
||||
dma_unmap_resource(dev->parent, bam_info.qdss_bam_iova,
|
||||
bam_info.qdss_bam_size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bam_info.data_fifo =
|
||||
kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
|
||||
if (!bam_info.data_fifo) {
|
||||
|
|
|
|||
|
|
@ -3623,8 +3623,10 @@ sm_done:
|
|||
spin_unlock_irqrestore(&pd->rx_lock, flags);
|
||||
|
||||
/* requeue if there are any new/pending RX messages */
|
||||
if (!ret && !pd->sm_queued)
|
||||
if (!ret) {
|
||||
usbpd_dbg(&pd->dev, "Requeuing new/pending RX messages\n");
|
||||
kick_sm(pd, 0);
|
||||
}
|
||||
|
||||
if (!pd->sm_queued)
|
||||
pm_relax(&pd->dev);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ struct br_ip_list {
|
|||
|
||||
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
|
||||
|
||||
//Handle HYFI_BRIDGING hooks related stuffs, only if HYFI_BRIDGE_HOOKS is defined
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
struct net_bridge_port;
|
||||
#endif
|
||||
|
||||
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
|
||||
|
||||
#ifdef CONFIG_ENABLE_SFE
|
||||
|
|
@ -151,4 +156,11 @@ br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
|
||||
extern br_notify_hook_t __rcu *br_notify_hook;
|
||||
typedef int (br_multicast_handle_hook_t)(const struct net_bridge_port *src,
|
||||
struct sk_buff *skb);
|
||||
extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook;
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018 - 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _IPA_FMWK_H_
|
||||
|
|
@ -207,6 +208,35 @@ struct ipa_wdi3_data {
|
|||
int (*ipa_get_wdi_version)(void);
|
||||
|
||||
bool (*ipa_wdi_is_tx1_used)(void);
|
||||
|
||||
int (*ipa_wdi_get_capabilities)(struct ipa_wdi_capabilities_out_params *out);
|
||||
|
||||
int (*ipa_wdi_init_per_inst)(struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out);
|
||||
|
||||
int (*ipa_wdi_cleanup_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_reg_intf_per_inst)(
|
||||
struct ipa_wdi_reg_intf_in_params *in);
|
||||
|
||||
int (*ipa_wdi_dereg_intf_per_inst)(const char *netdev_name, u32 hdl);
|
||||
|
||||
int (*ipa_wdi_conn_pipes_per_inst)(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out);
|
||||
|
||||
int (*ipa_wdi_disconn_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_enable_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_disable_pipes_per_inst)(u32 hdl);
|
||||
|
||||
int (*ipa_wdi_set_perf_profile_per_inst)(u32 hdl, struct ipa_wdi_perf_profile *profile);
|
||||
|
||||
int (*ipa_wdi_create_smmu_mapping_per_inst)(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
int (*ipa_wdi_release_smmu_mapping_per_inst)(u32 hdl, u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
};
|
||||
|
||||
struct ipa_qdss_data {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018 - 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _IPA_WDI3_H_
|
||||
|
|
@ -19,15 +20,19 @@
|
|||
|
||||
#define IPA_WDI_MAX_SUPPORTED_SYS_PIPE 3
|
||||
|
||||
typedef u32 ipa_wdi_hdl_t;
|
||||
|
||||
enum ipa_wdi_version {
|
||||
IPA_WDI_1,
|
||||
IPA_WDI_2,
|
||||
IPA_WDI_3
|
||||
IPA_WDI_3,
|
||||
IPA_WDI_VER_MAX
|
||||
};
|
||||
|
||||
#define IPA_WDI3_TX_DIR 1
|
||||
#define IPA_WDI3_TX1_DIR 2
|
||||
#define IPA_WDI3_RX_DIR 3
|
||||
#define IPA_WDI_INST_MAX (2)
|
||||
|
||||
/**
|
||||
* struct ipa_wdi_init_in_params - wdi init input parameters
|
||||
|
|
@ -43,6 +48,7 @@ struct ipa_wdi_init_in_params {
|
|||
#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
|
||||
ipa_wdi_meter_notifier_cb wdi_notify;
|
||||
#endif
|
||||
int inst_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -57,6 +63,7 @@ struct ipa_wdi_init_out_params {
|
|||
bool is_uC_ready;
|
||||
bool is_smmu_enabled;
|
||||
bool is_over_gsi;
|
||||
ipa_wdi_hdl_t hdl;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -93,6 +100,7 @@ struct ipa_wdi_reg_intf_in_params {
|
|||
u32 meta_data;
|
||||
u32 meta_data_mask;
|
||||
u8 is_tx1_used;
|
||||
ipa_wdi_hdl_t hdl;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -208,6 +216,7 @@ struct ipa_wdi_conn_in_params {
|
|||
struct ipa_wdi_pipe_setup_info tx;
|
||||
struct ipa_wdi_pipe_setup_info_smmu tx_smmu;
|
||||
} u_tx1;
|
||||
ipa_wdi_hdl_t hdl;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -236,8 +245,30 @@ struct ipa_wdi_perf_profile {
|
|||
u32 max_supported_bw_mbps;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct ipa_wdi_capabilities - wdi capability parameters
|
||||
*
|
||||
* @num_of_instances: Number of WLAN instances supported.
|
||||
*/
|
||||
struct ipa_wdi_capabilities_out_params {
|
||||
u8 num_of_instances;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPA3)
|
||||
|
||||
/**
|
||||
* ipa_wdi_get_capabilities - Client should call this function to
|
||||
* know the WDI capabilities
|
||||
*
|
||||
* Note: Should not be called from atomic context and only
|
||||
* after checking IPA readiness using ipa_register_ipa_ready_cb()
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_get_capabilities(
|
||||
struct ipa_wdi_capabilities_out_params *out);
|
||||
|
||||
/**
|
||||
* ipa_wdi_init - Client should call this function to
|
||||
* init WDI IPA offload data path
|
||||
|
|
@ -256,6 +287,18 @@ int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
|
|||
*/
|
||||
bool ipa_wdi_is_tx1_used(void);
|
||||
|
||||
/**
|
||||
* ipa_wdi_init_per_inst - Client should call this function to
|
||||
* init WDI IPA offload data path
|
||||
*
|
||||
* Note: Should not be called from atomic context and only
|
||||
* after checking IPA readiness using ipa_register_ipa_ready_cb()
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_init_per_inst(struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out);
|
||||
|
||||
/**
|
||||
* ipa_wdi_cleanup - Client should call this function to
|
||||
* clean up WDI IPA offload data path
|
||||
|
|
@ -264,6 +307,17 @@ bool ipa_wdi_is_tx1_used(void);
|
|||
*/
|
||||
int ipa_wdi_cleanup(void);
|
||||
|
||||
/**
|
||||
* ipa_wdi_cleanup_per_inst - Client should call this function to
|
||||
* clean up WDI IPA offload data path
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_cleanup_per_inst(ipa_wdi_hdl_t hdl);
|
||||
|
||||
|
||||
/**
|
||||
* ipa_wdi_reg_intf - Client should call this function to
|
||||
* register interface
|
||||
|
|
@ -275,6 +329,17 @@ int ipa_wdi_cleanup(void);
|
|||
int ipa_wdi_reg_intf(
|
||||
struct ipa_wdi_reg_intf_in_params *in);
|
||||
|
||||
/**
|
||||
* ipa_wdi_reg_intf_per_inst - Client should call this function to
|
||||
* register interface
|
||||
*
|
||||
* Note: Should not be called from atomic context
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_reg_intf_per_inst(
|
||||
struct ipa_wdi_reg_intf_in_params *in);
|
||||
|
||||
/**
|
||||
* ipa_wdi_dereg_intf - Client Driver should call this
|
||||
* function to deregister before unload and after disconnect
|
||||
|
|
@ -283,6 +348,14 @@ int ipa_wdi_reg_intf(
|
|||
*/
|
||||
int ipa_wdi_dereg_intf(const char *netdev_name);
|
||||
|
||||
/**
|
||||
* ipa_wdi_dereg_intf_per_inst - Client Driver should call this
|
||||
* function to deregister before unload and after disconnect
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_dereg_intf_per_inst(const char *netdev_name, ipa_wdi_hdl_t hdl);
|
||||
|
||||
/**
|
||||
* ipa_wdi_conn_pipes - Client should call this
|
||||
* function to connect pipes
|
||||
|
|
@ -297,6 +370,20 @@ int ipa_wdi_dereg_intf(const char *netdev_name);
|
|||
int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out);
|
||||
|
||||
/**
|
||||
* ipa_wdi_conn_pipes_per_inst - Client should call this
|
||||
* function to connect pipes
|
||||
*
|
||||
* @in: [in] input parameters from client
|
||||
* @out: [out] output params to client
|
||||
*
|
||||
* Note: Should not be called from atomic context
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_conn_pipes_per_inst(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out);
|
||||
|
||||
/**
|
||||
* ipa_wdi_disconn_pipes() - Client should call this
|
||||
* function to disconnect pipes
|
||||
|
|
@ -307,6 +394,17 @@ int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
|
|||
*/
|
||||
int ipa_wdi_disconn_pipes(void);
|
||||
|
||||
/**
|
||||
* ipa_wdi_disconn_pipes_per_inst() - Client should call this
|
||||
* function to disconnect pipes
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* Note: Should not be called from atomic context
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_disconn_pipes_per_inst(ipa_wdi_hdl_t hdl);
|
||||
|
||||
/**
|
||||
* ipa_wdi_enable_pipes() - Client should call this
|
||||
* function to enable IPA offload data path
|
||||
|
|
@ -317,6 +415,17 @@ int ipa_wdi_disconn_pipes(void);
|
|||
*/
|
||||
int ipa_wdi_enable_pipes(void);
|
||||
|
||||
/**
|
||||
* ipa_wdi_enable_pipes_per_inst() - Client should call this
|
||||
* function to enable IPA offload data path
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* Note: Should not be called from atomic context
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_enable_pipes_per_inst(ipa_wdi_hdl_t hdl);
|
||||
|
||||
/**
|
||||
* ipa_wdi_disable_pipes() - Client should call this
|
||||
* function to disable IPA offload data path
|
||||
|
|
@ -327,6 +436,17 @@ int ipa_wdi_enable_pipes(void);
|
|||
*/
|
||||
int ipa_wdi_disable_pipes(void);
|
||||
|
||||
/**
|
||||
* ipa_wdi_disable_pipes_per_inst() - Client should call this
|
||||
* function to disable IPA offload data path
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* Note: Should not be called from atomic context
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_disable_pipes_per_inst(ipa_wdi_hdl_t hdl);
|
||||
|
||||
/**
|
||||
* ipa_wdi_set_perf_profile() - Client should call this function to
|
||||
* set IPA clock bandwidth based on data rates
|
||||
|
|
@ -337,6 +457,18 @@ int ipa_wdi_disable_pipes(void);
|
|||
*/
|
||||
int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile);
|
||||
|
||||
/**
|
||||
* ipa_wdi_set_perf_profile_per_inst() - Client should call this function to
|
||||
* set IPA clock bandwidth based on data rates
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* @profile: [in] BandWidth profile to use
|
||||
*
|
||||
* Returns: 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_set_perf_profile_per_inst(ipa_wdi_hdl_t hdl,
|
||||
struct ipa_wdi_perf_profile *profile);
|
||||
|
||||
/**
|
||||
* ipa_wdi_create_smmu_mapping() - Create smmu mapping
|
||||
*
|
||||
|
|
@ -347,6 +479,17 @@ int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile);
|
|||
int ipa_wdi_create_smmu_mapping(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
/**
|
||||
* ipa_wdi_create_smmu_mapping_per_inst() - Create smmu mapping
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* @num_buffers: number of buffers
|
||||
* @info: wdi buffer info
|
||||
*/
|
||||
int ipa_wdi_create_smmu_mapping_per_inst(ipa_wdi_hdl_t hdl,
|
||||
u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
/**
|
||||
* ipa_wdi_release_smmu_mapping() - Release smmu mapping
|
||||
*
|
||||
|
|
@ -357,6 +500,18 @@ int ipa_wdi_create_smmu_mapping(u32 num_buffers,
|
|||
int ipa_wdi_release_smmu_mapping(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
/**
|
||||
* ipa_wdi_release_smmu_mapping_per_inst() - Release smmu mapping
|
||||
*
|
||||
* @hdl: hdl to wdi client
|
||||
* @num_buffers: number of buffers
|
||||
*
|
||||
* @info: wdi buffer info
|
||||
*/
|
||||
int ipa_wdi_release_smmu_mapping_per_inst(ipa_wdi_hdl_t hdl,
|
||||
u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info);
|
||||
|
||||
/**
|
||||
* ipa_wdi_get_stats() - Query WDI statistics
|
||||
* @stats: [inout] stats blob from client populated by driver
|
||||
|
|
@ -394,12 +549,34 @@ int ipa_get_wdi_version(void);
|
|||
|
||||
#else /* IS_ENABLED(CONFIG_IPA3) */
|
||||
|
||||
/**
|
||||
* ipa_wdi_get_capabilities - Client should call this function to
|
||||
* know the WDI capabilities
|
||||
*
|
||||
* Note: Should not be called from atomic context and only
|
||||
* after checking IPA readiness using ipa_register_ipa_ready_cb()
|
||||
*
|
||||
* @Return 0 on success, negative on failure
|
||||
*/
|
||||
int ipa_wdi_get_capabilities(
|
||||
struct ipa_wdi_capabilities_out_params *out)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_init_per_inst(
|
||||
struct ipa_wdi_init_in_params *in,
|
||||
struct ipa_wdi_init_out_params *out)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_get_wdi_version(void)
|
||||
{
|
||||
return -EPERM;
|
||||
|
|
@ -415,56 +592,119 @@ static inline int ipa_wdi_cleanup(void)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_cleanup_per_inst(ipa_wdi_hdl_t hdl)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_reg_intf(
|
||||
struct ipa_wdi_reg_intf_in_params *in)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_reg_intf_per_inst(
|
||||
struct ipa_wdi_reg_intf_in_params *in)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_dereg_intf(const char *netdev_name)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_dereg_intf_per_inst(const char *netdev_name,
|
||||
ipa_wdi_hdl_t hdl)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_conn_pipes_per_inst(
|
||||
struct ipa_wdi_conn_in_params *in,
|
||||
struct ipa_wdi_conn_out_params *out)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_disconn_pipes(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_disconn_pipes_per_inst(ipa_wdi_hdl_t hdl)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
||||
static inline int ipa_wdi_enable_pipes(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_enable_pipes_per_inst(ipa_wdi_hdl_t hdl)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_disable_pipes(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_disable_pipes_per_inst(ipa_wdi_hdl_t hdl)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_set_perf_profile(
|
||||
struct ipa_wdi_perf_profile *profile)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_set_perf_profile_per_inst(
|
||||
ipa_wdi_hdl_t hdl,
|
||||
struct ipa_wdi_perf_profile *profile)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_create_smmu_mapping(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_create_smmu_mapping_per_inst(
|
||||
ipa_wdi_hdl_t hdl,
|
||||
u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_release_smmu_mapping(u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_release_smmu_mapping_per_inst(
|
||||
ipa_wdi_hdl_t hdl,
|
||||
u32 num_buffers,
|
||||
struct ipa_wdi_buffer_info *info)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
|
||||
{
|
||||
return -EPERM;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ enum {
|
|||
NETIF_F_HW_TLS_RECORD_BIT, /* Offload TLS record */
|
||||
NETIF_F_GRO_FRAGLIST_BIT, /* Fraglist GRO */
|
||||
|
||||
NETIF_F_HW_MACSEC_BIT, /* Offload MACsec operations */
|
||||
|
||||
/*
|
||||
* Add your fresh new feature above and remember to update
|
||||
* netdev_features_strings[] in net/ethtool/common.c and maybe
|
||||
|
|
@ -154,6 +156,7 @@ enum {
|
|||
#define NETIF_F_HW_TLS_RX __NETIF_F(HW_TLS_RX)
|
||||
#define NETIF_F_GRO_FRAGLIST __NETIF_F(GRO_FRAGLIST)
|
||||
#define NETIF_F_GSO_FRAGLIST __NETIF_F(GSO_FRAGLIST)
|
||||
#define NETIF_F_HW_MACSEC __NETIF_F(HW_MACSEC)
|
||||
|
||||
/* Finds the next feature with the highest number of the range of start till 0.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ struct netpoll_info;
|
|||
struct device;
|
||||
struct phy_device;
|
||||
struct dsa_port;
|
||||
struct macsec_context;
|
||||
struct macsec_ops;
|
||||
|
||||
struct sfp_bus;
|
||||
/* 802.11 specific */
|
||||
|
|
@ -1809,6 +1811,8 @@ enum netdev_priv_flags {
|
|||
*
|
||||
* @wol_enabled: Wake-on-LAN is enabled
|
||||
*
|
||||
* @macsec_ops: MACsec offloading ops
|
||||
*
|
||||
* FIXME: cleanup struct net_device such that network protocol info
|
||||
* moves out.
|
||||
*/
|
||||
|
|
@ -2100,6 +2104,11 @@ struct net_device {
|
|||
bool proto_down;
|
||||
unsigned wol_enabled:1;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MACSEC)
|
||||
/* MACsec management functions */
|
||||
const struct macsec_ops *macsec_ops;
|
||||
#endif
|
||||
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
ANDROID_KABI_RESERVE(2);
|
||||
ANDROID_KABI_RESERVE(3);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
enum qcom_download_mode {
|
||||
QCOM_DOWNLOAD_NODUMP = 0x00,
|
||||
QCOM_DOWNLOAD_EDL = 0x01,
|
||||
QCOM_EDLOAD_PCI_MODE = 0X04,
|
||||
QCOM_DOWNLOAD_FULLDUMP = 0x10,
|
||||
QCOM_DOWNLOAD_MINIDUMP = 0x20,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -231,7 +231,10 @@ struct macsec_secy {
|
|||
* struct macsec_context - MACsec context for hardware offloading
|
||||
*/
|
||||
struct macsec_context {
|
||||
struct phy_device *phydev;
|
||||
union {
|
||||
struct net_device *netdev;
|
||||
struct phy_device *phydev;
|
||||
};
|
||||
enum macsec_offload offload;
|
||||
|
||||
struct macsec_secy *secy;
|
||||
|
|
|
|||
|
|
@ -14,27 +14,27 @@
|
|||
|
||||
TRACE_EVENT(cpu_power_select,
|
||||
|
||||
TP_PROTO(int index, u32 sleep_us, u32 latency, u32 next_event_us),
|
||||
TP_PROTO(int index, u32 sleep_us, u32 latency, u64 sched_bias),
|
||||
|
||||
TP_ARGS(index, sleep_us, latency, next_event_us),
|
||||
TP_ARGS(index, sleep_us, latency, sched_bias),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, index)
|
||||
__field(u32, sleep_us)
|
||||
__field(u32, latency)
|
||||
__field(u32, next_event_us)
|
||||
__field(u64, sched_bias)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->index = index;
|
||||
__entry->sleep_us = sleep_us;
|
||||
__entry->latency = latency;
|
||||
__entry->next_event_us = next_event_us;
|
||||
__entry->sched_bias = sched_bias;
|
||||
),
|
||||
|
||||
TP_printk("idx:%d sleep_time:%u latency:%u next_event:%u",
|
||||
TP_printk("idx:%d sleep_time:%u latency:%u sched_bias:%lu",
|
||||
__entry->index, __entry->sleep_us, __entry->latency,
|
||||
__entry->next_event_us)
|
||||
__entry->sched_bias)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cpu_pred_select,
|
||||
|
|
|
|||
|
|
@ -2841,7 +2841,7 @@ struct ipa_move_nat_table_complt_ind_msg_v01 {
|
|||
#define QMI_IPA_MOVE_NAT_COMPLETE_IND_V01 0x0046
|
||||
|
||||
/* add for max length*/
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 210
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 197
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_RESP_MAX_MSG_LEN_V01 25
|
||||
#define QMI_IPA_INDICATION_REGISTER_REQ_MAX_MSG_LEN_V01 16
|
||||
#define QMI_IPA_INDICATION_REGISTER_RESP_MAX_MSG_LEN_V01 7
|
||||
|
|
|
|||
|
|
@ -61,3 +61,15 @@ config BRIDGE_VLAN_FILTERING
|
|||
Say N to exclude this support and reduce the binary size.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HYFI_BRIDGE_HOOKS
|
||||
bool "Port Hy-Fi Bridging Hooks"
|
||||
depends on BRIDGE
|
||||
depends on QGKI
|
||||
default y
|
||||
help
|
||||
If you say Y here, then the Port Hy-Fi Bridging Hooks will be enabled.
|
||||
|
||||
Say N to exclude this support.
|
||||
|
||||
If unsure, say Y.
|
||||
|
|
|
|||
|
|
@ -394,6 +394,12 @@ static void __exit br_deinit(void)
|
|||
br_fdb_fini();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
/* Hook for bridge event notifications */
|
||||
br_notify_hook_t __rcu *br_notify_hook __read_mostly;
|
||||
EXPORT_SYMBOL(br_notify_hook);
|
||||
#endif
|
||||
|
||||
module_init(br_init)
|
||||
module_exit(br_deinit)
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (is_broadcast_ether_addr(dest)) {
|
||||
br_flood(br, skb, BR_PKT_BROADCAST, false, true);
|
||||
} else if (is_multicast_ether_addr(dest)) {
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
br_multicast_handle_hook_t *multicast_handle_hook =
|
||||
rcu_dereference(br_multicast_handle_hook);
|
||||
if (!__br_get(multicast_handle_hook, true, NULL, skb))
|
||||
goto out;
|
||||
#endif
|
||||
if (unlikely(netpoll_tx_running(dev))) {
|
||||
br_flood(br, skb, BR_PKT_MULTICAST, false, true);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,10 @@ struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
|
|||
return fdb_find_rcu(&br->fdb_hash_tbl, addr, vid);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
EXPORT_SYMBOL(br_fdb_find_rcu);
|
||||
#endif
|
||||
|
||||
/* When a static FDB entry is added, the mac address from the entry is
|
||||
* added to the bridge private HW address list and all required ports
|
||||
* are then updated with the new information.
|
||||
|
|
@ -709,6 +713,9 @@ static void fdb_notify(struct net_bridge *br,
|
|||
kfree_skb(skb);
|
||||
goto errout;
|
||||
}
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
__br_notify(RTNLGRP_NEIGH, type, fdb);
|
||||
#endif
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
errout:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,13 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
|
|||
return netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
static int br_pass_frame_up(struct sk_buff *skb)
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
/* Hook for external Multicast handler */
|
||||
br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly;
|
||||
EXPORT_SYMBOL(br_multicast_handle_hook);
|
||||
#endif
|
||||
|
||||
int br_pass_frame_up(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
|
||||
struct net_bridge *br = netdev_priv(brdev);
|
||||
|
|
@ -66,6 +72,10 @@ static int br_pass_frame_up(struct sk_buff *skb)
|
|||
br_netif_receive_skb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
EXPORT_SYMBOL(br_pass_frame_up);
|
||||
#endif
|
||||
|
||||
/* note: already called with rcu_read_lock */
|
||||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -75,6 +85,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
|||
struct net_bridge_mdb_entry *mdst;
|
||||
bool local_rcv, mcast_hit = false;
|
||||
struct net_bridge *br;
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
br_multicast_handle_hook_t *multicast_handle_hook;
|
||||
#endif
|
||||
u16 vid = 0;
|
||||
|
||||
if (!p || p->state == BR_STATE_DISABLED)
|
||||
|
|
@ -128,6 +141,11 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
|||
|
||||
switch (pkt_type) {
|
||||
case BR_PKT_MULTICAST:
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
multicast_handle_hook = rcu_dereference(br_multicast_handle_hook);
|
||||
if (!__br_get(multicast_handle_hook, true, p, skb))
|
||||
goto out;
|
||||
#endif
|
||||
mdst = br_mdb_get(br, skb, vid);
|
||||
if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
|
||||
br_multicast_querier_exists(br, eth_hdr(skb))) {
|
||||
|
|
|
|||
|
|
@ -499,6 +499,9 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
|
|||
kfree_skb(skb);
|
||||
goto errout;
|
||||
}
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
__br_notify(RTNLGRP_LINK, event, port);
|
||||
#endif
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
errout:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
#include <linux/if_vlan.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/refcount.h>
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
#include <linux/export.h>
|
||||
#endif
|
||||
|
||||
#define BR_HASH_BITS 8
|
||||
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
|
||||
|
|
@ -625,6 +628,9 @@ void br_manage_promisc(struct net_bridge *br);
|
|||
int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
|
||||
|
||||
/* br_input.c */
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
int br_pass_frame_up(struct sk_buff *skb);
|
||||
#endif
|
||||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
|
||||
|
||||
|
|
@ -1266,4 +1272,17 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
|
|||
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
|
||||
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
|
||||
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
|
||||
#ifdef CONFIG_HYFI_BRIDGE_HOOKS
|
||||
#define __br_get(__hook, __default, __args ...) \
|
||||
({ typeof(__hook) HOOK_ = (__hook); \
|
||||
(HOOK_ ? (HOOK_(__args)) : (__default)); })
|
||||
|
||||
static inline void __br_notify(int group, int type, const void *data)
|
||||
{
|
||||
br_notify_hook_t *notify_hook = rcu_dereference(br_notify_hook);
|
||||
|
||||
if (notify_hook)
|
||||
notify_hook(group, type, data);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
|
|||
[NETIF_F_HW_TLS_RECORD_BIT] = "tls-hw-record",
|
||||
[NETIF_F_HW_TLS_TX_BIT] = "tls-hw-tx-offload",
|
||||
[NETIF_F_HW_TLS_RX_BIT] = "tls-hw-rx-offload",
|
||||
[NETIF_F_HW_MACSEC_BIT] = "macsec-hw-offload",
|
||||
};
|
||||
|
||||
static const char
|
||||
|
|
|
|||
Loading…
Reference in a new issue