Merge commit '1337cd6a19dc8f7fe0d355334d43b0ef1ba87d0f'

* commit '1337cd6a19dc8f7fe0d355334d43b0ef1ba87d0f':
  arm64: dts: rockchip: rv1126b-evb1-v10: rockchip_suspend: sleep-debug-en = 1
  arm64: dts: rockchip: rv1126b: rockchip_suspend: sleep-debug-en = 0
  arm64: dts: rockchip: Add rv1126b-thunder-boot for SPI Nor/eMMC
  media: rockchip: sc850sl: Support for 40 frame rates
  arm64: dts: rockchip: rv1126b-evb2-v10: sc485sl enable hw_standby
  media: rockchip: isp: fix sequence error correction
  drm/rockchip: vop2: Fix the abnormal brightness when post-csc is enabled
  media: rockchip: vpss: reset sw_vi2enc_sel on dvbm deinit
  arm64: dts: rockchip: rk3588-evb: Use the hdmi phy pll dynamic allocation mode
  media: rockchip: vpss: fix ch5 output issue
  media: rockchip: vpss: reduce rockit buf vmap
  video: rockchip: mpp: rkvdec2: Fix reg reading
  misc: rockchip: pcie-rkep: Fix mutex lock not released in pcie_rkep_release
  phy: rockchip-snps-pcie3: RK3588 phy lock determines compatibility with all bifurcation situations
  video: rockchip: rga3: adapt to kernel-6.12
  net: r8168: update r8168 driver to v8.055.00

Change-Id: I0670788cb1339561587f40a9825461b1bbae20ae
This commit is contained in:
Tao Huang
2025-06-06 18:38:03 +08:00
45 changed files with 7612 additions and 3617 deletions

View File

@@ -280,6 +280,11 @@
mem-supply = <&vdd_cpu_big1_mem_s0>;
};
&display_subsystem {
clocks = <&hdptxphy_hdmi0>, <&hdptxphy_hdmi1>;
clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
};
&dsi0 {
status = "disabled";
//rockchip,lane-rate = <1000>;

View File

@@ -17,6 +17,8 @@
&rockchip_suspend {
status = "okay";
rockchip,sleep-debug-en = <1>;
rockchip,sleep-mode-config = <
(0
| RKPM_SLP_ARMOFF_LOGOFF

View File

@@ -588,6 +588,7 @@
&sc850sl {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-stb = <1>;
};
&sdmmc0 {

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
#include "rv1126b-thunder-boot.dtsi"
/ {
thunder_boot_mmc: thunder-boot-mmc {
compatible = "rockchip,thunder-boot-mmc";
reg = <0x21470000 0x4000>;
clocks = <&cru HCLK_EMMC>, <&cru CCLK_EMMC>;
clock-names = "biu", "ciu";
memory-region-src = <&ramdisk_c>;
memory-region-dst = <&ramdisk_r>;
memory-region-idmac = <&mmc_idmac>;
};
};
&emmc {
memory-region-ecsd = <&mmc_ecsd>;
post-power-on-delay-ms = <0>;
};
&reserved_memory {
mmc_ecsd: mmc@47fffe00 {
reg = <0x47fffe00 0x00001000>;
};
mmc_idmac: mmc@48000000 {
reg = <0x48000000 0x00400000>;
};
};

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
#include "rv1126b-thunder-boot.dtsi"
/ {
thunder_boot_spi_nor: thunder-boot-spi-nor {
compatible = "rockchip,thunder-boot-sfc";
reg = <0x21460000 0x4000>;
memory-region-src = <&ramdisk_c>;
memory-region-dst = <&ramdisk_r>;
};
};

View File

@@ -0,0 +1,95 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
/ {
ramdisk: ramdisk {
compatible = "rockchip,ramdisk";
memory-region = <&ramdisk_r>;
};
};
&reserved_memory {
/*
* reserved memory layout
*
* H _______________________
* | |
* | ramdisk_c |
* |_______________________|
* | |
* | ramdisk_r |
* 0x48c40000 |_______________________|
* | |
* | mcu_log |
* 0x48c3c000 |_______________________|
* | |
* | mcu |
* 0x48c00000 |_______________________|
* | |
* | [TEEOS+TA+SHM] |
* 0x48400000 |_______________________|
* | |
* | isp[0..1]_tb_rmem |
* |_______________________|
* | |
* | meta |
* 0x41240000 |_______________________|
* | |
* | fdt |
* 0x41200000 |_______________________|
* | |
* | kernel_r |
* 0x40208000 |_______________________|
* | |
* | bl31 |
* L |_______________________|
*
*/
meta: meta@41240000 {
/* reg's offset MUST match with RTOS */
reg = <0x41240000 0x000c0000>;
};
rkisp_thunderboot: rkisp@41300000 {
/* reg's offset MUST match with RTOS */
/*
* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num)
* e.g. 1920x1080: 0xa8c000
*/
reg = <0x41300000 0xa8c000>;
};
rkisp1_thunderboot: rkisp1_thunderboot {
/* vicap capture for a second camera */
};
/* Should enable this node if the security feature is enabled, like TA. */
tee: tee@48400000 {
reg = <0x48400000 0x00800000>;
status = "disabled";
};
rtos: rtos@48c00000 {
reg = <0x48c00000 0x0003a000>;
};
mcu_log: mcu_log@48c3c000 {
reg = <0x48c3c000 0x4000>;
};
ramdisk_r: ramdisk_r {
reg = <0x48c40000 (10 * 0x00100000)>;
};
ramdisk_c: ramdisk_c {
reg = <0x49640000 (5 * 0x00100000)>;
};
};
&hw_decompress {
memory-region = <&ramdisk_c>;
status = "okay";
};

View File

@@ -879,7 +879,7 @@
rockchip_suspend: rockchip-suspend {
compatible = "rockchip,pm-config";
status = "disabled";
rockchip,sleep-debug-en = <0>;
rockchip,sleep-mode-config = <
(0
| RKPM_SLP_ARMOFF_PMUOFF

View File

@@ -12888,7 +12888,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
struct vop2 *vop2 = vp->vop2;
struct drm_plane *plane;
struct drm_plane_state *pstate, *pstate_max = NULL;
struct drm_plane_state *pstate, *max_yuv_pstate = NULL;
struct vop2_plane_state *vpstate;
struct post_csc_coef csc_coef = {};
struct post_csc_convert_mode convert_mode = {};
@@ -12896,6 +12896,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
bool acm_enable;
bool post_r2y_en = false;
bool post_csc_en = false;
bool rgb_limited_plane = false;
int range_type;
u64 max_yuv_plane = 0, plane_area;
enum drm_color_encoding max_yuv_plane_color_encoding = DRM_COLOR_YCBCR_BT601;
@@ -12907,13 +12908,17 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
vpstate = to_vop2_plane_state(pstate);
dest = &vpstate->dest;
if (!pstate->fb->format->is_yuv &&
pstate->color_range != DRM_COLOR_YCBCR_FULL_RANGE)
rgb_limited_plane = true;
if (pstate->fb->format->is_yuv) {
plane_area = drm_rect_width(dest) * drm_rect_height(dest);
/* find yuv plane with largest area */
if (max_yuv_plane < plane_area) {
max_yuv_plane = plane_area;
max_yuv_plane_color_encoding = pstate->color_encoding;
pstate_max = pstate;
max_yuv_pstate = pstate;
}
}
}
@@ -12948,36 +12953,49 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st
if (is_yuv_output(vcstate->bus_format))
convert_mode.is_output_yuv = true;
if (!vcstate->yuv_overlay || vp->has_dci_enabled_win)
if (vp->has_dci_enabled_win) {
convert_mode.is_input_full_range = true;
else if (vcstate->yuv_overlay)
} else if (!vcstate->yuv_overlay) {
/* if there are yuv planes, choose max plane's range */
if (max_yuv_pstate) {
/* Todo RGB limit range plane */
convert_mode.is_input_full_range = true;
} else {
if (rgb_limited_plane)
convert_mode.is_input_full_range = false;
else
convert_mode.is_input_full_range = true;
}
} else {
/* yuv overlay range is limited */
convert_mode.is_input_full_range = false;
else if (pstate_max)
convert_mode.is_input_full_range =
pstate_max->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
else
convert_mode.is_input_full_range =
vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
}
convert_mode.is_output_full_range =
vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH);
if (post_csc_en) {
convert_mode.output_color_encoding = vcstate->color_encoding;
/*
* When all layers are rgb, the post-csc input color encoding
* is fixed to rgb full, and the value of input_color_encoding
* has no actual utility.
* If there are any yuv planes, value of post-csc input_color_encoding
* selects the value of the yuv plane with the largest area.
*/
if (!pstate_max && !vcstate->yuv_overlay)
convert_mode.intput_color_encoding = vcstate->color_encoding;
else
convert_mode.intput_color_encoding = max_yuv_plane_color_encoding;
convert_mode.output_color_encoding = vcstate->color_encoding;
/*
* When all layers are rgb, the value of input_color_encoding
* has no actual utility, however, the plane csc only supports
* limited range under bt709. Therefore, in this scene, the colorspace
* of plane csc is selected as bt601. The intput_color_encoding
* is consistent with colorspace of plane csc, which is DRM_COLOR_YCBCR_BT601.
* If there are any yuv planes, value of post-csc input_color_encoding
* selects the value of the yuv plane with the largest area.
*/
if (!max_yuv_pstate)
convert_mode.intput_color_encoding = DRM_COLOR_YCBCR_BT601;
else
convert_mode.intput_color_encoding = max_yuv_plane_color_encoding;
if (convert_mode.intput_color_encoding != convert_mode.output_color_encoding ||
convert_mode.is_input_full_range != convert_mode.is_output_full_range)
post_csc_en = true;
if (post_csc_en) {
rockchip_calc_post_csc(csc, &csc_coef, &convert_mode);
VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00);

View File

@@ -41,8 +41,10 @@
#endif
#define MIPI_FREQ_540M 540000000
#define MIPI_FREQ_972M 486000000
#define SC850AI_MAX_LINK_FREQ MIPI_FREQ_540M
#define SC850SL_MAX_PIXEL_RATE (MIPI_FREQ_540M / 10 * 2 * SC850SL_4LANES)
#define SC850SL_MAX_PIXEL_RATE (SC850AI_MAX_LINK_FREQ / 10 * 2 * SC850SL_4LANES)
#define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode"
#define SC850SL_XVCLK_FREQ_24M 24000000
@@ -144,6 +146,7 @@ struct sc850sl_mode {
u32 vts_def;
u32 exp_def;
u32 mipi_freq_idx;
u32 xvclk_freq;
u32 bpp;
const struct regval *reg_list;
u32 hdr_mode;
@@ -195,7 +198,7 @@ struct sc850sl {
#define to_sc850sl(sd) container_of(sd, struct sc850sl, subdev)
//cleaned_0x20_SC850SL_MIPI_24Minput_1C4D_1080Mbps_10bit_3840x2160_30fps_one_expo.ini
static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] = {
static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_30fps_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
{0x36e9, 0x80},
@@ -394,6 +397,208 @@ static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] =
{REG_NULL, 0x00},
};
static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_40fps_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
{0x36e9, 0x80},
{0x36f9, 0x80},
{0x36ea, 0x09},
{0x36eb, 0x0c},
{0x36ec, 0x4b},
{0x36ed, 0x34},
{0x36fa, 0xcb},
{0x36fb, 0x13},
{0x36fc, 0x00},
{0x36fd, 0x07},
{0x36e9, 0x53},
{0x36f9, 0x53},
{0x3000, 0x01},
{0x3018, 0x7a},
{0x3019, 0xf0},
{0x301a, 0x30},
{0x301e, 0x3c},
{0x301f, 0x0d},
{0x302a, 0x00},
{0x3031, 0x0a},
{0x3032, 0x20},
{0x3033, 0x22},
{0x3037, 0x60},
{0x303e, 0xb4},
{0x3201, 0x98},
{0x3203, 0x0c},
{0x3205, 0xa7},
{0x3207, 0x83},
{0x320c, 0x03},
{0x320d, 0x39},
{0x3211, 0x08},
{0x3213, 0x2c},
{0x3223, 0xc0},
{0x3226, 0x00},
{0x3227, 0x03},
{0x3230, 0x11},
{0x3231, 0x93},
{0x3250, 0x40},
{0x3253, 0x08},
{0x327e, 0x00},
{0x3280, 0x00},
{0x3281, 0x00},
{0x3301, 0x24},
{0x3304, 0x30},
{0x3306, 0x54},
{0x3308, 0x10},
{0x3309, 0x60},
{0x330a, 0x00},
{0x330b, 0xa0},
{0x330d, 0x10},
{0x3314, 0x92},
{0x331e, 0x29},
{0x331f, 0x59},
{0x3333, 0x10},
{0x3347, 0x05},
{0x3348, 0xd0},
{0x3352, 0x01},
{0x3356, 0x38},
{0x335d, 0x60},
{0x3362, 0x70},
{0x338f, 0x80},
{0x33af, 0x48},
{0x33fe, 0x00},
{0x3400, 0x12},
{0x3406, 0x04},
{0x3410, 0x12},
{0x3416, 0x06},
{0x3433, 0x01},
{0x3440, 0x12},
{0x3446, 0x08},
{0x3478, 0x01},
{0x3479, 0x01},
{0x347a, 0x02},
{0x347b, 0x01},
{0x347c, 0x04},
{0x347d, 0x01},
{0x3616, 0x0c},
{0x3620, 0x94},
{0x3622, 0x74},
{0x3629, 0x74},
{0x362a, 0xf0},
{0x362b, 0x0f},
{0x362d, 0x00},
{0x3630, 0x68},
{0x3633, 0x24},
{0x3634, 0x22},
{0x3635, 0x20},
{0x3637, 0x18},
{0x3638, 0x26},
{0x363b, 0x06},
{0x363c, 0x07},
{0x363d, 0x05},
{0x363e, 0x8f},
{0x3648, 0xe0},
{0x3649, 0x0a},
{0x364a, 0x06},
{0x364c, 0x6a},
{0x3650, 0x3d},
{0x3654, 0x70},
{0x3656, 0x68},
{0x3657, 0x0f},
{0x3658, 0x3d},
{0x365c, 0x40},
{0x365e, 0x68},
{0x3901, 0x04},
{0x3902, 0xf1},
{0x3904, 0x20},
{0x3905, 0x91},
{0x391e, 0x03},
{0x3928, 0x04},
{0x3933, 0xa0},
{0x3934, 0x0a},
{0x3935, 0x68},
{0x3936, 0x00},
{0x3937, 0x20},
{0x3938, 0x0a},
{0x3946, 0x20},
{0x3961, 0x40},
{0x3962, 0x40},
{0x3963, 0xc8},
{0x3964, 0xc8},
{0x3965, 0x40},
{0x3966, 0x40},
{0x3967, 0x00},
{0x39cd, 0xc8},
{0x39ce, 0xc8},
{0x3e01, 0x82},
{0x3e02, 0x00},
{0x3e0e, 0x02},
{0x3e0f, 0x00},
{0x3e1c, 0x0f},
{0x3e23, 0x00},
{0x3e24, 0x00},
{0x3e53, 0x00},
{0x3e54, 0x00},
{0x3e68, 0x00},
{0x3e69, 0x80},
{0x3e73, 0x00},
{0x3e74, 0x00},
{0x3e86, 0x03},
{0x3e87, 0x40},
{0x3f02, 0x24},
{0x4424, 0x02},
{0x4501, 0xb4},
{0x4503, 0x20},
{0x4509, 0x20},
{0x4561, 0x12},
{0x4800, 0x24},
{0x4837, 0x20},
{0x4900, 0x24},
{0x4937, 0x16},
{0x5000, 0x0e},
{0x500f, 0x35},
{0x5020, 0x00},
{0x5787, 0x10},
{0x5788, 0x06},
{0x5789, 0x00},
{0x578a, 0x18},
{0x578b, 0x0c},
{0x578c, 0x00},
{0x5790, 0x10},
{0x5791, 0x06},
{0x5792, 0x01},
{0x5793, 0x18},
{0x5794, 0x0c},
{0x5795, 0x01},
{0x5799, 0x06},
{0x57a2, 0x60},
{0x59e0, 0xfe},
{0x59e1, 0x40},
{0x59e2, 0x38},
{0x59e3, 0x30},
{0x59e4, 0x20},
{0x59e5, 0x38},
{0x59e6, 0x30},
{0x59e7, 0x20},
{0x59e8, 0x3f},
{0x59e9, 0x38},
{0x59ea, 0x30},
{0x59eb, 0x3f},
{0x59ec, 0x38},
{0x59ed, 0x30},
{0x59ee, 0xfe},
{0x59ef, 0x40},
{0x59f4, 0x38},
{0x59f5, 0x30},
{0x59f6, 0x20},
{0x59f7, 0x38},
{0x59f8, 0x30},
{0x59f9, 0x20},
{0x59fa, 0x3f},
{0x59fb, 0x38},
{0x59fc, 0x30},
{0x59fd, 0x3f},
{0x59fe, 0x38},
{0x59ff, 0x30},
{REG_NULL, 0x00},
};
/*
* The width and height must be configured to be
* the same as the current output resolution of the sensor.
@@ -407,6 +612,26 @@ static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] =
* }
*/
static const struct sc850sl_mode supported_modes[] = {
#if defined CONFIG_VIDEO_CAM_SLEEP_WAKEUP
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.width = 3840,
.height = 2160,
.max_fps = {
.numerator = 10000,
.denominator = 400000,
},
.exp_def = 0x08c0,
.hts_def = 0x10e0,
.vts_def = 0x08ca,
.reg_list = sc850sl_linear10bit_3840x2160_40fps_regs,
.hdr_mode = NO_HDR,
.xvclk_freq = 24000000,
.mipi_freq_idx = 1,
.bpp = 10,
.vc[PAD0] = 0,
},
#endif
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.width = 3840,
@@ -419,8 +644,9 @@ static const struct sc850sl_mode supported_modes[] = {
.hts_def = 0x0226 * 5 - 0x180,
.vts_def = 0x08ca,
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.reg_list = sc850sl_linear10bit_3840x2160_regs,
.reg_list = sc850sl_linear10bit_3840x2160_30fps_regs,
.hdr_mode = NO_HDR,
.xvclk_freq = 24000000,
.mipi_freq_idx = 0,
.bpp = 10,
.vc[PAD0] = 0,
@@ -441,6 +667,7 @@ static const char *const sc850sl_test_pattern_menu[] = {
static const s64 link_freq_items[] = {
MIPI_FREQ_540M,
MIPI_FREQ_972M,
};
/* Write registers up to 4 at a time */
@@ -1025,6 +1252,7 @@ static long sc850sl_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
case RKMODULE_SET_QUICK_STREAM:
stream = *((u32 *)arg);
dev_info(&sc850sl->client->dev, "stream: %d\n", stream);
if (stream) {
ret |= sc850sl_write_reg(sc850sl->client, 0x3019,
@@ -1354,10 +1582,10 @@ static int __sc850sl_power_on(struct sc850sl *sc850sl)
if (ret < 0)
dev_err(dev, "could not set pins\n");
}
ret = clk_set_rate(sc850sl->xvclk, SC850SL_XVCLK_FREQ_24M);
ret = clk_set_rate(sc850sl->xvclk, sc850sl->cur_mode->xvclk_freq);
if (ret < 0)
dev_warn(dev, "Failed to set xvclk rate 24MHz\n");
if (clk_get_rate(sc850sl->xvclk) != SC850SL_XVCLK_FREQ_24M)
if (clk_get_rate(sc850sl->xvclk) != sc850sl->cur_mode->xvclk_freq)
dev_warn(dev, "xvclk mismatched\n");
ret = clk_prepare_enable(sc850sl->xvclk);
if (ret < 0) {
@@ -1973,7 +2201,7 @@ static int sc850sl_probe(struct i2c_client *client,
#endif
if (!sc850sl->cam_sw_info) {
sc850sl->cam_sw_info = cam_sw_init();
cam_sw_clk_init(sc850sl->cam_sw_info, sc850sl->xvclk, SC850SL_XVCLK_FREQ_24M);
cam_sw_clk_init(sc850sl->cam_sw_info, sc850sl->xvclk, sc850sl->cur_mode->xvclk_freq);
cam_sw_reset_pin_init(sc850sl->cam_sw_info, sc850sl->reset_gpio, 0);
cam_sw_pwdn_pin_init(sc850sl->cam_sw_info, sc850sl->pwdn_gpio, 1);
}

View File

@@ -4242,7 +4242,7 @@ static int rkisp_vicap_sof(struct rkisp_device *dev, struct rkisp_vicap_sof *sof
v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
"vicap sof %d, isp sof %d\n",
sof->sequence, dev->dmarx_dev.cur_frame.id);
dev->dmarx_dev.cur_frame.id = sof->sequence;
dev->dmarx_dev.cur_frame.id = sof->sequence - 1;
}
spin_unlock_irqrestore(&dev->rdbk_lock, flag);
return 0;

View File

@@ -51,6 +51,12 @@ enum {
ROCKIT_DVBM_START,
};
enum {
DVBM_DEINIT = 0,
DVBM_ONLINE = 1,
DVBM_OFFLINE = 2,
};
enum rkvpss_fmt_pix_type {
FMT_YUV,
FMT_RGB,
@@ -112,6 +118,7 @@ static inline int vpss_outchn_max(int version)
}
extern int rkvpss_debug;
extern int rkvpss_buf_dbg;
extern struct platform_driver rkvpss_plat_drv;
extern int rkvpss_cfginfo_num;

View File

@@ -18,6 +18,10 @@ int rkvpss_debug;
module_param_named(debug, rkvpss_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-6)");
int rkvpss_buf_dbg;
module_param_named(buf_dbg, rkvpss_buf_dbg, int, 0644);
MODULE_PARM_DESC(buf_dbg, "rkvpss buf dbg");
static bool rkvpss_clk_dbg;
module_param_named(clk_dbg, rkvpss_clk_dbg, bool, 0644);
MODULE_PARM_DESC(clk_dbg, "rkvpss clk set by user");

View File

@@ -70,6 +70,8 @@ struct rkvpss_hw_dev {
bool is_suspend;
bool is_first;
bool is_probe_end;
int dvbm_refcnt;
int dvbm_flag;
};
#ifdef CONFIG_VIDEO_ROCKCHIP_VPSS_V10

View File

@@ -746,9 +746,9 @@ static struct stream_config scl5_config = {
.uv_offs_cnt = RKVPSS2X_MI_CHN5_WR_CB_OFFS_CNT,
.y_pic_width = RKVPSS2X_MI_CHN5_WR_Y_PIC_WIDTH,
.y_pic_size = RKVPSS2X_MI_CHN5_WR_Y_PIC_SIZE,
.ctrl_shd = RKVPSS2X_MI_CHN4_WR_CTRL_SHD,
.y_shd = RKVPSS2X_MI_CHN4_WR_Y_BASE_SHD,
.uv_shd = RKVPSS2X_MI_CHN4_WR_CB_BASE_SHD,
.ctrl_shd = RKVPSS2X_MI_CHN5_WR_CTRL_SHD,
.y_shd = RKVPSS2X_MI_CHN5_WR_Y_BASE_SHD,
.uv_shd = RKVPSS2X_MI_CHN5_WR_CB_BASE_SHD,
},
};
@@ -887,7 +887,7 @@ static void scl_force_update(struct rkvpss_stream *stream)
val = RKVPSS2X_MI_CHN4_FORCE_UPD;
break;
case RKVPSS_OUTPUT_CH5:
val = RKVPSS2X_MI_CHN4_FORCE_UPD;
val = RKVPSS2X_MI_CHN5_FORCE_UPD;
break;
default:
return;
@@ -1129,7 +1129,7 @@ static void scl_disable_mi(struct rkvpss_stream *stream)
val = RKVPSS2X_ISP2VPSS_CHN4_SEL(3);
break;
case RKVPSS_OUTPUT_CH5:
val = RKVPSS2X_ISP2VPSS_CHN4_SEL(3);
val = RKVPSS2X_ISP2VPSS_CHN5_SEL(3);
break;
default:
return;
@@ -1992,6 +1992,13 @@ static void rkvpss_stop_streaming(struct vb2_queue *queue)
destroy_buf_queue(stream, VB2_BUF_STATE_ERROR);
rkvpss_pipeline_close(dev);
tasklet_disable(&stream->buf_done_tasklet);
if (hw->dvbm_refcnt <= 0 && hw->dvbm_flag != DVBM_OFFLINE) {
v4l2_dbg(2, rkvpss_debug, &dev->v4l2_dev, "%s: clear vpss2enc_sel\n", __func__);
rkvpss_hw_clear_bits(hw, RKVPSS_VPSS_CTRL, RKVPSS_VPSS2ENC_SEL);
hw->dvbm_refcnt = 0;
}
v4l2_dbg(1, rkvpss_debug, &dev->v4l2_dev,
"%s %s id:%d exit\n", __func__,
node->vdev.name, stream->id);
@@ -2103,7 +2110,10 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count)
goto pipe_close;
}
if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0)
rkvpss_dvbm_init(stream);
if (rkvpss_dvbm_init(stream) != 0) {
v4l2_err(&dev->v4l2_dev, "dvbm init failed\n");
goto stop_stream;
}
ret = rkvpss_pipeline_stream(dev, true);
if (ret < 0)
goto stop_stream;

View File

@@ -50,6 +50,14 @@ int rkvpss_dvbm_init(struct rkvpss_stream *stream)
if (!g_dvbm)
return -EINVAL;
if (vpss_dev->hw_dev->dvbm_flag == DVBM_OFFLINE) {
v4l2_err(&vpss_dev->v4l2_dev,
"offline dvbm already set, online dvbm set fail.\n");
return -EINVAL;
}
vpss_dev->hw_dev->dvbm_refcnt++;
vpss_dev->hw_dev->dvbm_flag = DVBM_ONLINE;
width = stream->out_fmt.plane_fmt[0].bytesperline;
height = stream->out_fmt.height;
@@ -76,6 +84,11 @@ void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev)
pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_dvbm, vpss_dev);
return;
}
vpss_dev->hw_dev->dvbm_refcnt--;
if (vpss_dev->hw_dev->dvbm_refcnt <= 0)
vpss_dev->hw_dev->dvbm_flag = DVBM_DEINIT;
rk_dvbm_unlink(g_dvbm, vpss_dev->dev_id);
}

View File

@@ -38,13 +38,20 @@ int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl)
return ret;
}
int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line,
int width, int height, int id)
int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf, u32 dma_addr,
u32 wrap_line, int width, int height, int id)
{
struct dvbm_isp_cfg_t dvbm_cfg;
if (!g_ofl_dvbm)
return -EINVAL;
if (ofl->hw->dvbm_flag == DVBM_ONLINE) {
v4l2_err(&ofl->v4l2_dev,
"online dvbm already set, offline dvbm set fail.\n");
return -EINVAL;
}
ofl->hw->dvbm_flag = DVBM_OFFLINE;
dvbm_cfg.dma_addr = dma_addr;
dvbm_cfg.buf = dbuf;
@@ -70,7 +77,10 @@ void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id)
pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_ofl_dvbm, ofl);
return;
}
ofl->hw->dvbm_flag = DVBM_DEINIT;
rk_dvbm_unlink(g_ofl_dvbm, id);
v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, "%s: clear vpss2enc_sel\n", __func__);
rkvpss_hw_clear_bits(ofl->hw, RKVPSS_VPSS_CTRL, RKVPSS_VPSS2ENC_SEL);
}
int rkvpss_ofl_dvbm_event(u32 event, u32 seq)

View File

@@ -12,12 +12,15 @@
#if IS_ENABLED(CONFIG_ROCKCHIP_DVBM)
int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl);
int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id);
int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf,
u32 dma_addr, u32 wrap_line, int width, int height, int id);
void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id);
int rkvpss_ofl_dvbm_event(u32 event, u32 seq);
#else
static inline int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl) {return -EINVAL; }
static inline int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id) {return -EINVAL; }
static inline int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf,
u32 dma_addr, u32 wrap_line, int width, int height,
int id) {return -EINVAL; }
static inline void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id) {}
static inline int rkvpss_ofl_dvbm_event(u32 event, u32 seq) {return -EINVAL; }
#endif

View File

@@ -2438,7 +2438,7 @@ static long rkvpss_ofl_wrap_dvbm_init(struct rkvpss_offline_dev *ofl,
wrap_line = cfg->output[i].wrap.wrap_line;
rkvpss_ofl_dvbm_init(dbuf, dma_addr, wrap_line, width, height, cfg->dev_id);
rkvpss_ofl_dvbm_init(ofl, dbuf, dma_addr, wrap_line, width, height, cfg->dev_id);
v4l2_dbg(4, rkvpss_debug, &ofl->v4l2_dev, "%s file_id:%d dev_id:%d wrap_chn:%d\n",
__func__, file_id, cfg->dev_id, i);

View File

@@ -216,8 +216,13 @@ int rkvpss_rockit_buf_queue(struct rockit_rkvpss_cfg *input_cfg)
}
vpssrk_buf->vaddr = NULL;
if (dma_buf_vmap(input_cfg->buf, &map) == 0)
vpssrk_buf->vaddr = map.vaddr;
/* default vmap two to get image, rkvpss_buf_dbg > 0 to vmap all */
if (i < 2 || rkvpss_buf_dbg > 0) {
v4l2_dbg(3, rkvpss_debug, &vpss_dev->v4l2_dev,
"stream:%d rockit vmap buf:%p\n", stream->id, input_cfg->buf);
if (dma_buf_vmap(input_cfg->buf, &map) == 0)
vpssrk_buf->vaddr = map.vaddr;
}
vpssrk_buf->buff_addr = sg_dma_address(sgt->sgl);
get_dma_buf(input_cfg->buf);

View File

@@ -351,8 +351,10 @@ static int pcie_rkep_release(struct inode *inode, struct file *file)
mutex_lock(&pcie_file->file_lock_mutex);
index = find_first_bit(pcie_file->child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX);
if (index >= RKEP_EP_VIRTUAL_ID_MAX)
if (index >= RKEP_EP_VIRTUAL_ID_MAX) {
mutex_unlock(&pcie_file->file_lock_mutex);
break;
}
__clear_bit(index, pcie_file->child_vid_bitmap);
mutex_unlock(&pcie_file->file_lock_mutex);

View File

@@ -4,7 +4,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@@ -44,6 +44,11 @@ ENABLE_S0_MAGIC_PACKET = n
CONFIG_DYNAMIC_ASPM = y
ENABLE_USE_FIRMWARE_FILE = n
CONFIG_CTAP_SHORT_OFF = n
ENABLE_MULTIPLE_TX_QUEUE = n
ENABLE_RSS_SUPPORT = n
ENABLE_LIB_SUPPORT = n
DISABLE_WOL_SUPPORT = n
ENABLE_GIGA_LITE = y
ifneq ($(KERNELRELEASE),)
obj-$(CONFIG_R8168) := r8168.o
@@ -67,7 +72,9 @@ ifneq ($(KERNELRELEASE),)
r8168-objs += r8168_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
endif
EXTRA_CFLAGS += -DCONFIG_R8168_NAPI
ifneq ($(ENABLE_RSS_SUPPORT), y)
EXTRA_CFLAGS += -DCONFIG_R8168_NAPI
endif
EXTRA_CFLAGS += -DCONFIG_R8168_VLAN
ifeq ($(CONFIG_DOWN_SPEED_100), y)
EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
@@ -97,6 +104,23 @@ ifneq ($(KERNELRELEASE),)
ifeq ($(CONFIG_CTAP_SHORT_OFF), y)
EXTRA_CFLAGS += -DCONFIG_CTAP_SHORT_OFF
endif
ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y)
EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE
endif
ifeq ($(ENABLE_RSS_SUPPORT), y)
r8168-objs += r8168_rss.o
EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
endif
ifeq ($(ENABLE_LIB_SUPPORT), y)
r8168-objs += r8168_lib.o
EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT
endif
ifeq ($(DISABLE_WOL_SUPPORT), y)
EXTRA_CFLAGS += -DDISABLE_WOL_SUPPORT
endif
ifeq ($(ENABLE_GIGA_LITE), y)
EXTRA_CFLAGS += -DENABLE_GIGA_LITE
endif
else
BASEDIR := /lib/modules/$(shell uname -r)
KERNELDIR ?= $(BASEDIR)/build

View File

@@ -4,7 +4,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@@ -60,7 +60,6 @@ int rtl8168_asf_ioctl(struct net_device *dev,
struct rtl8168_private *tp = netdev_priv(dev);
void *user_data = ifr->ifr_data;
struct asf_ioctl_struct asf_usrdata;
unsigned long flags;
if (tp->mcfg != CFG_METHOD_7 && tp->mcfg != CFG_METHOD_8)
return -EOPNOTSUPP;
@@ -68,8 +67,6 @@ int rtl8168_asf_ioctl(struct net_device *dev,
if (copy_from_user(&asf_usrdata, user_data, sizeof(struct asf_ioctl_struct)))
return -EFAULT;
spin_lock_irqsave(&tp->lock, flags);
switch (asf_usrdata.offset) {
case HBPeriod:
rtl8168_asf_hbperiod(tp, asf_usrdata.arg, asf_usrdata.u.data);
@@ -192,12 +189,9 @@ int rtl8168_asf_ioctl(struct net_device *dev,
rtl8168_asf_key_access(tp, asf_usrdata.arg, KR, asf_usrdata.u.data);
break;
default:
spin_unlock_irqrestore(&tp->lock, flags);
return -EOPNOTSUPP;
}
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(user_data, &asf_usrdata, sizeof(struct asf_ioctl_struct)))
return -EFAULT;
@@ -390,10 +384,10 @@ void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *
int i;
if (arg == ASF_GET)
for (i = 0; i < SYSID_LEN ; i++)
for (i = 0; i < SYSID_LEN; i++)
data[i] = rtl8168_eri_read(tp, SysID + i, RW_ONE_BYTE, ERIAR_ASF);
else /* arg == ASF_SET */
for (i = 0; i < SYSID_LEN ; i++)
for (i = 0; i < SYSID_LEN; i++)
rtl8168_eri_write(tp, SysID + i, RW_ONE_BYTE, data[i], ERIAR_ASF);
}
@@ -414,9 +408,9 @@ void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data
int i, j;
if (arg == ASF_GET)
for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++)
for (i = UUID_LEN - 1, j = 0; i >= 0; i--, j++)
data[j] = rtl8168_eri_read(tp, UUID + i, RW_ONE_BYTE, ERIAR_ASF);
else /* arg == ASF_SET */
for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++)
for (i = UUID_LEN - 1, j = 0; i >= 0; i--, j++)
rtl8168_eri_write(tp, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF);
}

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@@ -160,6 +160,7 @@ RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define OCP_REG_CR (0x36)
#define OCP_REG_DMEMSTA (0x38)
#define OCP_REG_GPHYAR (0x60)
#define OCP_REG_FIRMWARE_MAJOR_VERSION (0x120)
#define OCP_REG_CONFIG0_DASHEN BIT_15
@@ -175,6 +176,9 @@ RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1)
#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2)
#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3)
#define HW_DASH_SUPPORT_CMAC(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || HW_DASH_SUPPORT_TYPE_3(_M))
#define HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(_M) (HW_DASH_SUPPORT_TYPE_2(_M) || \
HW_DASH_SUPPORT_TYPE_3(_M))
#define RECV_FROM_FW_BUF_SIZE (2048)
#define SEND_TO_FW_BUF_SIZE (2048)
@@ -247,6 +251,7 @@ RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
int rtl8168_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
bool CheckDashInterrupt(struct net_device *dev, u16 status);
void HandleDashInterrupt(struct net_device *dev);
int AllocateDashShareMemory(struct net_device *dev);
void FreeAllocatedDashShareMemory(struct net_device *dev);

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek 2.5Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -0,0 +1,482 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, see <http://www.gnu.org/licenses/>.
#
# Author:
# Realtek NIC software team <nicfae@realtek.com>
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
#
################################################################################
*/
/************************************************************************************
* This product is covered by one or more of the following patents:
* US6,570,884, US6,115,776, and US6,327,625.
***********************************************************************************/
#include <linux/version.h>
#include "r8168.h"
enum rtl8168_rss_register_content {
/* RSS */
RSS_CTRL_TCP_IPV4_SUPP = (1 << 0),
RSS_CTRL_IPV4_SUPP = (1 << 1),
RSS_CTRL_TCP_IPV6_SUPP = (1 << 2),
RSS_CTRL_IPV6_SUPP = (1 << 3),
RSS_CTRL_IPV6_EXT_SUPP = (1 << 4),
RSS_CTRL_TCP_IPV6_EXT_SUPP = (1 << 5),
RSS_HALF_SUPP = (1 << 7),
RSS_QUAD_CPU_EN = (1 << 16),
RSS_HQ_Q_SUP_R = (1 << 31),
};
static int rtl8168_get_rss_hash_opts(struct rtl8168_private *tp,
struct ethtool_rxnfc *cmd)
{
cmd->data = 0;
/* Report default options for RSS */
switch (cmd->flow_type) {
case TCP_V4_FLOW:
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
fallthrough;
case IPV4_FLOW:
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
break;
case TCP_V6_FLOW:
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
fallthrough;
case IPV6_FLOW:
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
break;
default:
return -EINVAL;
}
return 0;
}
int rtl8168_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct rtl8168_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP;
if (!(dev->features & NETIF_F_RXHASH))
return ret;
switch (cmd->cmd) {
case ETHTOOL_GRXRINGS:
cmd->data = rtl8168_tot_rx_rings(tp);
ret = 0;
break;
case ETHTOOL_GRXFH:
ret = rtl8168_get_rss_hash_opts(tp, cmd);
break;
default:
break;
}
return ret;
}
u32 rtl8168_rss_indir_tbl_entries(struct rtl8168_private *tp)
{
return tp->HwSuppIndirTblEntries;
}
#define RSS_MASK_BITS_OFFSET (8)
static int _rtl8168_set_rss_hash_opt(struct rtl8168_private *tp)
{
u32 hash_mask_len;
u32 rss_ctrl;
/* Perform hash on these packet types */
rss_ctrl = RSS_CTRL_TCP_IPV4_SUPP
| RSS_CTRL_IPV4_SUPP
| RSS_CTRL_IPV6_SUPP
| RSS_CTRL_IPV6_EXT_SUPP
| RSS_CTRL_TCP_IPV6_SUPP
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
if (R8168_MULTI_RSS_4Q(tp))
rss_ctrl |= RSS_QUAD_CPU_EN;
hash_mask_len = ilog2(rtl8168_rss_indir_tbl_entries(tp));
hash_mask_len &= (BIT_0 | BIT_1 | BIT_2);
rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET;
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, rss_ctrl, ERIAR_ExGMAC);
return 0;
}
static int rtl8168_set_rss_hash_opt(struct rtl8168_private *tp,
struct ethtool_rxnfc *nfc)
{
u32 rss_flags = tp->rss_flags;
/*
* RSS does not support anything other than hashing
* to queues on src and dst IPs and ports
*/
if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3))
return -EINVAL;
switch (nfc->flow_type) {
case TCP_V4_FLOW:
case TCP_V6_FLOW:
if (!(nfc->data & RXH_IP_SRC) ||
!(nfc->data & RXH_IP_DST) ||
!(nfc->data & RXH_L4_B_0_1) ||
!(nfc->data & RXH_L4_B_2_3))
return -EINVAL;
break;
case SCTP_V4_FLOW:
case AH_ESP_V4_FLOW:
case AH_V4_FLOW:
case ESP_V4_FLOW:
case SCTP_V6_FLOW:
case AH_ESP_V6_FLOW:
case AH_V6_FLOW:
case ESP_V6_FLOW:
case IP_USER_FLOW:
case ETHER_FLOW:
/* RSS is not supported for these protocols */
if (nfc->data) {
netif_err(tp, drv, tp->dev, "Command parameters not supported\n");
return -EINVAL;
}
return 0;
default:
return -EINVAL;
}
/* if we changed something we need to update flags */
if (rss_flags != tp->rss_flags) {
u32 rss_ctrl = rtl8168_eri_read(tp, RSS_CTRL_8168, 4, ERIAR_ExGMAC);
tp->rss_flags = rss_flags;
/* Perform hash on these packet types */
rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP
| RSS_CTRL_IPV4_SUPP
| RSS_CTRL_IPV6_SUPP
| RSS_CTRL_IPV6_EXT_SUPP
| RSS_CTRL_TCP_IPV6_SUPP
| RSS_CTRL_TCP_IPV6_EXT_SUPP;
if (R8168_MULTI_RSS_4Q(tp))
rss_ctrl |= RSS_QUAD_CPU_EN;
else
rss_ctrl &= ~RSS_QUAD_CPU_EN;
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, rss_ctrl, ERIAR_ExGMAC);
}
return 0;
}
int rtl8168_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
struct rtl8168_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP;
if (!(dev->features & NETIF_F_RXHASH))
return ret;
switch (cmd->cmd) {
case ETHTOOL_SRXFH:
ret = rtl8168_set_rss_hash_opt(tp, cmd);
break;
default:
break;
}
return ret;
}
static u32 _rtl8168_get_rxfh_key_size(struct rtl8168_private *tp)
{
return sizeof(tp->rss_key);
}
u32 rtl8168_get_rxfh_key_size(struct net_device *dev)
{
struct rtl8168_private *tp = netdev_priv(dev);
if (!(dev->features & NETIF_F_RXHASH))
return 0;
return _rtl8168_get_rxfh_key_size(tp);
}
u32 rtl8168_rss_indir_size(struct net_device *dev)
{
struct rtl8168_private *tp = netdev_priv(dev);
if (!(dev->features & NETIF_F_RXHASH))
return 0;
return rtl8168_rss_indir_tbl_entries(tp);
}
static void rtl8168_get_reta(struct rtl8168_private *tp, u32 *indir)
{
int i, reta_size = rtl8168_rss_indir_tbl_entries(tp);
for (i = 0; i < reta_size; i++)
indir[i] = tp->rss_indir_tbl[i];
}
static u32 rtl8168_rss_key_reg(struct rtl8168_private *tp)
{
return RSS_KEY_8168;
}
static u32 rtl8168_rss_indir_tbl_reg(struct rtl8168_private *tp)
{
return Rss_indir_tbl;
}
static void rtl8168_store_reta(struct rtl8168_private *tp)
{
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
u16 indir_tbl_reg = rtl8168_rss_indir_tbl_reg(tp);
u32 hw_indir[RTL8168_RSS_INDIR_TBL_SIZE] = {0};
u8 *indir = tp->rss_indir_tbl;
u32 bit_on_cnt = 0x00000001;
u32 i, j;
/* Mapping redirection table to HW */
for (i = 0, j = 0; i < reta_entries; i++) {
if ((indir[i] & 2) && R8168_MULTI_RSS_4Q(tp))
hw_indir[j + 4] |= bit_on_cnt;
if (indir[i] & 1)
hw_indir[j] |= bit_on_cnt;
if (bit_on_cnt == 0x80000000) {
bit_on_cnt = 0x00000001;
j++;
continue;
}
bit_on_cnt <<= 1;
}
/* Write redirection table to HW */
for (i = 0; i < RTL8168_RSS_INDIR_TBL_SIZE; i++)
RTL_W32(tp, indir_tbl_reg + i*4, hw_indir[i]);
}
static void rtl8168_store_rss_key(struct rtl8168_private *tp)
{
const u16 rss_key_reg = rtl8168_rss_key_reg(tp);
u32 i, rss_key_size = _rtl8168_get_rxfh_key_size(tp);
u32 *rss_key = (u32*)tp->rss_key;
/* Write redirection table to HW */
for (i = 0; i < rss_key_size; i+=4)
rtl8168_eri_write(tp, rss_key_reg + i, 4, *rss_key++, ERIAR_ExGMAC);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8168_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
{
struct rtl8168_private *tp = netdev_priv(dev);
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->indir)
rtl8168_get_reta(tp, rxfh->indir);
if (rxfh->key)
memcpy(rxfh->key, tp->rss_key, RTL8168_RSS_KEY_SIZE);
return 0;
}
int rtl8168_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct rtl8168_private *tp = netdev_priv(dev);
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
int i;
/* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters
*/
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
/* Fill out the redirection table */
if (rxfh->indir) {
int max_queues = tp->num_rx_rings;
/* Verify user input. */
for (i = 0; i < reta_entries; i++)
if (rxfh->indir[i] >= max_queues)
return -EINVAL;
for (i = 0; i < reta_entries; i++)
tp->rss_indir_tbl[i] = rxfh->indir[i];
}
/* Fill out the rss hash key */
if (rxfh->key)
memcpy(tp->rss_key, rxfh->key, RTL8168_RSS_KEY_SIZE);
rtl8168_store_reta(tp);
rtl8168_store_rss_key(tp);
return 0;
}
#else
int rtl8168_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct rtl8168_private *tp = netdev_priv(dev);
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
if (indir)
rtl8168_get_reta(tp, indir);
if (key)
memcpy(key, tp->rss_key, RTL8168_RSS_KEY_SIZE);
return 0;
}
int rtl8168_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct rtl8168_private *tp = netdev_priv(dev);
u32 reta_entries = rtl8168_rss_indir_tbl_entries(tp);
int i;
/* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters
*/
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
/* Fill out the redirection table */
if (indir) {
int max_queues = tp->num_rx_rings;
/* Verify user input. */
for (i = 0; i < reta_entries; i++)
if (indir[i] >= max_queues)
return -EINVAL;
for (i = 0; i < reta_entries; i++)
tp->rss_indir_tbl[i] = indir[i];
}
/* Fill out the rss hash key */
if (key)
memcpy(tp->rss_key, key, RTL8168_RSS_KEY_SIZE);
rtl8168_store_reta(tp);
rtl8168_store_rss_key(tp);
return 0;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
static u32 rtl8168_get_rx_desc_hash(struct rtl8168_private *tp,
struct RxDescV2 *desc)
{
if (!desc->RSSResult)
fsleep(1);
return le32_to_cpu(desc->RSSResult);
}
#define RXS_8168_RSS_IPV4 BIT(17)
#define RXS_8168_RSS_IPV6 BIT(18)
#define RXS_8168_RSS_TCP BIT(19)
#define RTL8168_RXS_RSS_L3_TYPE_MASK (RXS_8168_RSS_IPV4 | RXS_8168_RSS_IPV6)
#define RTL8168_RXS_RSS_L4_TYPE_MASK (RXS_8168_RSS_TCP)
void rtl8168_rx_hash(struct rtl8168_private *tp,
struct RxDescV2 *desc,
struct sk_buff *skb)
{
u32 rss_header_info;
if (!(tp->dev->features & NETIF_F_RXHASH))
return;
rss_header_info = le32_to_cpu(desc->opts2);
if (!(rss_header_info & RTL8168_RXS_RSS_L3_TYPE_MASK))
return;
skb_set_hash(skb, rtl8168_get_rx_desc_hash(tp, desc),
(RTL8168_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
}
void rtl8168_disable_rss(struct rtl8168_private *tp)
{
rtl8168_eri_write(tp, RSS_CTRL_8168, 4, 0x00000000, ERIAR_ExGMAC);
}
void _rtl8168_config_rss(struct rtl8168_private *tp)
{
_rtl8168_set_rss_hash_opt(tp);
rtl8168_store_reta(tp);
rtl8168_store_rss_key(tp);
}
void rtl8168_config_rss(struct rtl8168_private *tp)
{
if (!HW_RSS_SUPPORT_RSS(tp))
return;
if (!tp->EnableRss) {
rtl8168_disable_rss(tp);
return;
}
_rtl8168_config_rss(tp);
}
void rtl8168_init_rss(struct rtl8168_private *tp)
{
int i;
for (i = 0; i < rtl8168_rss_indir_tbl_entries(tp); i++)
tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings);
netdev_rss_key_fill(tp->rss_key, RTL8168_RSS_KEY_SIZE);
}

View File

@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, see <http://www.gnu.org/licenses/>.
#
# Author:
# Realtek NIC software team <nicfae@realtek.com>
# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
#
################################################################################
*/
/************************************************************************************
* This product is covered by one or more of the following patents:
* US6,570,884, US6,115,776, and US6,327,625.
***********************************************************************************/
#ifndef _LINUX_RTL8168_RSS_H
#define _LINUX_RTL8168_RSS_H
#include <linux/netdevice.h>
#include <linux/types.h>
#define RTL8168_RSS_INDIR_TBL_SIZE 8
#define RTL8168_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
#define RTL8168_MAX_INDIRECTION_TABLE_ENTRIES 128
struct rtl8168_private;
struct RxDescV2;
int rtl8168_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs);
int rtl8168_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd);
u32 rtl8168_get_rxfh_key_size(struct net_device *netdev);
u32 rtl8168_rss_indir_size(struct net_device *netdev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8168_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
int rtl8168_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack);
#else
int rtl8168_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc);
int rtl8168_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
void rtl8168_rx_hash(struct rtl8168_private *tp,
struct RxDescV2 *desc,
struct sk_buff *skb);
void _rtl8168_config_rss(struct rtl8168_private *tp);
void rtl8168_config_rss(struct rtl8168_private *tp);
void rtl8168_init_rss(struct rtl8168_private *tp);
u32 rtl8168_rss_indir_tbl_entries(struct rtl8168_private *tp);
void rtl8168_disable_rss(struct rtl8168_private *tp);
#endif /* _LINUX_RTL8168_RSS_H */

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@@ -93,7 +93,7 @@ void rtl8168_eeprom_cleanup(struct rtl8168_private *tp)
rtl8168_lower_clock(tp, &x);
}
int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp)
static int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp)
{
u8 x;
int i;
@@ -104,10 +104,10 @@ int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp)
x = RTL_R8(tp, Cfg9346);
if (x & Cfg9346_EEDO) {
udelay(RTL_CLOCK_RATE * 2 * 3);
fsleep(RTL_CLOCK_RATE * 2 * 3);
return 0;
}
udelay(1);
fsleep(1);
}
return -1;
@@ -157,9 +157,8 @@ void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data)
int addr_sz = 6;
int w_dummy_addr = 4;
if(tp->eeprom_type == EEPROM_TYPE_NONE) {
return ;
}
if(tp->eeprom_type == EEPROM_TYPE_NONE)
return;
if (tp->eeprom_type==EEPROM_TYPE_93C46) {
addr_sz = 6;
@@ -178,17 +177,15 @@ void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data)
rtl8168_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
rtl8168_shift_out_bits(tp, reg, addr_sz);
if (rtl8168_eeprom_cmd_done(tp) < 0) {
if (rtl8168_eeprom_cmd_done(tp) < 0)
return;
}
rtl8168_stand_by(tp);
rtl8168_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
rtl8168_shift_out_bits(tp, reg, addr_sz);
rtl8168_shift_out_bits(tp, data, 16);
if (rtl8168_eeprom_cmd_done(tp) < 0) {
if (rtl8168_eeprom_cmd_done(tp) < 0)
return;
}
rtl8168_stand_by(tp);
rtl8168_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
@@ -202,7 +199,7 @@ void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x)
{
*x = *x | Cfg9346_EESK;
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
fsleep(RTL_CLOCK_RATE);
}
void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x)
@@ -210,7 +207,7 @@ void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x)
*x = *x & ~Cfg9346_EESK;
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
fsleep(RTL_CLOCK_RATE);
}
void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count)
@@ -229,7 +226,7 @@ void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count)
x &= ~Cfg9346_EEDI;
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
fsleep(RTL_CLOCK_RATE);
rtl8168_raise_clock(tp, &x);
rtl8168_lower_clock(tp, &x);
mask = mask >> 1;
@@ -272,7 +269,7 @@ void rtl8168_stand_by(struct rtl8168_private *tp)
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EECS | Cfg9346_EESK);
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
fsleep(RTL_CLOCK_RATE);
x |= Cfg9346_EECS;
RTL_W8(tp, Cfg9346, x);
@@ -283,7 +280,7 @@ void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp)
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
udelay(20);
fsleep(20);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
}

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
@@ -47,7 +47,6 @@
int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
{
struct rtltool_cmd my_cmd;
unsigned long flags;
int ret;
if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd)))
@@ -56,6 +55,11 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
ret = 0;
switch (my_cmd.cmd) {
case RTLTOOL_READ_MAC:
if ((my_cmd.offset + my_cmd.len) > R8168_REGS_SIZE) {
ret = -EINVAL;
break;
}
if (my_cmd.len==1)
my_cmd.data = readb(tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2)
@@ -72,8 +76,12 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
break;
}
break;
case RTLTOOL_WRITE_MAC:
if ((my_cmd.offset + my_cmd.len) > R8168_REGS_SIZE) {
ret = -EINVAL;
break;
}
if (my_cmd.len==1)
writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2)
@@ -84,51 +92,31 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_PHY:
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_mdio_prot_read(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_PHY:
spin_lock_irqsave(&tp->lock, flags);
rtl8168_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
case RTLTOOL_READ_EPHY:
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_ephy_read(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_EPHY:
spin_lock_irqsave(&tp->lock, flags);
rtl8168_ephy_write(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
case RTLTOOL_READ_ERI:
my_cmd.data = 0;
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC);
spin_unlock_irqrestore(&tp->lock, flags);
} else {
ret = -EOPNOTSUPP;
break;
@@ -138,20 +126,15 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_ERI:
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
spin_lock_irqsave(&tp->lock, flags);
rtl8168_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
spin_unlock_irqrestore(&tp->lock, flags);
} else {
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_PCI:
my_cmd.data = 0;
if (my_cmd.len==1)
@@ -173,7 +156,6 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
break;
}
break;
case RTLTOOL_WRITE_PCI:
if (my_cmd.len==1)
pci_write_config_byte(tp->pci_dev, my_cmd.offset,
@@ -188,108 +170,69 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_EEPROM:
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_eeprom_read_sc(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_EEPROM:
spin_lock_irqsave(&tp->lock, flags);
rtl8168_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
case RTL_READ_OOB_MAC:
spin_lock_irqsave(&tp->lock, flags);
rtl8168_oob_mutex_lock(tp);
my_cmd.data = rtl8168_ocp_read(tp, my_cmd.offset, 4);
rtl8168_oob_mutex_unlock(tp);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_WRITE_OOB_MAC:
if (my_cmd.len == 0 || my_cmd.len > 4)
return -EOPNOTSUPP;
spin_lock_irqsave(&tp->lock, flags);
rtl8168_oob_mutex_lock(tp);
rtl8168_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data);
rtl8168_oob_mutex_unlock(tp);
spin_unlock_irqrestore(&tp->lock, flags);
break;
case RTL_ENABLE_PCI_DIAG:
spin_lock_irqsave(&tp->lock, flags);
tp->rtk_enable_diag = 1;
spin_unlock_irqrestore(&tp->lock, flags);
dprintk("enable rtk diag\n");
break;
case RTL_DISABLE_PCI_DIAG:
spin_lock_irqsave(&tp->lock, flags);
tp->rtk_enable_diag = 0;
spin_unlock_irqrestore(&tp->lock, flags);
dprintk("disable rtk diag\n");
break;
case RTL_READ_MAC_OCP:
if (my_cmd.offset % 2)
return -EOPNOTSUPP;
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_mac_ocp_read(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_WRITE_MAC_OCP:
if ((my_cmd.offset % 2) || (my_cmd.len != 2))
return -EOPNOTSUPP;
spin_lock_irqsave(&tp->lock, flags);
rtl8168_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
case RTL_DIRECT_READ_PHY_OCP:
spin_lock_irqsave(&tp->lock, flags);
my_cmd.data = rtl8168_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset);
spin_unlock_irqrestore(&tp->lock, flags);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_DIRECT_WRITE_PHY_OCP:
spin_lock_irqsave(&tp->lock, flags);
rtl8168_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
spin_unlock_irqrestore(&tp->lock, flags);
break;
default:
ret = -EOPNOTSUPP;
break;

View File

@@ -5,7 +5,7 @@
# r8168 is the Linux device driver released for Realtek Gigabit Ethernet
# controllers with PCI-Express interface.
#
# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved.
# Copyright(c) 2024 Realtek Semiconductor Corp. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free

View File

@@ -174,25 +174,29 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
static int rockchip_p3phy_rk3588_calibrate(struct rockchip_p3phy_priv *priv)
{
int ret = 0;
u32 reg;
u32 phy0_status, phy1_status;
int i, sleep_us = 100;
bool check_both = (priv->pcie30_phymode == PHY_MODE_PCIE_AGGREGATION);
ret = regmap_read_poll_timeout(priv->phy_grf,
RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
reg, RK3588_SRAM_INIT_DONE(reg),
100, RK_PCIE_SRAM_INIT_TIMEOUT);
if (priv->pcie30_phymode == PHY_MODE_PCIE_AGGREGATION) {
ret |= regmap_read_poll_timeout(priv->phy_grf,
RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
reg, RK3588_SRAM_INIT_DONE(reg),
100, RK_PCIE_SRAM_INIT_TIMEOUT);
for (i = 0; i < RK_PCIE_SRAM_INIT_TIMEOUT; i += sleep_us) {
regmap_read(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_STATUS1, &phy0_status);
regmap_read(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_STATUS1, &phy1_status);
if (check_both) {
if (RK3588_SRAM_INIT_DONE(phy0_status) && RK3588_SRAM_INIT_DONE(phy1_status))
return 0;
} else {
if (RK3588_SRAM_INIT_DONE(phy0_status) || RK3588_SRAM_INIT_DONE(phy1_status))
return 0;
}
usleep_range(sleep_us, sleep_us + 10);
}
if (ret)
dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
__func__, reg);
pr_err("%s: lock failed p0=0x%x p1=0x%x, check input refclk and power supply\n",
__func__, phy0_status, phy1_status);
return ret;
return -ETIMEDOUT;
}
static const struct rockchip_p3phy_ops rk3588_ops = {

View File

@@ -537,7 +537,7 @@ static int rkvdec2_link_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task)
struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp);
struct rkvdec2_task *task = to_rkvdec2_task(mpp_task);
struct rkvdec_link_dev *link_dec = dec->link_dec;
struct mpp_dma_buffer *table = link_dec->table;
struct mpp_dma_buffer *table = task->table;
struct rkvdec_link_info *info = link_dec->info;
struct rkvdec_link_part *part = info->part_r;
u32 *tb_reg = (u32 *)table->vaddr;

View File

@@ -83,4 +83,6 @@ void rga_dump_memory_parm(struct rga_memory_parm *parm);
void rga_dump_external_buffer(struct rga_external_buffer *buffer);
void rga_dump_req(struct rga_request *request, struct rga_req *req);
unsigned long rga_get_free_pages(gfp_t gfp_mask, unsigned int *order, unsigned long size);
#endif

View File

@@ -925,3 +925,27 @@ void rga_dump_req(struct rga_request *request, struct rga_req *req)
rga_req_log(request, "core_mask = %#x, priority = %d, in_fence = %d(%#x)\n",
req->core, req->priority, req->in_fence_fd, req->in_fence_fd);
}
unsigned long rga_get_free_pages(gfp_t gfp_mask, unsigned int *order, unsigned long size)
{
int cur_order, max_order;
unsigned long pages;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
max_order = MAX_ORDER;
#else
max_order = MAX_PAGE_ORDER;
#endif
cur_order = get_order(size);
if (cur_order > max_order) {
rga_err("Can not alloc pages with order[%d] for viraddr pages, max_order = %d\n",
cur_order, max_order);
return 0;
}
pages = __get_free_pages(gfp_mask, cur_order);
*order = cur_order;
return pages;
}

View File

@@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
#include "rga.h"
#include "rga_debugger.h"

View File

@@ -1497,7 +1497,11 @@ pm_disable:
return ret;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0)
static int rga_drv_remove(struct platform_device *pdev)
#else
static void rga_drv_remove(struct platform_device *pdev)
#endif
{
struct rga_scheduler_t *scheduler = NULL;
@@ -1515,7 +1519,9 @@ static int rga_drv_remove(struct platform_device *pdev)
up_write(&rga_drvdata->rwsem);
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0)
return 0;
#endif
}
static void rga_drv_shutdown(struct platform_device *pdev)

View File

@@ -167,28 +167,16 @@ struct rga_mmu_base *rga_mmu_base_init(size_t size)
* malloc pre scale mid buf mmu table:
* size * channel_num * address_size
*/
order = get_order(size * 3 * sizeof(*mmu_base->buf_virtual));
if (order >= MAX_ORDER) {
pr_err("Can not alloc pages with order[%d] for mmu_page_table, max_order = %d\n",
order, MAX_ORDER);
goto err_free_mmu_base;
}
mmu_base->buf_virtual = (uint32_t *) __get_free_pages(GFP_KERNEL | GFP_DMA32, order);
mmu_base->buf_virtual = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32,
&order, size * 3 * sizeof(*mmu_base->buf_virtual));
if (mmu_base->buf_virtual == NULL) {
pr_err("Can not alloc pages for mmu_page_table\n");
goto err_free_mmu_base;
}
mmu_base->buf_order = order;
order = get_order(size * sizeof(*mmu_base->pages));
if (order >= MAX_ORDER) {
pr_err("Can not alloc pages with order[%d] for mmu_base->pages, max_order = %d\n",
order, MAX_ORDER);
goto err_free_buf_virtual;
}
mmu_base->pages = (struct page **)__get_free_pages(GFP_KERNEL | GFP_DMA32, order);
mmu_base->pages = (struct page **)rga_get_free_pages(GFP_KERNEL | GFP_DMA32,
&order, size * sizeof(*mmu_base->pages));
if (mmu_base->pages == NULL) {
pr_err("Can not alloc pages for mmu_base->pages\n");
goto err_free_buf_virtual;

View File

@@ -133,9 +133,12 @@ static int rga_get_user_pages(struct page **pages, unsigned long Memory,
result = get_user_pages_remote(current, current_mm,
Memory << PAGE_SHIFT,
pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL, NULL);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)
result = get_user_pages_remote(current_mm, Memory << PAGE_SHIFT,
pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL, NULL);
#else
result = get_user_pages_remote(current_mm, Memory << PAGE_SHIFT,
pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL);
#endif
if (result > 0 && result >= pageCount) {
@@ -252,14 +255,8 @@ static int rga_alloc_virt_addr(struct rga_virt_addr **virt_addr_p,
}
/* alloc pages and page_table */
order = get_order(count * sizeof(struct page *));
if (order >= MAX_ORDER) {
rga_err("Can not alloc pages with order[%d] for viraddr pages, max_order = %d\n",
order, MAX_ORDER);
return -ENOMEM;
}
pages = (struct page **)__get_free_pages(GFP_KERNEL, order);
pages = (struct page **)rga_get_free_pages(GFP_KERNEL,
&order, count * sizeof(struct page *));
if (pages == NULL) {
rga_err("%s can not alloc pages for viraddr pages\n", __func__);
return -ENOMEM;
@@ -1196,14 +1193,8 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
}
if (job->flags & RGA_JOB_USE_HANDLE) {
order = get_order(page_count * sizeof(uint32_t *));
if (order >= MAX_ORDER) {
rga_job_err(job, "Can not alloc pages with order[%d] for page_table, max_order = %d\n",
order, MAX_ORDER);
return -ENOMEM;
}
page_table = (uint32_t *)__get_free_pages(GFP_KERNEL | GFP_DMA32, order);
page_table = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32,
&order, page_count * sizeof(uint32_t *));
if (page_table == NULL) {
rga_job_err(job, "%s can not alloc pages for page_table, order = %d\n",
__func__, order);
@@ -1261,14 +1252,8 @@ static int rga_mm_set_mmu_base(struct rga_job *job,
}
if (job->flags & RGA_JOB_USE_HANDLE) {
order = get_order(page_count * sizeof(uint32_t *));
if (order >= MAX_ORDER) {
rga_job_err(job, "Can not alloc pages with order[%d] for page_table, max_order = %d\n",
order, MAX_ORDER);
return -ENOMEM;
}
page_table = (uint32_t *)__get_free_pages(GFP_KERNEL | GFP_DMA32, order);
page_table = (uint32_t *)rga_get_free_pages(GFP_KERNEL | GFP_DMA32,
&order, page_count * sizeof(uint32_t *));
if (page_table == NULL) {
rga_job_err(job, "%s can not alloc pages for page_table, order = %d\n",
__func__, order);