Compare commits

...

111 Commits

Author SHA1 Message Date
Ketan Patil
b27a1a79ee video: tegra: nvmap: Avoid double updation of RSS counter
The RSS counter is updated during buffer allocation as well as mmap,
which is leading to double updation. Fix this by decrementing the RSS
counter during page fault while increment it back during unmap flow.

Bug 5222690

Change-Id: I77972185f20d9d710571cc07ae1c5188060bfa1f
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3442670
(cherry picked from commit 1c59063ce7)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3453103
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
2025-09-18 10:19:09 -07:00
Ketan Patil
e488812038 video: tegra: nvmap: Remove use of add_mm_counter
add_mm_counter is not an exported function, so instead use
atomic_long_add_return/percpu_counter_add to directly modify RSS stat
counters.

Bug 5222690

Change-Id: I51a68d932aeb04f96e51a4a3c286ee5c8efc789a
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3446982
(cherry picked from commit 8e1a6b2dd1)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3453099
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Tested-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
2025-09-18 10:19:03 -07:00
Ketan Patil
cfe6242c8c video: tegra: nvmap: Account NvMap memory for OOM Decisions
Account NvMap allocated memory into both RSS and CG tracking to make
efficient OOM kill decisions during memory pressure.

NvMap allocates memory via kernel APIs like alloc_pages, the kernel
memory is not accounted on behalf of process who requests the
allocation. Hence in case OOM, the OOM killer never kills the process
who has allocated memory via NvMap even though this process might be
holding most of the memory.

Solve this issue using following approach:
- Use __GFP_ACCOUNT and __GFP_NORETRY flag
-  __GFP_NORETRY will not let the current allocation flow to go into OOM
path, so that it will never trigger OOM.
- __GFP_ACCOUNT causes the allocation to be accounted to kmemcg. So any
allocation done by NvMap will be definitely accounted to kmemcg and
cgroups can be used to define memory limits.
- Add RSS counting for the process which allocates by NvMap, so that OOM
score for that process will get updated and OOM killer can pick this
process based upon the OOM score.
- Every process that has a reference to NvMap Handle would have the
memory size accounted into its RSS. On releasing the reference to
handle, the RSS would be reduced.

Bug 5222690

Change-Id: I3fa9b76ec9fc8d7f805111cb96e11e2ab1db42ce
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3427871
(cherry picked from commit 2ca91098aa)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3453101
Tested-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-09-18 10:18:41 -07:00
Akhil R
efa698bed8 crypto: tegra: Do not use IV for AES ECB
It may happen that the variable req->iv may have stale values or
zero sized buffer by default and may end up getting used during
encryption/decryption. This in turn may corrupt the results or break
the operation. Ensure not use IV for algorithms like AES ECB where IV
is not expected.

Bug 4883011

Change-Id: I309ad26f99fe54005ff71b270b3b115dc62ac168
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3319062
(cherry picked from commit 4b72ba2c83)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322768
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-03-20 09:43:41 -07:00
Akhil R
e7bf6f1444 crypto: tegra: Reserve keyslots to allocate dynamically
The HW supports only storing 15 keys at a time. This limits the number
of tfms that can work without failutes. Reserve keyslots to solve this
and use the reserved ones during the encryption/decryption operation.
This allow users to have the capability of hardware protected keys
and faster operations if there are limited number of tfms while not
halting the operation if there are more tfms.

Bug 4883011

Change-Id: I220f1e8205dde1f078be6ed4cb09b699b6d5dfa2
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263283
(cherry picked from commit 15d7ca57b1)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322767
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-03-20 09:43:35 -07:00
Akhil R
e228deeef1 crypto: tegra: Use separate buffer setkey
Use a separate buffer for setkey operation. setkey() is called
asynchronous to crypto engine APIs. This causes concurrency issues in
the tegra engine oprations.

Bug 4883011

Change-Id: I1ec7d0a041ee8a0a0bf350d2f3e9915091993034
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263282
(cherry picked from commit 2f3c077115)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322626
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-03-20 09:43:29 -07:00
Brad Griffis
36a712b801 Revert "crypto: tegra: Use separate buffer for each host1x command"
This reverts commit f6c3d49e92.

Reason for revert: Optimize implementation and align with upstream.

Bug 4883011

Change-Id: I32fe35daa30ddb5a272dbeee0c3316134e9ca55b
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3321697
(cherry picked from commit efeb1061bb)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322625
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-03-20 09:43:23 -07:00
Akhil R
087418781c crypto: tegra: Use separate buffer for each host1x command
Allocate separate buffer for each host1x command. The single buffer used
for host1x commands can get corrupted when independent crypto operations
overlap.

Bug 4883011

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I43029364c8e65e5014a5b7068cb45225c039aaf8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3248913
(cherry picked from commit f6c3d49e92)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262770
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
2024-12-17 15:56:55 -08:00
Jon Hunter
fe0a030fee media: camera: Fix build for Linux v6.8+
In Linux v6.8, the 'g_frame_interval' and 's_frame_interval' function
pointers were removed from the 'v4l2_subdev_video_ops' structure and
replaced by 'get_frame_interval' and 'set_frame_interval' that were
added to the 'v4l2_subdev_pad_ops' structure.

This change was previously fixed for the Tegra CSI driver by adding the
necessary conftest changes. A new update to the Tegra Cam V4L2 causes
the build to fail for Linux v6.8+ kernels because of the same issue. Fix
up the Tegra Cam V4L2 driver in the same way as the Tegra CSI driver,
but update the name of the conftest test to indicate that this is
applicable for both the 'get_frame_interval' and 'set_frame_interval'
function pointers.

Bug 4448428
Bug 4807063

Change-Id: Ica47f3aaece0bf81e2adc3c431056ea51b64a893
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3231775
(cherry picked from commit 91416b264c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262768
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-12-17 15:56:23 -08:00
Praveen AC
7ad4c09866 [t23x][camera]: Fix VIDIOC_G/S_PARM v4l2-compliance test fail.
Implemented VIDIOC_G/S_PARM ioctl calls to fix
v4l2-compliance test fail.

Bug 4807063

Change-Id: Ia03b161b5659c710976084f277064a44d10aec15
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3221436
(cherry picked from commit c3b8c1cd3e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262767
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-12-17 15:56:15 -08:00
Akhil R
f41b74b8c3 crypto: tegra: Fix size of buffer allocated
Allocate the buffer based on the request instead of a fixed buffer
length. In operations which may require larger buffer size, a fixed
buffer may fail. Similar patch was added for AES algorithms. Fix the
same for HASH algorithms as well.

Bug 4908156

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: Idd2c1ceae1a85434a5a51154a17dce8c927bb66c
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3234055
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
(cherry picked from commit 3415677f0f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3235205
2024-10-24 08:31:48 -07:00
Ketan Patil
ff0c2e64e9 video: tegra: nvmap: Fix data race between create and destroy client
nvmap uses pid of group_leader task to indicate a client process. During
create_client operation, whenever any client with the same group_leader
pid already exists in clients list of nvmap_device, then nvmap
increments the count field of nvmap_client struct. Otherwise, create a
new nvmap_client. Both of the operations i.e. checking the list for
client and incrementing the counter happen inside lock. On the other
hand, during nvmap_release, first the counter is decremented and checked
if it's zero or not. If it's zero then the lock is taken and client is
removed from client list of nvmap_device. As both the operations i.e.
decrementing the counter value and removing client from list (if the
counter becomes 0) are not happening inside a lock, it's resulting into
the following data race scenario.
1) nvmap_release on existing client process 1
   - decrement client's counter
   - counter value has become zero
   - client is yet to be removed from the dev->clients list
   - context switch happen to __nvmap_create_client as another
namespace/thread with same with same group_leader pid is created.
2) __nvmap_create_client
   - as the client with same pid exists in dev->client list, it
increments counter value to 1, instead of creating a new client struct.
   - context switch happen to nvmap_release from step 1
3) nvmap_release
   - It calls destroy_client and remove the client from dev->client
list.
   - Completes rest of the operations in destroy_client and returns.
   - Context switch to remaining operations from step 2
4) nvmap_release
   - Now, when the nvmap_release will be called for the thread/namespace
which was created in step 2, then list_del operation would fail as the
client struct was already removed from dev->client list.

Fix the above issue by doing both operations i.e. decrementing the
counter value and removing the client struct from dev->client list in a
single lock.

Bug 4829958

Change-Id: I87ebbcb45b18114d0ec75520443bee010f88d59e
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3209794
(cherry picked from commit cc74d1fe1b)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3210845
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-09-10 17:54:27 -07:00
Vishwaroop A
8b2781df07 drivers: spi: update misc register programming.
Update misc register programming.

Bug 4752858

Change-Id: If328518f4a2d31ed83aa94e6ed40e99bc08bf6b1
Signed-off-by: Vishwaroop A <va@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3202398
Reviewed-by: svcacv <svcacv@nvidia.com>
Tested-by: Kevin Fu <chunhuaif@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-09-05 05:24:01 -07:00
Shobek Attupurath
34b2a9887a rtl8822ce: Disable debug prints
Issue - Driver debug prints are enabled causing spew in dmesg

Fix - Reduce log level to 0

Bug 4829658

Change-Id: If6aef4d7b17a44e2fa6901e60604828ed5a8c065
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3202802
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-09-03 21:39:10 -07:00
Bitan Biswas
f3b12ead83 crypto: fix crypto_engine_ctx build error
struct crypto_engine_ctx removed in k6.6 hence use
conftest helper based macro to select updated data types

Bug 4346767

Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Change-Id: Iaf565c4ef74fdd87ea0020b369bc3d882d32326e
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3176823
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
(cherry picked from commit cba663d0db)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3196067
2024-08-26 04:08:59 -07:00
Akhil R
f73208daa3 crypto: tegra: Fix size of buffer allocated
Allocate the buffer based on the request instead of a fixed buffer
length. In operations which may require larger buffer size, a fixed
buffer may fail.

Bug 4798264

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I0eac3e04aed89b07f5674cf69828d3ac0801a6c7
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3194058
(cherry picked from commit 01bdbd8a6679a5e31d0a06e5f21cd20cf0600ba6)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3199308
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-08-24 15:24:02 -07:00
Shobek Attupurath
b4250020cf rtl8822ce: Add Nvidia changes on v5.14.0.4-250
1. Add custom roam parameters
2. Add path for power file
3. Add source tree path for Makefile
4. Add section in Makefile for TEGRA platform
5. Update permissions from 0755 to 0644 for files
6. Move roaming debug prints to RTW_INFO
7. Remove pr_debug redefinition
8. Move LOG_LEVEL to 0

Bug 4556940

Change-Id: Ic6de0172e6e866c6e81fa84685a929b60051ffce
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3140409
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
2024-08-21 16:54:07 -07:00
Shobek Attupurath
0eb7d29c91 rtl8822ce: Add driver version v5.14.0.4-250
Release Notes:
1. Add extra queue to handle EAPOL
    Mark include/autoconf.h RTW_EAPOL_QUEUE to disable it
2. Use xmit_ext queue to TX eapol packet
3. Flush roam_buf_pkt after roaming is fail
4. Do NOT roam if previous roam does NOT finish
5. Report to WPS after all roam retries are failed
6. Support 11K beacon report fragmentation
7. Fix compile error on Kernel 5.19.2

Bug 4556940

Change-Id: I578ec882584d5d18dfbb8b5a5513ddbe733367b9
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3140393
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
2024-08-21 16:54:03 -07:00
Sandipan Patra
a863247bfc driver: platform: tegra: remove pfn_valid usage
Use ioremap after phys_to_virt to get the kernel accessible
read/write memory region. Hence remove pfn_valid check.

Bug 3804913

Change-Id: I798ea0a47133b4eb4a8f1d23585ce48ae4f1e53e
Signed-off-by: Sandipan Patra <spatra@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195495
Reviewed-by: Preetham Chandru R <pchandru@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-08-21 00:54:27 -07:00
Akhil R
80c7d7a67b crypto: tegra: Align with upstream
Fix the known bugs in the SE driver and align the driver with the
upstream version

Bug 4488964

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I6efa471b6efcd161d36167a0784185f3e0266d7c
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3124250
(cherry picked from commit abb0a027b2)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3196063
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-08-20 02:24:41 -07:00
Sandipan Patra
0d1196a9f2 driver: platform: tegra: handle error path
Handle error path properly so that the device can handle subsequent
insmod/rmmod of tegra-bootloader-debug.ko

Bug 3804913

Change-Id: I9a0f214a7fc0307352b40615b04a6372a7f43bc8
Signed-off-by: Sandipan Patra <spatra@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195493
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-08-19 08:39:10 -07:00
Praveen AC
7373b7bc0b camera: Fix v4l2-compliance test fails
Fix following test cases:
1.test invalid ioctls test
2.test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF

return proper error value from the driver.

Bug 4587577

Change-Id: Iee1114d4cc74ba27c3bef30190f936f69cbc32ac
Signed-off-by: Praveen AC <pac@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3191238
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-08-17 01:38:59 -07:00
snchen
06c838e81c vi5: camera: move allow_signal to dequeue
move allow_signal(SIGINT) to tegra_channel_kthread_capture_dequeue
to allow user space to break capture thread while capture timeout
override to infinite(-1).

bug 4737219

Change-Id: Ic166c5e48d67e15e1bf26bb3abc9d2f9070f7cf4
Signed-off-by: snchen <snchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3182589
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-08-08 00:09:06 -07:00
Jon Hunter
d4a130e720 scripts: conftest: Fix of_property_for_each_u32 test
The conftest test for detecting the number of arguments for the macro
of_property_for_each_u32() is not working as expected because the header
file for the function pr_info() is not included. Fix and simplify this
by removing pr_info() altogether.

Bug 4749580

Change-Id: I42eb91e1cb647b44f3e0c87f1c56fe5e29a56b34
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3186544
(cherry picked from commit da1b446b64)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3188144
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-08-05 08:54:06 -07:00
Jason Mei
ae8e0690e8 host1x-fence: Remove callback and cancel fence
Issue: [k6.8/l4t/] ap_compute_level1_test is failing in GVS
[ 2720.076010] Call trace:
[ 2720.078520]  kmalloc_trace+0xa8/0x270
[ 2720.082275]  0xffffcb8bdce9f9ac
[ 2720.085497]  __arm64_sys_ioctl+0xa8/0x100
[ 2720.089618]  invoke_syscall+0x44/0x128
[ 2720.093466]  el0_svc_common.constprop.0+0x3c/0xec
[ 2720.098290]  do_el0_svc+0x1c/0x2c
[ 2720.101690]  el0_svc+0x30/0xbc
[ 2720.104831]  el0t_64_sync_handler+0x13c/0x158
[ 2720.109304]  el0t_64_sync+0x16c/0x170
[ 2720.113060] Code: aa1403e1 f9405e64 8b000282 dac00c42 (f8606a95)
[ 2720.119320] ---[ end trace 0000000000000000 ]---
[ 2720.212951] Kernel panic - not syncing: Oops: Fatal exception

Fix: Remove callback and cancel fence in poll

Bug 4779016

Change-Id: I49f2a67cdcb7e8882664fa203fcc90adf8c9341a
Signed-off-by: Jason Mei <jianjunm@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3187581
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-08-05 02:54:53 -07:00
Jon Hunter
3a4fed381d misc: mods: Disable MODS for Linux v6.11
In Linux v6.11, the 'platform_driver' structure 'remove' callback was
updated to return void instead of 'int'. This breaks the build for
various MODS drivers and so disable these for Linux v6.11 and greater.

Bug 4749580

Change-Id: Ie76da62af1b9645d24964165fd656b21ea67f78c
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3183067
(cherry picked from commit 19c93284bd)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185780
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-08-01 15:09:22 -07:00
Jon Hunter
d19626ceee drivers: Fix bus->match for Linux v6.11
In Linux v6.11, the 'bus_type' structure match() callback was updated to
make its 'drv' argument constant. Add a conftest test to detect this and
update the relevant drivers according to fix building them for Linux
v6.11.

Bug 4749580

Change-Id: I895d97241a7357074bb34b8e7a5bdfa2e31d5ca5
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3183068
(cherry picked from commit fc171fe539)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185781
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-08-01 10:24:56 -07:00
Jon Hunter
42263f1dfe drivers: pva: Fix build for Linux v6.11
In Linux v6.11, commit 1a251f52cfdc ("minmax: make generic MIN() and
MAX() macros available everywhere") causes the PVA driver build to fail
with the following error:

 include/uapi/linux/nvpva_ioctl.h:601: error: "MAX" redefined [-Werror]
 601 | #define MAX(a, b) ((a) > (b) ? (a) : (b))

Fix this by add guards around the definition of 'MAX' in the
nvpva_ioctl.h file.

Bug 4749580

Change-Id: If7960e0617e659f4e264b1e638e9f8c98a027a73
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3184093
(cherry picked from commit d8bc5883f3)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185779
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-08-01 10:24:45 -07:00
Jon Hunter
1ae45fbaa7 hwmon: f75308: Fix build for Linux v6.11
The macro of_property_for_each_u32() was updated for Linux v6.11 to
remove two of the arguments that were only used internally in the macro
and do not need to be passed. Add a test to conftest to detect the
version of the of_property_for_each_u32() that is present in the kernel
and fix the f75308 driver accordingly.

Bug 4749580

Change-Id: If787a40d0af49989d93d9563dd6a84e906cb5209
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3184092
(cherry picked from commit 8f1e881a2f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185778
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-08-01 10:24:40 -07:00
Jon Hunter
97a8781a1b block: virtual-storage: Disable for Linux v6.11
The Tegra virtual storage driver fails to build for Linux v6.11 because
of the following issues:

 1. The functions blk_queue_logical_block_size(),
    blk_queue_physical_block_size() and blk_queue_max_discard_sectors()
    have been removed.
 2. The function blk_queue_write_cache() has too many arguments for
    Linux v6.11.
 3. The flag QUEUE_FLAG_NONROT is not defined for Linux v6.11.

Disable this driver for Linux v6.11 until this driver is fixed.

Bug 4311184
Bug 4749580

Change-Id: I56f811d6ee29dd0025a5dc199ae84e3fc0f37b21
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185049
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-08-01 10:24:31 -07:00
Jon Hunter
8f4ee697f9 ASoC: tegra: Fix redefinition error for Linux v6.11
In Linux v6.11, commit 1a251f52cfdc ("minmax: make generic MIN() and
MAX() macros available everywhere") causes the Tegra ASoC Utils driver
build to fail with the following error:

 sound/soc/tegra/tegra_asoc_utils.c:18: error: "MAX" redefined [-Werror]
  18 | #define MAX(X, Y) ((X > Y) ? (X) : (Y))

Fix this by add guards around the definition of 'MAX' in the
Tegra ASoC Utils file.

Bug 4749580

Change-Id: I63df434627e6ee7ab16d865c296b07b91405fdfd
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3185143
Reviewed-by: Sameer Pujar <spujar@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-07-31 01:24:12 -07:00
Jon Hunter
8fbb56adb6 ASoC: tegra: Fix build for Linux v6.11
For Linux v6.11, the 'tx_slot' and 'rx_slot' arguments for the ASoC
set_channel_map() function were made constant. Add a test to conftest to
check for this and update the Tegra210 ADX and AMX driver accordingly.

Bug 4749580

Change-Id: I584d721ee46ae0af6312df4641fc4bbdbc1714f0
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3184824
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-07-30 05:54:11 -07:00
Jon Hunter
55b09a913f nvmap: Implement nvmap_page_mapcount()
Upstream commit cdd9a571b7d8 ("fs/proc: move page_mapcount() to
fs/proc/internal.h") made page_mapcount() an internal function for Linux
v6.11. This function is used by the NVMAP driver and so implement this
function in the NVMAP driver directly instead. Note that newer kernels
implement folio_entire_mapcount() for compound page counts where as
older kernels use compound_mapcount(). Use conftest to detect which of
these functions is present in the kernel.

Bug 4749580

Change-Id: I6504448727d6b3e9f2caa8581a66aad464ae2426
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3180097
(cherry picked from commit f327656ea3)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3183926
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ketan Patil <ketanp@nvidia.com>
2024-07-30 01:54:01 -07:00
Mikko Perttunen
386aa2f039 gpu: host1x: Increase pushbuffer slots to 1023
To avoid CDMA waiting when many jobs are queued, double
pushbuffer size.

Bug 4386806

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: I80841fdec96ba3c203c070bcc1f5c7fd1c3a7cbc
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3032829
(cherry picked from commit 281f74c323)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3152866
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Santosh BS <santoshb@nvidia.com>
2024-07-29 08:54:06 -07:00
Ankur Pawar
3c87c18fcf media: i2c: fix IMX390 SDR mode corruption
Bottom two lines in IMX390 SDR mode are completely
black. Fix issue in SDR mode table. Also change the
image resolution to 1936x1096.

Last two line are removed by disabling SMPG(Safety Mechanism Pattern Generator) using register 0x2DFC, 0x2E24.

Bug 4505240

Change-Id: I92047ea83d20f1b4ca4e712718051a9c6e69cfcb
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147214
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-07-25 09:54:13 -07:00
jianjunm
84de937501 host1x-fence:Free the kzalloc mem
Issue: ioctl call host1x-fence cause memory leak
The kmemleak log shows:
  unreferenced object 0xffff0001ac305500 (size 128):
  comm "deepstream-test", pid 4370, jiffies 4295045195 (age 133.220s)
  hex dump (first 32 bytes):
    00 01 00 00 00 00 ad de 22 01 00 00 00 00 ad de  ........".......
    28 aa 67 bf 00 00 ff ff 00 7c ed 1f 01 00 ff ff  (.g......|......
  backtrace:
    [<000000000d2d94dc>] kmem_cache_alloc_trace+0x2bc/0x3d0
    [<000000006a957993>] dev_file_ioctl+0x588/0x86c [host1x_fence]
    [<000000003528f698>] __arm64_sys_ioctl+0xb4/0x100
    [<00000000d39dabe0>] invoke_syscall+0x5c/0x130
    [<00000000aee791e3>] el0_svc_common.constprop.0+0x64/0x110
    [<0000000050bcd11c>] do_el0_svc+0x74/0xa0
    [<00000000530f0cc4>] el0_svc+0x28/0x80
    [<00000000b6d076a3>] el0t_64_sync_handler+0xa4/0x130
    [<000000008943bb27>] el0t_64_sync+0x1a4/0x1a8

Fix: release the kzalloc memory after finish using

Bug 4738188

Change-Id: Ifeb316a2a52432f0199ad22d3de277b123acda24
Signed-off-by: jianjunm <jianjunm@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3175899
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
2024-07-23 05:39:06 -07:00
Jon Hunter
85be13c709 net: nvethernet: Fix build for Linux v6.11
In Linux v6.11, the structure 'kernel_ethtool_ts_info' was added as a
copy of the existing 'ethtool_ts_info' for the kernel and the various
kernel functions were updated to use the new structure. This broke the
build for the nvethernet driver, so add a test to the conftest script to
detect the presence of this new strucutue and update the nvethernet
driver accordingly.

Bug 4749580

Change-Id: I2c5daa0132edee8c98eec3a66e19144484325ab0
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3176868
(cherry picked from commit 9d6283ca4f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3178809
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
2024-07-22 02:26:53 -07:00
Jon Hunter
913e17563b media: camera: Use of_pwm_xlate_with_flags()
In Linux v6.11, commit d6f66e292676 ("pwm: Make pwm_request_from_chip()
private to the core") made the function pwm_request_from_chip() a
private function to the PWM core driver. This function is used by both
the CDI and ISC camera drivers and so these driver no longer build
against Linux v6.11.

Fix this by updating the CDI and ISC drivers to use the function
of_pwm_xlate_with_flags() which has been supported since Linux v3.8.
This function internally calls pwm_request_from_chip() and configures
the pwm->args.period parameter and is therefore, equivalent to the
existing code.

Bug 4749580

Change-Id: Id1381ebc08730aaaa6c3591d90bcc4cc95a6c235
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3176063
(cherry picked from commit f308807197)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3178155
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-07-19 09:09:06 -07:00
snchen
f2d3ec994c camera: add SBGGR12 color format
Add SBGGR12 color format to support bayer bggr12

bug 4575548

Change-Id: Ic59b6bc33e67da7f94e2a6805a18971423036e74
Signed-off-by: snchen <snchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3173804
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Amit Purwar <apurwar@nvidia.com>
Reviewed-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-by: Praveen AC <pac@nvidia.com>
2024-07-16 04:40:16 -07:00
snchen
20374db85d vi5: camera: add ovrride capture timeout control
add CID to override the capture timeout.

bug 4737219

Change-Id: I6df8e760ce8051054ba34a8b85b00bb237f9cd98
Signed-off-by: snchen <snchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3173821
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-07-15 01:09:31 -07:00
Jason Mei
bd0a8befee nvethernet:Fix cbb error when ifconfig down
Issue:  CBB bus error when running ifconfig down
	on the nvethernet interface.

Fix:    All MDIO interfaces must be disabled
	before resetting the MAC. The MDIO was
	accessed by the MAC.

Bug 4714627

Change-Id: Ib75cfae70b13093cc574cd0cd07334cc03468ad7
Signed-off-by: Jason Mei <jianjunm@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3165268
Tested-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-07-12 16:24:19 -07:00
Jon Hunter
118cd4e0a6 media: camera: Fix crash in sensor drivers
When CONFIG_V4L2_ASYNC is not enabled and CONFIG_DEBUG_LIST is enabled
then the following kernel panic is observed ...

 imx219: probe of 9-0010 failed with error -524
 list_add corruption. next->prev should be prev (ffffb2b2e95dad78),
  but was 0000000000000000. (next=ffff000088baf508).
 ------------[ cut here ]------------
 kernel BUG at lib/list_debug.c:23!
 Internal error: Oops - BUG: 00000000f2000800 [#1] SMP

If CONFIG_V4L2_ASYNC is not enabled in the kernel, then the function
tegracam_v4l2subdev_register() will return -ENOTSUPP and this will cause
the probe of the sensor drivers to fail. Although failing to probe the
driver is expected in this case, it is not expected that this will
trigger a kernel panic if CONFIG_DEBUG_LIST is enabled. The panic is
caused because tegracam_device_unregister() is not being called in the
exit path of the probe function when tegracam_v4l2subdev_register()
returns an error.

Bug 4704110

Change-Id: I4875a31e55c24b5ab0932a683f16a7a74695a6b6
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3162389
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
2024-07-11 09:08:59 -07:00
Laxman Dewangan
87c78ad125 pci: Port pci-epf-tegra-vnet to support 5.14.0
Most of the code in the file pci-epf-tegra-vnet.c is written
to support the linux kernel version 5.14.x (x != 0), all minor
version above 0.
Make the condition of linux version check such that 5.14.0 is
also part of 5.14.x i.e. (5.14).

Jira HOSTX-5375

Change-Id: Ib3d7ca619497761b8bc77796c9fe0f59c2ab9cf8
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3166767
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3172802
Reviewed-by: Jason Mei <jianjunm@nvidia.com>
Tested-by: Jason Mei <jianjunm@nvidia.com>
2024-07-10 23:54:26 -07:00
Jon Hunter
408ef72fb9 net: realtek: Add option to disable drivers
The RealTek drivers do not build against all Linux distributions because
some Linux distributions have back-ported upstream changes and so the
KERNEL_VERSION checks in the driver do not work for these distributions.

Add compilation flags for these drivers so that we can skip the building
of these drivers for certain Linux distributions.

Please note that the RealTek drivers build fine against Linux v5.14 and
so we should not prevent these driver being built against all Linux
v5.14 kernels.

Bug 4729493

Change-Id: I004d61a884c6f01b4629de56ecc17b55d4fa2cd1
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3171274
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-07-09 04:39:09 -07:00
Jon Hunter
537492a880 trace: Fix build for Linux v6.10
In Linux v6.10, the __assign_str() macro was updated to remove the 2nd
argument. Add a test to the conftest script to detect this and update
the various trace header files as necessary.

Bug 4593750

Change-Id: I495e78658249baa84cca5b864f4e172c1f3f0838
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3152310
(cherry picked from commit 083d7038d1)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3170281
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-07-08 17:54:00 -07:00
Revanth Kumar Uppala
d99dede530 bt: realtek: Fix potential buffer overflow in cfg_list_item struct
The `cfg_list_item` struct previously defined the `data` array with a zero-length,
which can lead to buffer overflow issues detected by the `fortify_memcpy_chk` function.
So change the zero-length array to a flexible array length.

Bug 4701669

Change-Id: I3c4575efbab681fa8b6039793c410b23c4179106
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3159595
(cherry picked from commit 6f80c397ed)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3166006
Tested-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-07-02 06:39:24 -07:00
Laxman Dewangan
df9e50c808 rtcpu: Port IVC bus driver to use iosys-map utils
The IVC driver in core kernel has been changed to accept
VADDR via iosys_map structure. Use the proper iosys map
utils to pass address when doing the tegra_ivc_init().

Bug 4346767

Change-Id: I416f6fbbea7605da9ae729e2076d10fb6360525d
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3039534
(cherry picked from commit 0679fc19d6)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3161024
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Paritosh Dixit <paritoshd@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-27 04:24:04 -07:00
Revanth Kumar Uppala
a1658e5ab7 r8126: Enable support for RSS
Enable support for Receive Side Scaling (RSS)
in Makefile

Bug 4478230

Change-Id: Iafb026ba3b9b152ea7e44933562093144bfcf062
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3159352
(cherry picked from commit ee37ee732d)
Reviewed-by: Sandipan Patra <spatra@nvidia.com>
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3159475
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 08:39:01 -07:00
Revanth Kumar Uppala
523d81ebd5 ethernet: Add dummy driver for r8126
r8126 driver build is disabled on K6.10 and later. This is
causing the packaging failure where module is not available.

Add dummy driver when real driver is not available to make
packaging success.

Bug 4478230

Change-Id: I6ceef7f92863499c58edaf4ddd19ae65b12a2a00
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158781
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 01:12:49 -07:00
Revanth Kumar Uppala
cb5d91e562 r8126: Add r8126 driver version 10.013.00-NAPI-PTP
Add support for r8126 ethernet driverversion 10.013.00-NAPI-PTP
which adds support for PTP and supports till K6.9

Bug 4478230

Change-Id: I381d3689a188e5d365ff89092a98023eeaa2a095
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158780
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-06-19 01:12:44 -07:00
Revanth Kumar Uppala
36b50b7f27 ethernet: Add dummy driver for r8126
r8126 driver build is disabled on K6.9 and later. This is
causing the packaging failure where module is not available.

Add dummy driver when real driver is not available to make
packaging success.

Bug 4478230

Change-Id: I1b83fe1c3f30a9f825631650ca2520d720ef07c6
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3144344
(cherry picked from commit 4c39ed9cb5)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158779
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 01:12:39 -07:00
Revanth Kumar Uppala
98c8d2f1ab r8126: Change file permissions of source files
Remove executable permissions for source files

Bug 4478230

Change-Id: I2bf56e5abac7da957890ac73b7fd00656c8b7063
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3139856
(cherry picked from commit a1c548df68)
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158766
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 01:12:34 -07:00
Revanth Kumar Uppala
eb9eb329cb r8126: Add r8126 driver version 10.013.00
Add support for r8126 ethernet driverversion 10.013.00 which supports
till K6.4

Bug 4478230

Change-Id: I1fdac264355ca639d992825fd6e0404d9d075272
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3095406
(cherry picked from commit 33839a5be8)
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158765
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 01:12:29 -07:00
Laxman Dewangan
f65ba6483d ethernet: Add dummy driver for r8168
r8168 driver build is disabled on K6.9 and later. This is
causing the packaging failure where module is not available.

Add dummy driver when real driver is not available to make
packaging success.

bug 4628651

Change-Id: I8ade511488fab856f63e84c1ee51986286b2fa2d
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3138401
(cherry picked from commit 316baa6776)
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158764
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-19 01:12:24 -07:00
Jason Mei
e2bb52def5 PCI: EPF: tvnet: disable the edma interrupt
1. Disable the corresponding PCIe EP controller
   EDMA interrupt.
2. Disable IP checksum to improve performance
   since the PCIe link is reliable.
3. DMA unmap matches the map size.
4. Adjust the SKB buffer link list handle.

Bug 4704944

Signed-off-by: Jason Mei <jianjunm@nvidia.com>
Change-Id: I05f76fa60e3533c2dd01e53ed17664d6898fcffd
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3158126
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Nagarjuna Kristam <nkristam@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-06-18 22:39:00 -07:00
Revanth Kumar Uppala
f870a5f9fc nvethernet: macsec: Add module param for macsec.
Add module parameter to enable/disable macsec.

By default macsec will be enabled and it can be disabled
with help of module parameter "macsec_enable"

Bug 4640382

Change-Id: I3b6ffde52a73760cd65f02abe472c3133996b698
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3156387
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-06-17 03:57:32 -07:00
Mikko Perttunen
490c984662 gpu: host1x: Handle CDMA wraparound when debug printing
During channel debug information dump, when printing CDMA
opcodes, the circular nature of the CDMA pushbuffer wasn't being
taken into account, sometimes accessing past the end. Change
the printing to take this into account.

Bug 4398831
Bug 4386806

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: I3a24da2c310e9414882f7cabbbda5158b6da00a2
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3033461
(cherry picked from commit 58568987a6e9733e3113b927c6fce454778b3a4d)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3155731
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Johnny Liu <johnliu@nvidia.com>
Reviewed-by: Johnny Liu <johnliu@nvidia.com>
2024-06-12 21:24:07 -07:00
Revanth Kumar Uppala
928bbd8792 r8168: Replace kernel version checks with conftest
Use conftest instead of version checks for api changes
across the kernels.

Bug 4471899

Change-Id: Ia0750eb8e4d634c0a6ed71b6eb64857cddaf467f
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3134835
(cherry picked from commit dd4ca5aab9)
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147967
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-12 01:09:46 -07:00
Revanth Kumar Uppala
954d58f2bc r8168: Disable 10M EEE
- This disables 10M EEE for r8168 driver

Bug 4205197
Bug 4652606

Change-Id: I804b0d53460d19d8ed0b692b7327210634e2a111
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123376
(cherry picked from commit 6b62a514a3)
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147912
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-12 01:09:41 -07:00
Revanth Kumar Uppala
91baac051e r8168: Fix -20C 10mbps failure in Mods test
Issue:
Ethernet mplan stability tests at -20C for 10Mbps fails with rate 15%
Basically the GPHY 10M power saving includes the below parameters,
clock speed down, pll off and reference voltage off.
During debugging it was found that enable/disable pll circuit
frequently when in 10M low data traffic (such as idle mode) may have
a corner case and plays a part in this issue repro.

Fix:
So plloff saving function should be disable (do not have to open it) for nvidia -20C mplan test case.

Bug 3946623
Bug 4652606

Change-Id: Ifabe9e26e840537520d66acca106b37d3c285722
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123359
(cherry picked from commit 20dbe0996b)
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147911
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-12 01:09:36 -07:00
Revanth Kumar Uppala
6d4ef6154e r8168: Change file permissions of source files
Remove executable permissions for source files

Bug 4471899
Bug 4652606

Change-Id: I4d259b03014a8853b9baf0d04265ad521fefddb9
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123346
(cherry picked from commit ae13276f5d)
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147910
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-12 01:09:31 -07:00
Revanth Kumar Uppala
4643e350da r8168: update driver to 8.053.00
- Update realtek r8168 driver version to 8.053.00
- This update adds support till K6.8

Bug 4471899
Bug 4652606

Change-Id: I77734753b8ad9ca108afccda609d29ea73c848f5
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123343
(cherry picked from commit 7086a36e68)
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3147909
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-12 01:09:26 -07:00
Jon Hunter
b4cc53aa67 media: camera: Add missing conftest.h
The camera VI driver was recently updated to fix the build for Linux
v6.10, but the change that fixed the build did not add the 'conftest.h'
header file which is needed. Add this header file to fix building the
driver for Linux v6.10.

Bug 4593750

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Change-Id: I11fdab89a1cb69552fbafbf4b4358561b71cac13
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3150516
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-04 09:39:29 -07:00
Jon Hunter
9cb00122ac media: i2c: Fix build for Linux v6.1+
The IMX390 driver was recently updated and this broke building the
driver for Linux v6.1+ kernels. Revert the specific changes that broke
the build and update the max929x driver so that it can also be built for
Linux v6.1+ kernels.

Finally, replace 'gpio_cansleep' with 'gpiod_cansleep' because
'gpio_cansleep' was removed in Linux v6.5. This also aligns with the
other camera drivers that use 'gpiod_cansleep' instead of
gpio_cansleep'.

Bug 4505240

Change-Id: I46960bca1e1e4aeff9bd9fdaed8b2db2be104b5b
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3149880
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-06-04 07:24:28 -07:00
Ankur Pawar
adc35280cb media: i2c: enable IMX390 WDR mode
Enable WDR(wide dynamic range) mode for IMX390.
The following modification and addition are done:
1 Add WDR mode table
2 Restructure IMX390 driver for WDR gain and framerate
3 Use common driver to configure serializer(max9295) and
  deserializer(max9296)

Bug 4505240

Change-Id: I52fc3f03a66fe4e2446d7b41f409ed4154c42f02
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3105249
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: Shubham Chandra <shubhamc@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Praveen AC <pac@nvidia.com>
2024-05-30 05:39:35 -07:00
spatki
517660e465 tegra: tsec: port init_comms property to oot tree
This change ports the init_comms property handling to oot version
of the tsec driver.

Bug 4669447

Change-Id: Ifa0468dfbbd16b362622f50e49f4fbd076454c48
Signed-off-by: spatki <spatki@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3144129
Reviewed-by: Nikesh Oswal <noswal@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-05-30 01:13:15 -07:00
Nikesh Oswal
09b7b63ec4 video: tsec: Set tsec state before power_on/off
Set s_tsec_state before calling tsec_plat_poweron
as it enables irq and can context switch to the irq
handler which needs s_tsec_state set appropriately

Bug 4437491

Change-Id: I1f48713329b9315376fe926d1e8b33686d05d035
Signed-off-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3145973
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-05-30 01:13:10 -07:00
Nikesh Oswal
fa9c7418dc video: tsec: add support to reboot tsec fw with context
Add support to shutdown tsec firmware by saving the context info
first so that same can be used when rebooting the firmware.

Also use the DO_IPC_OVER_GSC_CO flag only to decide if commands and
messages are sent over GSC_CO or EMEM. Larger buffers will still be
allocated in GSC_CO and pointers to it can be embedded in commands
and messages.

https://confluence.nvidia.com/display/PSS/Reboot+HDCP2X+FW+with+Context+Information

Bug 4437491

Change-Id: Ibeebe98a30db04f1b4b1a28c06ba359ff3a8d85d
Signed-off-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3117020
Reviewed-by: Byungkuk Seo <bseo@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3145972
2024-05-30 01:13:05 -07:00
Jon Hunter
cb70a7e245 net: nvethernet: Fix support for Linux v6.9
When nvethernet was updated to support Linux v6.9 kernels, the code that
checks if the variable 'eee_req->advertised' is zero or non-zero was not
updated correctly. For Linux v6.9, the variable 'eee_req->advertised' is
a bitmask and so cannot be checked directly to see if it is zero or
non-zero. Building the nvethernet driver with the flag '-Werror=address'
exposed this issue. Fix this by using the 'linkmode_empty()' function to
determine if 'eee_req->advertised' is zero or non-zero for Linux v6.9
kernels.

Bug 4471899
Bug 4662166

Change-Id: Id4080d62006226648cd398dc8652578c74dd8158
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3146810
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-05-29 09:24:33 -07:00
Praveen AC
716ec492d8 cam_cdi_tsc: Fix Fsync IOCTL fail sometimes
Make sure tsc is stopped during device close, when the app
is failed to send stop IOCTL for tsc generator.Hence, it avoids
inconsistency in starting the External Fsync trigger.

Bug 4220418

Change-Id: I13286d42a62c85cb52e0d1eabf714865e8fe6956
Signed-off-by: Praveen AC <pac@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3129384
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Shubham Chandra <shubhamc@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
2024-05-24 09:54:30 -07:00
Jon Hunter
5e0562c90d media: virtual-i2c-mux: Fix build for Linux v6.10
In Linux v6.10, the 'class' argument was removed from the
i2c_mux_add_adapter() function. Add a test to conftest to detect the
correct number of arguments for i2c_mux_add_adapter() and update the
virtual-i2c-mux driver accordingly to fix the build for Linux v6.10.

Bug 4593750

Change-Id: I7333a511b487b7c2f2fa0ce7c34f2df5f061fbe4
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142398
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-05-24 07:40:09 -07:00
Jon Hunter
1b72d87cce media: camera: Fix build for Linux v6.10
In Linux v6.10, a pointer to a dynamically allocated 'struct device'
was replaced with a statically allocated 'struct device' in the
'pwm_chip' structure. Update the Tegra camera drivers accordingly to fix
the build for Linux v6.10.

Bug 4593750

Change-Id: I05e15e2a63383ab2f96be6c20e81705de9581869
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123220
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-05-24 07:39:58 -07:00
Jon Hunter
0104837e60 pwm: tachometer: Fix build for Linux v6.10
In Linux v6.10, a pointer to a dynamically allocated 'struct device'
was replaced with a statically allocated 'struct device' in the
'pwm_chip' structure. Update the Tegra PWM Tachometer driver accordingly
to fix the build for Linux v6.10.

Bug 4593750

Change-Id: I9d629746290282b5c1858f8308128d94ff155c49
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123219
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-05-24 07:39:53 -07:00
Jon Hunter
39e07fb02b block: virtual-storage: Allow build for Linux v6.10
The function blk_queue_max_hw_sectors() was removed in Linux v6.10 and
so add a test to conftest to see if this function is present or not to
allow the driver to build. The virtual-storage driver is currently
broken for Linux v5.19+ kernel due to other incompatibilities with these
newer kernels, but has been updated so that it still builds. Therefore,
allow the driver to build for Linux v6.10 while the driver is fixed
properly for these newer kernels.

Bug 4311184
Bug 4593750

Change-Id: Ic4054c87acdf3c77f03ff94fbdde513d84fe229b
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142216
(cherry picked from commit c73cf3c92a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142204
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-05-23 04:11:55 -07:00
Jon Hunter
67b36c62c3 conftest: Fix tests for Linux v6.10
Some of the conftest tests are no longer working with the mainline
kernel and this is causing various build failures for drivers. Upstream
commit a3b00f10da80 ("objpool: enable inlining objpool_push() and
objpool_pop() operations") inlined some code that causes build error to
occur when the tests are built with 'Werror=address-of-packed-member'.

Upstream commit 6f303d60534c ("gcc-9: silence 'address-of-packed-member'
warning") disables the option 'address-of-packed-member' for the kernel
already and so fix these new build failures by disabling this option
for the conftest tests.

Bug 4593750

Change-Id: I37af97079bb7734fcd5bf10384b1afc071613594
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142214
(cherry picked from commit 1a635bb0ea)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142203
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-05-23 04:11:44 -07:00
Jon Hunter
57d240e007 nv-virtio-poc: Add missing header
In Linux v6.10 the nv-virtio-poc driver fails to build and the following
error is seen ...

 drivers/nv-virtio/nv-virtio-console-poc.c:277:13:
  error: implicit declaration of function 'remap_pfn_range';
  did you mean 'vmap_page_range'? [-Werror=implicit-function-declaration]
  277 |         if (remap_pfn_range(vma, vma->vm_start, ipa_pfn,
      |             ^~~~~~~~~~~~~~~
      |             vmap_page_range

Upstream commit 22bcc915ae91 ("kfifo: don't use "proxy" headers")
updated some kernel headers to only 'include what is used' and exposed
that the nv-virtio-poc driver is not explicitly including 'linux/mm.h'.
The function remap_pfn_range() has been defined in 'linux/mm.h' since
Linux v2.6 and so fix this by always including 'linux/mm.h'.

Bug 4593750

Change-Id: Ic43b22ca51bbc16e2085d146d28e40c21206ae2f
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142213
(cherry picked from commit ef52cefdda)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142202
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-05-23 04:11:33 -07:00
Jon Hunter
d259181558 media: camera: Fix v4l2-subdev for Linux v6.10
In Linux v6.10, the v4l2-subdev callbacks 'g_dv_timings' and
's_dv_timings' were moved from the v4l2_subdev_video_ops structure to
the v4l2_subdev_pad_ops structure. Fix the build for Linux v6.10 by
using conftest to determine which structure is used for these callbacks.

Bug 4593750

Change-Id: Ic54e88da22ed7d1da9b6026a45b9c4307637c7b4
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142215
(cherry picked from commit 6255ffef44)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123222
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-05-23 04:11:18 -07:00
Jon Hunter
70cf7e08f3 drivers: Fix missing vmalloc.h for Linux v6.10
Upstream commit 690da22dbfa8 ("asm-generic/io.h: kill vmalloc.h
dependency") removed the vmalloc.h header file from io.h and this breaks
building various drivers with the latest -next kernels. Fix this
by ensuring vmalloc.h is included and in most cases slab is not actually
needed and so remove this where possible. Note that it is fine to make
this change for all current supported kernels.

Bug 4593750

Change-Id: I003d1302bda226d356467e6ede99949b2716940a
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3141984
(cherry picked from commit cb8b9f5a53)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123218
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-05-23 04:11:13 -07:00
Shubhi Garg
f902d95962 drivers: mttcan: fix bus-off restart txfer
[Issue]: CAN freezes/stops to send messages after restart from bus-off state.
Throws following log from kernel: "write: No buffer space available"

[Reason]: When message txfer starts, tx_object (which keeps track of active tx)
gets filled. If CAN goes to bus-off state, txfer remains incomplete for some
messages. In such case, tx_object bits will not get cleared. It will stop
adding more messages in controller RAM.

Along with tx_object, from network layer, there are socket echo buffers.
When CAN is initialized and up on network, netif_start_queue is pushed to start
transmission. When msg txfer starts, socket buffer gets filled and freed only
when txfer completes. During bus-off, since network queue remains ON, all the
queued msgs get filled in socket buffers and does not allow upcoming msgs.
Therefore we see "write: No buffer space available".

[Fix]: Clear tx_object when device goes to bus-off state and stop network queue.
Start network queue again during restart from bus-off.

Bug 4438223

Change-Id: I3cbc6529a90f357372c8b0095bdce4217b133e9b
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3142091
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-05-23 01:54:36 -07:00
Jon Hunter
d95c0d0add thermal: Fix build for Linux v6.10
In Linux v6.10, commit b1ae92dcfa8e ("thermal: core: Make struct
thermal_zone_device definition internal") made the structure
'thermal_zone_device' internal and so the 'devdata' member is no longer
directly accessible. The function thermal_zone_device_priv() was added
in Linux v6.4 for retrieving the 'devdata' and so update the various
thermal drivers to use this function if present.

Bug 4593750

Change-Id: Ic53de9bbd5459c99a3ac26759aa8a966cd775fe5
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123221
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-05-20 07:39:53 -07:00
Praveen AC
32ed59d81b camera:driver: Fix the race condition of setting bypass mode.
Add the check to see if the device is already in use or not,
while calling s_ctrl by multiple user apps on the same video node.

Here ,The "vb2_is_busy" function checks if the queue represented
by the vb2_queue instance is busy by checking if there are any
buffers in the active queue.If there are any buffers in the active queue,
it means that they are currently being processed by the device driver,
and the queue is considered busy.

Bug 3836336

Change-Id: I3d9b215f953c44d55cbbc287fe94c9b793da5955
Signed-off-by: Praveen AC <pac@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2856359
Tested-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-by: Shubham Chandra <shubhamc@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3130744
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
2024-05-08 20:54:46 -07:00
Praveen AC
664ca6964c t23x:tpg:[WAR] Disable gain control to avoid insmod fail.
Disable gain control during tpg probe for t23x to avoid
insmod fail due to "NULL VI channel" when "tpg_gain_ctrl"
is enabled.

Bug 3695458

Change-Id: I15c035eaa2f187b927dc114e88959378f9e52a61
Signed-off-by: Praveen AC <pac@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2828420
Reviewed-by: Nithin Varghese <nvarghese@nvidia.com>
Reviewed-by: Shashank Kumar (shaskumar) <shaskumar@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3130734
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
2024-05-08 20:54:41 -07:00
Jon Hunter
e9b64b08d1 net: nvethernet: Drop adjfreq support
The 'adjfine' method was first introduced in Linux v4.10 by commit
d8d263541913 ("ptp: Introduce a high resolution frequency adjustment
method.") and the 'adjfreq' method was finally removed in Linux v6.2.
Given that 'adjfine' has been supported since Linux v4.10, drop the
deprecated 'adjfreq' method completely to simplify the nvethernet
driver. This fixes build issues for 3rd party kernels that removed the
'adjfreq' method and are older than Linux v6.2.

Bug 3936429

Change-Id: I897bbd3ba92b11d8132c5762d2618b4e82ad44aa
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128119
(cherry picked from commit 46af0c1d24)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3129149
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-02 04:09:19 -07:00
Brad Griffis
b0e75c8874 pci: endpoint: use conftest for pci-epf-tegra-vnet.c
There are several build issues observed in pci-epf-tegra-vnet.c
when building against mainline.

These errors pertain to the following previous commits:

* Use conftest to find if pci_epc_event_ops struct has core_deinit.
* pci: Use conftest to find if probe of pci_epf_driver has ID arg
* misc: nvscic2c-pcie: Drop usage of enum pci_epc_irq_type from Linux 6.8

The pci-epf-tegra-vnet.c is recently added and needs to use those
same new conftest capabilities.

Bug 4346767

Change-Id: I4ea66524513cdc4d62607a061c3f253e2a3cee2b
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128608
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-01 09:56:19 -07:00
Jon Hunter
28f1253514 PCI: Fix endpoint DMA test for Linux v6.9
Building the PCI EPF DMA test driver for Linux v6.9 is failing because
the parameters for the pci_epf_alloc_space() function has been updated
to pass the alignment value via the 'pci_epc_features' structure instead
of passing the value directly.

Instead of hard-coding the endpoint alignment in the EPF DMA test driver
use the 'pcie_epc_get_features()' function to retrieve the endpoint
features structure which has the endpoint alignment.

By using the conftest script to detect the parameters for the
pci_epf_alloc_space() function, we can then pass the appropriate
arguments to the pci_epf_alloc_space() function.

Bug 4471899

Change-Id: Id80259a4c90d6f6ae2132cccbec1a96113d22be7
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3116548
(cherry picked from commit 971680aadb)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128431
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-05-01 09:56:14 -07:00
Laxman Dewangan
83238f4563 pci: Use conftest to find if pci_epc_event_ops struct has core_deinit
Use the conftest to find if the struct pci_epc_event_ops has
core_deinit as callback function. This callback is added
by Nvidia in core kernel.

Bug 4346767

Change-Id: I399197917ac7746ca367f55b9dc4e3a5bd79f073
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3028740
(cherry picked from commit 1e9fc00bc2)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128430
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-01 09:56:09 -07:00
Laxman Dewangan
cbac517483 pcie: Enable core_deinit only when core has implemented it
The core_deinit callback is the Nvidia internal feature
which is not upstreamed yet. Enable the call back from
OOT modules only when core have implemented this callback.

Bug 4374520

Change-Id: Iee2b92b7d70326ea3ce99ce6f6600d27f1e2896b
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3014989
(cherry picked from commit dc69c0b58a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128429
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2024-05-01 09:56:04 -07:00
Brad Griffis
4e35e4b067 drivers: misc: fix implicit function
The following error is observed when PCIE EP is enabled:

drivers/misc/nvscic2c-pcie/stream-extensions.c:766:23: error: implicit
declaration of function ‘platform_get_drvdata’

Include the appropriate file.

Bug 4456727
Bug 4451567

Change-Id: I46aab2fbd01142b9eb3a5a5d665465c115ddeb47
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128579
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-05-01 09:55:59 -07:00
Brad Griffis
a84ded5d3e drivers: misc: fix implicit conversion
The following error is observed when PCIE EP is enabled:

drivers/misc/nvscic2c-pcie/pci-client.c:766:24: error: implicit
conversion from ‘enum peer_cpu_t’ to ‘enum drv_mode_t’
[-Werror=enum-conversion]

Cast the return value to avoid the error.

Bug 4456727
Bug 4451567

Change-Id: Ie11b8231ed65771aaf1f91ff12f9c7bf104f8b2c
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128564
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-01 09:55:54 -07:00
Brad Griffis
222eebeb31 drivers: misc: Fix the argument of iommu_map() for Linux v6.3
There is additional argument added in iommu_map() from Linux v6.3.
Pass the proper argument from the driver who are using this
APIs. Using conftest methods for differentiating whether
additional argument is needed or not.

Bug 4374520

Change-Id: I3d6452cf6c71f495e3b6e3b240b2c2d839aa4b0d
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128547
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-01 09:55:49 -07:00
Laxman Dewangan
6ca4e1e64c misc: nvscic2c-pcie: Drop usage of enum pci_epc_irq_type from Linux 6.8
The enum pci_epc_irq_type is dropped from Linux 6.8 with
commit 74955cb8ccc385 ("PCI: endpoint: Drop PCI_EPC_IRQ_XXX definitions")
Use alternative definition from mainline.

Bug 4448428

Change-Id: Ic248ee2522f171c311ac1086c2792bcf3ad6ed64
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3062520
(cherry picked from commit 932f9757ab)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3128946
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-05-01 09:55:44 -07:00
Brad Griffis
e9cdb435a3 net: ethernet: build realtek ethernet driver only for k5.15
Realtek does not support latest kernels with this driver.  Build it
only for k5.15.

Bug 4471899

Change-Id: Ic60b34f2c3d34d5642d8b568aae61339f6f15349
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3126899
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-05-01 09:55:23 -07:00
Jon Hunter
ac51641cf1 tsec: Fix build with -Werror=old-style-declaration
When the tsec driver is built with the compiler flag
-Werror=old-style-declaration the following error is observed ...

 error: 'static' is not at beginning of declaration
 [-Werror=old-style-declaration]
   393 | const static struct dev_pm_ops tsec_module_pm_ops = {
       | ^~~~~

This is observed with the latest linux-next kernels, but could be
observed with any kernel where this flag is set. Fix this by ensuring
that the 'static' keyword is declared first.

Bug 4593750

Change-Id: Ia635188569d827d361bd36f7be943fbf9f1f0a60
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3126898
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-04-26 17:10:02 -07:00
Shobek Attupurath
0313251d13 rtl8822ce: Initialize spinlock before usage
Issue: Kernel warning print observed from rtl8822ce module
    2024-04-23 21:04:14,547: [   42.507680] Call trace:
    2024-04-23 21:04:14,547: [   42.510201]  dump_backtrace+0xe0/0x140
    2024-04-23 21:04:14,547: [   42.514079]  show_stack+0x1c/0x30
    2024-04-23 21:04:14,547: [   42.517502]  dump_stack_lvl+0x64/0x84
    2024-04-23 21:04:14,648: [   42.521290]  dump_stack+0x14/0x34
    2024-04-23 21:04:14,648: [   42.524703]  spin_dump+0x98/0xb0
    2024-04-23 21:04:14,648: [   42.528030]  do_raw_spin_lock+0x110/0x130
    2024-04-23 21:04:14,648: [   42.532165]  _raw_spin_lock_irqsave+0x34/0xb0
    2024-04-23 21:04:14,648: [   42.536666]  rtl8822ce_reset_bd+0x50/0x334 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.542087]  rtw_hal_irp_reset+0x20/0x28 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.547290]  rtw_halmac_rx_agg_switch+0x728/0x9a8 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.553272]  rtw_halmac_dlfw+0x90/0xc0 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.558281]  rtl8822c_fw_dl+0x4c/0x17c [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.563302]  rtw_hal_fw_dl+0x20/0x34 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.568136]  hal_read_mac_hidden_rpt+0x10c/0x32c [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.574063]  rtl8822c_read_efuse+0x86c/0x1438 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.579726]  rtl8822ce_aspm_config_l1off+0x40c/0x998 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.586009]  rtw_hal_read_chip_info+0xc4/0xec [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.591668]  rtw_pci_primary_adapter_init+0x13c/0xd4c0 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.598134]  rtw_pci_primary_adapter_init+0xd30/0xd4c0 [rtl8822ce]
    2024-04-23 21:04:14,648: [   42.604598]  local_pci_probe+0x44/0xd0
    2024-04-23 21:04:14,648: [   42.608500]  pci_device_probe+0xb0/0x270

Fix: Initialize the lock before using it

Bug 3414392

Change-Id: I82b6f00b4a3599665b1a7194b5785a785d11501a
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123003
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-04-24 08:54:32 -07:00
Revanth Kumar Uppala
8b529ece8f rtl8822ce: Remove pr_debug redefinition
Issue: pr_debug is redfined to printk causing unwanted
       log prints in dmesg

Fix: Remove pr_debug redefintion in rtl8822ce driver

Bug 3844473

Change-Id: I4177f8c3fa245a881cd35c206f8d3caa4b811b32
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3121450
(cherry picked from commit 564ce2a709)
Reviewed-by: Amulya Yarlagadda <ayarlagadda@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3121447
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-04-24 08:54:27 -07:00
Jon Hunter
315ceb951b net: nvethernet: Fix build for Linux v6.9
For Linux v6.9, the structure 'ethtool_eee' was replaced by
'ethtool_keee' and this new structure uses bitmaps for the structure
fields 'supported', 'advertised' and 'lp_advertised' as opposed to
'u32' types.

Add a test to conftest to detect the presence of the new 'ethtool_keee'
structure and update the nvethernet driver to use the various
linkmode_xxx helper functions for accessing the bitmap structure fields.

Bug 4471899

Change-Id: I275becfa665a36ed90e8bc227eaa4122825faa6a
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3110494
(cherry picked from commit 72761b8276)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3111548
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 16:09:35 -07:00
Jon Hunter
044cc6adda nvmap: Fix build for Linux v6.9
Commit c1fa617caeb0 ("tracing: Rework __assign_str() and __string() to
not duplicate getting the string") update the __assign_str() function
and dropped the trailing semi-colon from the definition. This is causing
the NVMAP driver build to fail because of a missing semi-colon on some
of the __assign_str() declarations in the nvmap.h header. Some already
have a semi-colon and so fix this by populating a semi-colon for the
ones that are missing. Note that there is no harm in having multiple
semi-colons for kernels that define __assign_str() already with a
trailing semi-colon.

Bug 4471899

Change-Id: Ic804ca0ce1480f830ec3f6b5636e099b00734857
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
(cherry picked from commit 6b355b554a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3119066
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
2024-04-18 13:57:02 -07:00
Vishwaroop A
51806fef24 drivers: spi: remove spi_master_put() in probe
Currently the spi_master is allocated by devm_spi_alloc_master()
in the spi slave. so there is no need to call spi_master
put again this fixes the probe failure seen in spi slave
driver

Bug 4537830

Signed-off-by: Vishwaroop A <va@nvidia.com>
Change-Id: Ie0ea17c308caade7c0a1f298c7ac4f3b86a38541
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3095347
(cherry picked from commit 3584ef129e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3111547
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:56:57 -07:00
Jon Hunter
6997999d7a spi: Fix build for Linux v6.9
For Linux v6.9 the compatibility layer that existed for transitioning
SPI drivers from using the legacy 'master' based naming to the
'controller' based naming for functions, structures and variables has
been removed. This is causing the various SPI driver build failures.

The compatibility layer was first introduced in Linux v4.13 by commit
8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") and given
that the newer "controller" based naming works for kernels from v4.13,
update the various SPI drivers to use the new naming for all current
supported kernels.

Bug 4471899

Change-Id: I5d9fcc429ab4262eb2827b61eb5aec729059f4b5
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3109504
(cherry picked from commit 4432f3b652)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3111546
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:56:47 -07:00
Jon Hunter
91ee86eced conftest: Fix test for SLAB_MEM_SPREAD
The conftest test for detecting if the definition SLAB_MEM_SPREAD is
present is not working as expected because it is using the 'functions'
type which is intended for only checking if a function is present or
not. Fix this by correcting the type to 'types'.

Bug 4471899

Change-Id: Iba3c9fe70a97793576d9f188d50628acb55f44df
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
(cherry picked from commit b8b92d5d5f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3111545
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:56:26 -07:00
Paritosh Dixit
91e87c9346 net: nvethernet: Fix build for Linux v6.9
In Linux v6.9-rc1, the typedef of skb_frag_t is updated to a new struct
skb_frag. Struct skb_frag does not include bv_offset and bv_page
members. Hence, use functions skb_frag_off and skb_frag_page to get
offset and page respectively. Use of functions skb_frag_off and
skb_frag_page is backward compatible with older kernel versions that
we use.

Bug 4471899

Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Change-Id: I5d14c750c5b4cd28a2abeda95d7c11bf975ef1b8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104114
(cherry picked from commit f451b88fd7)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3108315
Tested-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-04-18 13:56:15 -07:00
Jon Hunter
e351ba75c7 media: camera: Ensure gpio_device_get_chip is present
In Linux v6.7, both gpio_device_find() and gpio_device_get_chip() were
added. However, don't assume that if one is present then so is the other
and so add a test to check if gpio_device_get_chip() is also present.

Bug 4471899

Change-Id: I0c547a52b0f397aef43884ab76d815573e8ed3f8
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3112133
(cherry picked from commit 9458d6b97f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3119068
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:56:10 -07:00
Jon Hunter
5ff50fc9ea media: camera: Fix build for Linux v6.9
In Linux v6.9 the data argument of the function pointer passed to
gpio_device_find() was updated to be a const type. This breaks building
the CDI and ISC drivers for Linux v6.9. Update the test in conftest that
detects the presence of the gpio_device_find() function to perform a
second test to see if the argument for the function pointer is a const
type. Update the drivers that use the gpio_device_find() function
accordingly to fix the build.

Bug 4471899

Change-Id: I562451a401bcaebcf0acf9a7d563cb0ea1d87807
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104559
(cherry picked from commit 037fa78728)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104651
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:56:00 -07:00
Jon Hunter
94090ac30e media: camera: Update conftest for gpio_device_find
When adding conftest tests for detecting if specific functions are
present, it is always better to check if the newly added function is
present versus the function that has been removed. The reason being that
is the newly added function is modified in the future then the conftest
tests can be extended to check for updates to the function.

Therefore, instead of checking if the function gpiochip_find() is
present, which was removed in Linux v6.7, check if the function
gpio_device_find() is present, which replaced gpiochip_find in Linux
v6.7.

Bug 4346767
Bug 4471899

Change-Id: I32bf1c3da32abbf3c8d3ef9ea350decf1564e0bc
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
(cherry picked from commit 68e7840dd8)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3111544
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:55:49 -07:00
Jon Hunter
f78df7fa59 video: tegra: virt: Fix build for Linux v6.9
The definition SLAB_MEM_SPREAD was removed in Linux v6.9 and this breaks
the compilation of the Tegra Graphics Virtualization Comms driver. Add a
test to conftest to detect if SLAB_MEM_SPREAD is defined and update the
driver accordingly to fix the build.

Bug 4471899

Change-Id: Ibcac2dbc6538bcda92e818b333a9db6b8234f1d7
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104558
(cherry picked from commit 7acb255112)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104650
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:55:38 -07:00
Jon Hunter
1a5be9188a soc/tegra: bpmp: Fix build for Linux v6.9
In Linux v6.9-rc1, the typedef genpd_xlate_t was updated to make
'of_phandle_args' argument const. Add a test to the conftest script to
test if this argument is const and update the BPMP powergate driver
accordingly.

Bug 4471899

Change-Id: I85ddb3689ccf5dc769cd208575db69a2cf7b0a11
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3103819
(cherry picked from commit 9c180ac0c8)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104378
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-04-18 13:55:28 -07:00
Jon Hunter
6969153c7c block: virtual-storage: Fix build for Linux v6.9
In Linux v6.9-rc1, the function blk_mq_init_queue() was renamed
blk_mq_alloc_queue() and the arguments passed to the function were
updated. Add a test to conftest to detect if the function
blk_mq_alloc_queue() is present and update the virtual-storage driver
accordingly.

Bug 4471899

Change-Id: I7dc937eaad27445b1c140c57aafd36f4a4b769ba
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3095926
(cherry picked from commit 3b9f5783b2)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3104377
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-04-18 13:55:17 -07:00
Shobek Attupurath
4e544f3b3a rtl8822ce: Add Nvidia changes on v5.14.0.4-217
1. Add custom roam parameters
2. Add path for power file
3. Add source tree path for Makefile
4. Add section in Makefile for TEGRA platform
5. Update permissions from 0755 to 0644 for files
6. Move roaming debug prints to RTW_INFO

Bug 4320751
Bug 4556940
Bug 4568390

Change-Id: I842f150781652b3b54949aef8f982903c8d7991e
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3108666
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-04-18 09:24:33 -07:00
Revanth Kumar Uppala
ed30eb40ff rtl8822ce: Fix TLP/EAPOL/TXFIFO issues
Issue: Observing the EAPOL packet after a second in 1/10 roams

       Observing TLP Malform packets on SC7

       Observing TXFIFO error when connected to serving AP

       Compilation errors for K6.x

Fix:   Add exact base driver released by realtek with EAPOL/TLP/TXFIFO
       fixes and also resolve some compilation errors.

DRIVERVERSION   v5.14.0.4-217-g7a0377e61.20240410_COEX20240327-2727_beta
BTCOEXVERSION   COEX20240327-2727

Bug 4320751
Bug 4556940
Bug 4568390

Change-Id: Ib02056ea388300dab2364b2bd6ceaf0a2096d3f4
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3115032
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
Tested-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
2024-04-18 09:24:27 -07:00
yunzhao
f107cac72e csi5:add error config
add the error configuration for v4l2 path, Make the error config
of v4l2 and Argus consistent on the same port.

bug 4499208

Signed-off-by: yunzhao <yunzhao@nvidia.com>
Change-Id: I3dce5b9a30e3f04d2224252b3aff7ca0c9ef5567
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3097276
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Jackie Chen <jackchen@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2024-04-18 07:09:24 -07:00
Mikko Perttunen
83d8dcc34c drm/tegra: nvdec: Enable SLCG/PG
Add register writes to enable second level clock gating /
power gating. For now only for Tegra234.

Bug 4475968

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: Ie2e3b6d375bb6b7772b71999df81d73bea7ad550
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3116212
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Santosh BS <santoshb@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-04-15 23:09:24 -07:00
199 changed files with 40181 additions and 5731 deletions

View File

@@ -1,13 +1,19 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Makefile for Virtual Storage Driver
#
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_11 := $(shell expr 6 \* 256 + 11)
# Use dummy driver for Kernel versions greater than or equal to Linux v6.11
ifeq ($(shell test $(LINUX_VERSION) -lt $(LINUX_VERSION_6_11); echo $$?),0)
tegra_vblk-y += tegra_hv_vblk.o
tegra_vblk-y += tegra_hv_ioctl.o
tegra_vblk-y += tegra_hv_mmc.o
tegra_vblk-y += tegra_hv_scsi.o
tegra_vblk-y += tegra_hv_ufs.o
obj-m += tegra_vblk.o
endif

View File

@@ -1,10 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/vmalloc.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/fcntl.h> /* O_ACCMODE */

View File

@@ -1,9 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/slab.h> /* kmalloc() */
#include <linux/vmalloc.h> /* kmalloc() */
#include <linux/errno.h> /* error codes */
#include <linux/delay.h> /* For msleep and usleep_range */
#include <uapi/scsi/ufs/ioctl.h>

View File

@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -997,7 +995,11 @@ static void setup_device(struct vblk_dev *vblkdev)
if (ret)
return;
#if defined(NV_BLK_MQ_ALLOC_QUEUE_PRESENT)
vblkdev->queue = blk_mq_alloc_queue(&vblkdev->tag_set, NULL, NULL);
#else
vblkdev->queue = blk_mq_init_queue(&vblkdev->tag_set);
#endif
if (IS_ERR(vblkdev->queue)) {
dev_err(vblkdev->device, "failed to init blk queue\n");
blk_mq_free_tag_set(&vblkdev->tag_set);
@@ -1162,7 +1164,9 @@ static void setup_device(struct vblk_dev *vblkdev)
vblkdev->max_requests = max_requests;
vblkdev->max_ioctl_requests = max_ioctl_requests;
#if defined(NV_BLK_QUEUE_MAX_HW_SECTORS_PRESENT) /* Removed in Linux v6.10 */
blk_queue_max_hw_sectors(vblkdev->queue, max_io_bytes / SECTOR_SIZE);
#endif
blk_queue_flag_set(QUEUE_FLAG_NONROT, vblkdev->queue);
if ((vblkdev->config.blk_config.req_ops_supported & VS_BLK_SECURE_ERASE_OP_F)

View File

@@ -54,7 +54,7 @@ struct cfg_list_item {
struct list_head list;
u16 offset;
u8 len;
u8 data[0];
u8 data[];
};
static struct list_head list_configs;

View File

@@ -5,9 +5,7 @@ ifdef CONFIG_TEGRA_HOST1X
obj-m += tegra-hv-vse-safety.o
obj-m += tegra-nvvse-cryptodev.o
ifdef CONFIG_CRYPTO_ENGINE
ifndef CONFIG_SKIP_CRYPTO
obj-m += tegra/
endif
endif
endif
obj-m += tegra-se-nvrng.o

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
ccflags-y += -I$(srctree.nvidia)/drivers/gpu/host1x/include

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
*/
@@ -7,7 +7,6 @@
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -27,15 +26,14 @@ struct tegra_sha_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct crypto_engine_ctx enginectx;
#endif
struct crypto_ahash *fallback_tfm;
struct tegra_se *se;
unsigned int alg;
bool fallback;
u32 key_id;
struct crypto_ahash *fallback_tfm;
};
struct tegra_sha_reqctx {
struct ahash_request fallback_req;
struct scatterlist *src_sg;
struct tegra_se_datbuf datbuf;
struct tegra_se_datbuf residue;
@@ -46,6 +44,8 @@ struct tegra_sha_reqctx {
unsigned int blk_size;
unsigned int task;
u32 key_id;
u32 result[HASH_RESULT_REG_COUNT];
struct ahash_request fallback_req;
};
static int tegra_sha_get_config(u32 alg)
@@ -216,13 +216,13 @@ static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
}
static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
struct tegra_sha_reqctx *rctx)
struct tegra_sha_reqctx *rctx)
{
u64 msg_len, msg_left;
int i = 0;
msg_len = (u64)rctx->total_len * 8;
msg_left = (u64)rctx->datbuf.size * 8;
msg_len = rctx->total_len * 8;
msg_left = rctx->datbuf.size * 8;
/*
* If IN_ADDR_HI_0.SZ > SHA_MSG_LEFT_[0-3] to the HASH engine,
@@ -236,7 +236,7 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
}
cpuvaddr[i++] = host1x_opcode_setpayload(8);
cpuvaddr[i++] = host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
cpuvaddr[i++] = lower_32_bits(msg_len);
cpuvaddr[i++] = upper_32_bits(msg_len);
cpuvaddr[i++] = 0;
@@ -246,14 +246,15 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
cpuvaddr[i++] = 0;
cpuvaddr[i++] = 0;
cpuvaddr[i++] = host1x_opcode_setpayload(6);
cpuvaddr[i++] = host1x_opcode_incr_w(SE_SHA_CFG);
cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG);
cpuvaddr[i++] = rctx->config;
if (rctx->task & SHA_FIRST) {
cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
rctx->task &= ~SHA_FIRST;
} else
} else {
cpuvaddr[i++] = 0;
}
cpuvaddr[i++] = rctx->datbuf.addr;
cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) |
@@ -263,30 +264,47 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
SE_ADDR_HI_SZ(rctx->digest.size));
if (rctx->key_id) {
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
cpuvaddr[i++] = SE_AES_KEY_INDEX(rctx->key_id);
}
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_nonincr_w(SE_SHA_OPERATION);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION);
cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
SE_SHA_OP_START |
SE_SHA_OP_LASTBUF;
cpuvaddr[i++] = host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x",
msg_len, msg_left, rctx->config);
msg_len, msg_left, rctx->config);
return i;
}
static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
{
int i;
for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4));
}
static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
{
int i;
for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
writel(rctx->result[i],
se->base + se->hw->regs->result + (i * 4));
}
static int tegra_sha_do_update(struct ahash_request *req)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
unsigned int nblks, nresidue, size;
unsigned int nblks, nresidue, size, ret;
u32 *cpuvaddr = ctx->se->cmdbuf->addr;
nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
@@ -311,21 +329,26 @@ static int tegra_sha_do_update(struct ahash_request *req)
*/
if (nblks < 1) {
scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size,
rctx->src_sg, 0, req->nbytes, 0);
rctx->src_sg, 0, req->nbytes, 0);
rctx->residue.size += req->nbytes;
return 0;
}
rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
/* Copy the previous residue first */
if (rctx->residue.size)
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
scatterwalk_map_and_copy(rctx->datbuf.buf + rctx->residue.size,
rctx->src_sg, 0, req->nbytes - nresidue, 0);
rctx->src_sg, 0, req->nbytes - nresidue, 0);
scatterwalk_map_and_copy(rctx->residue.buf, rctx->src_sg,
req->nbytes - nresidue, nresidue, 0);
req->nbytes - nresidue, nresidue, 0);
/* Update residue value with the residue after current block */
rctx->residue.size = nresidue;
@@ -333,9 +356,30 @@ static int tegra_sha_do_update(struct ahash_request *req)
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_HASH_REG;
/*
* If this is not the first 'update' call, paste the previous copied
* intermediate results to the registers so that it gets picked up.
* This is to support the import/export functionality.
*/
if (!(rctx->task & SHA_FIRST))
tegra_sha_paste_hash_result(ctx->se, rctx);
size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
return tegra_se_host1x_submit(ctx->se, size);
ret = tegra_se_host1x_submit(ctx->se, ctx->se->cmdbuf, size);
/*
* If this is not the final update, copy the intermediate results
* from the registers so that it can be used in the next 'update'
* call. This is to support the import/export functionality.
*/
if (!(rctx->task & SHA_FINAL))
tegra_sha_copy_hash_result(ctx->se, rctx);
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
return ret;
}
static int tegra_sha_do_final(struct ahash_request *req)
@@ -347,16 +391,25 @@ static int tegra_sha_do_final(struct ahash_request *req)
u32 *cpuvaddr = se->cmdbuf->addr;
int size, ret = 0;
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
rctx->datbuf.size = rctx->residue.size;
rctx->total_len += rctx->residue.size;
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_MEMORY;
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
if (rctx->residue.size) {
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf) {
ret = -ENOMEM;
goto out_free;
}
ret = tegra_se_host1x_submit(se, size);
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
}
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
if (ret)
goto out;
@@ -364,12 +417,14 @@ static int tegra_sha_do_final(struct ahash_request *req)
memcpy(req->result, rctx->digest.buf, rctx->digest.size);
out:
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
rctx->datbuf.buf, rctx->datbuf.addr);
if (rctx->residue.size)
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
out_free:
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
rctx->residue.buf, rctx->residue.addr);
rctx->residue.buf, rctx->residue.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
rctx->digest.addr);
return ret;
}
@@ -380,7 +435,7 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
int ret = -EINVAL;
int ret = 0;
if (rctx->task & SHA_UPDATE) {
ret = tegra_sha_do_update(req);
@@ -394,27 +449,43 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
crypto_finalize_hash_request(se->engine, req, ret);
return ret;
return 0;
}
static void tegra_sha_init_fallback(struct tegra_sha_ctx *ctx, const char *algname)
static void tegra_sha_init_fallback(struct crypto_ahash *tfm, struct tegra_sha_ctx *ctx,
const char *algname)
{
unsigned int statesize;
ctx->fallback_tfm = crypto_alloc_ahash(algname, 0, CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK);
if (IS_ERR(ctx->fallback_tfm)) {
dev_warn(ctx->se->dev, "failed to allocate fallback for %s %ld\n",
algname, PTR_ERR(ctx->fallback_tfm));
dev_warn(ctx->se->dev,
"failed to allocate fallback for %s\n", algname);
ctx->fallback_tfm = NULL;
return;
}
statesize = crypto_ahash_statesize(ctx->fallback_tfm);
if (statesize > sizeof(struct tegra_sha_reqctx))
crypto_hash_alg_common(tfm)->statesize = statesize;
/* Update reqsize if fallback is added */
crypto_ahash_set_reqsize(tfm,
sizeof(struct tegra_sha_reqctx) +
crypto_ahash_reqsize(ctx->fallback_tfm));
}
static int tegra_sha_cra_init(struct crypto_tfm *tfm)
{
struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_ahash *ahash_tfm = __crypto_ahash_cast(tfm);
struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
struct tegra_se_alg *se_alg;
const char *algname;
int ret;
algname = crypto_tfm_alg_name(tfm);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
@@ -423,21 +494,28 @@ static int tegra_sha_cra_init(struct crypto_tfm *tfm)
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash);
#endif
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
sizeof(struct tegra_sha_reqctx));
crypto_ahash_set_reqsize(ahash_tfm, sizeof(struct tegra_sha_reqctx));
ctx->se = se_alg->se_dev;
ctx->fallback = false;
ctx->key_id = 0;
ctx->alg = se_algname_to_algid(algname);
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req;
ctx->enginectx.op.unprepare_request = NULL;
#endif
ret = se_algname_to_algid(algname);
if (ret < 0) {
dev_err(ctx->se->dev, "invalid algorithm\n");
return ret;
}
if (se_alg->alg_base)
tegra_sha_init_fallback(ctx, algname);
tegra_sha_init_fallback(ahash_tfm, ctx, algname);
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req;
#endif
return 0;
}
@@ -449,7 +527,7 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
if (ctx->fallback_tfm)
crypto_free_ahash(ctx->fallback_tfm);
tegra_key_invalidate(ctx->se, ctx->key_id);
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
}
static int tegra_sha_init(struct ahash_request *req)
@@ -458,45 +536,34 @@ static int tegra_sha_init(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
const char *algname;
if (ctx->fallback)
return tegra_sha_fallback_init(req);
algname = crypto_tfm_alg_name(&tfm->base);
rctx->total_len = 0;
rctx->datbuf.size = 0;
rctx->residue.size = 0;
rctx->key_id = ctx->key_id;
rctx->task = SHA_FIRST;
rctx->alg = se_algname_to_algid(algname);
rctx->alg = ctx->alg;
rctx->blk_size = crypto_ahash_blocksize(tfm);
rctx->digest.size = crypto_ahash_digestsize(tfm);
rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
&rctx->digest.addr, GFP_KERNEL);
&rctx->digest.addr, GFP_KERNEL);
if (!rctx->digest.buf)
goto digbuf_fail;
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
&rctx->residue.addr, GFP_KERNEL);
&rctx->residue.addr, GFP_KERNEL);
if (!rctx->residue.buf)
goto resbuf_fail;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
goto datbuf_fail;
return 0;
datbuf_fail:
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
rctx->residue.addr);
resbuf_fail:
dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
rctx->datbuf.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
digbuf_fail:
return -ENOMEM;
}
@@ -505,7 +572,7 @@ static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
unsigned int keylen)
{
if (!ctx->fallback_tfm) {
dev_err(ctx->se->dev, "invalid key length\n");
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
@@ -517,13 +584,18 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
int ret;
if (aes_check_keylen(keylen))
return tegra_hmac_fallback_setkey(ctx, key, keylen);
ctx->fallback = false;
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
if (ret)
return tegra_hmac_fallback_setkey(ctx, key, keylen);
return 0;
}
static int tegra_sha_update(struct ahash_request *req)
@@ -593,9 +665,6 @@ static int tegra_sha_export(struct ahash_request *req, void *out)
return tegra_sha_fallback_export(req, out);
memcpy(out, rctx, sizeof(*rctx));
/*
* TODO: Copy HASH_RESULT registers as well.
*/
return 0;
}
@@ -629,7 +698,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA1_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha1",
.cra_driver_name = "tegra-se-sha1",
@@ -661,7 +729,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha224",
.cra_driver_name = "tegra-se-sha224",
@@ -693,7 +760,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha256",
.cra_driver_name = "tegra-se-sha256",
@@ -725,7 +791,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha384",
.cra_driver_name = "tegra-se-sha384",
@@ -757,7 +822,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha512",
.cra_driver_name = "tegra-se-sha512",
@@ -789,7 +853,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-224",
.cra_driver_name = "tegra-se-sha3-224",
@@ -821,7 +884,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-256",
.cra_driver_name = "tegra-se-sha3-256",
@@ -853,7 +915,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-384",
.cra_driver_name = "tegra-se-sha3-384",
@@ -885,7 +946,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-512",
.cra_driver_name = "tegra-se-sha3-512",
@@ -919,7 +979,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha224)",
.cra_driver_name = "tegra-se-hmac-sha224",
@@ -953,7 +1012,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha256)",
.cra_driver_name = "tegra-se-hmac-sha256",
@@ -987,7 +1045,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha384)",
.cra_driver_name = "tegra-se-hmac-sha384",
@@ -1021,7 +1078,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha512)",
.cra_driver_name = "tegra-se-hmac-sha512",
@@ -1077,28 +1133,32 @@ static int tegra_hash_kac_manifest(u32 user, u32 alg, u32 keylen)
int tegra_init_hash(struct tegra_se *se)
{
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct ahash_engine_alg *alg;
#else
struct ahash_alg *alg;
#endif
int i, ret;
se->manifest = tegra_hash_kac_manifest;
for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) {
tegra_hash_algs[i].se_dev = se;
ret = CRYPTO_REGISTER(ahash, &tegra_hash_algs[i].alg.ahash);
alg = &tegra_hash_algs[i].alg.ahash;
ret = CRYPTO_REGISTER(ahash, alg);
if (ret) {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
dev_err(se->dev, "failed to register %s\n",
tegra_hash_algs[i].alg.ahash.base.halg.base.cra_name);
alg->base.halg.base.cra_name);
#else
dev_err(se->dev, "failed to register %s\n",
tegra_hash_algs[i].alg.ahash.halg.base.cra_name);
alg->halg.base.cra_name);
#endif
goto sha_err;
}
}
dev_info(se->dev, "registered HASH algorithms\n");
return 0;
sha_err:
@@ -1108,8 +1168,7 @@ sha_err:
return ret;
}
void tegra_deinit_hash(void)
void tegra_deinit_hash(struct tegra_se *se)
{
int i;

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver file to manage keys of NVIDIA Security Engine.
*/
@@ -16,66 +16,77 @@
#define SE_KEY_RSVD_MASK (BIT(0) | BIT(14) | BIT(15))
#define SE_KEY_VALID_MASK (SE_KEY_FULL_MASK & ~SE_KEY_RSVD_MASK)
/* Mutex lock to guard keyslots */
static DEFINE_MUTEX(kslt_lock);
/* Keyslot bitmask (0 = available, 1 = in use/not available) */
static u16 tegra_se_keyslots = SE_KEY_RSVD_MASK;
static u16 tegra_keyslot_alloc(void)
{
u16 keyid;
mutex_lock(&kslt_lock);
/* Check if all key slots are full */
if (tegra_se_keyslots == GENMASK(SE_MAX_KEYSLOT, 0))
if (tegra_se_keyslots == GENMASK(SE_MAX_KEYSLOT, 0)) {
mutex_unlock(&kslt_lock);
return 0;
}
keyid = ffz(tegra_se_keyslots);
tegra_se_keyslots |= BIT(keyid);
mutex_unlock(&kslt_lock);
return keyid;
}
static void tegra_keyslot_free(u16 slot)
{
mutex_lock(&kslt_lock);
tegra_se_keyslots &= ~(BIT(slot));
mutex_unlock(&kslt_lock);
}
static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr,
const u32 *key, u32 keylen, u16 slot, u32 alg)
const u32 *key, u32 keylen, u16 slot, u32 alg)
{
int i = 0, j;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = SE_AES_OP_WRSTALL | SE_AES_OP_DUMMY;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->manifest);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->manifest);
cpuvaddr[i++] = se->manifest(se->owner, alg, keylen);
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_dst);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_dst);
cpuvaddr[i++] = SE_AES_KEY_DST_INDEX(slot);
for (j = 0; j < keylen / 4; j++) {
/* Set key address */
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_addr);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_addr);
cpuvaddr[i++] = j;
/* Set key data */
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_data);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_data);
cpuvaddr[i++] = key[j];
}
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->config);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->config);
cpuvaddr[i++] = SE_CFG_INS;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = SE_AES_OP_WRSTALL | SE_AES_OP_START |
SE_AES_OP_LASTBUF;
cpuvaddr[i++] = host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
@@ -87,29 +98,44 @@ static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr,
static bool tegra_key_in_kslt(u32 keyid)
{
bool ret;
if (keyid > SE_MAX_KEYSLOT)
return false;
return ((BIT(keyid) & SE_KEY_VALID_MASK) &&
mutex_lock(&kslt_lock);
ret = ((BIT(keyid) & SE_KEY_VALID_MASK) &&
(BIT(keyid) & tegra_se_keyslots));
mutex_unlock(&kslt_lock);
return ret;
}
static int tegra_key_insert(struct tegra_se *se, const u8 *key,
u32 keylen, u16 slot, u32 alg)
u32 keylen, u16 slot, u32 alg)
{
const u32 *keyval = (u32 *)key;
u32 *addr = se->cmdbuf->addr, size;
u32 *addr = se->keybuf->addr, size;
int ret;
mutex_lock(&kslt_lock);
size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg);
ret = tegra_se_host1x_submit(se, se->keybuf, size);
mutex_unlock(&kslt_lock);
return tegra_se_host1x_submit(se, size);
return ret;
}
void tegra_key_invalidate(struct tegra_se *se, u32 keyid)
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
{
u8 zkey[AES_MAX_KEY_SIZE] = {0};
if (!keyid)
return;
/* Overwrite the key with 0s */
tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
tegra_keyslot_free(keyid);
}
@@ -120,8 +146,10 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3
/* Use the existing slot if it is already allocated */
if (!tegra_key_in_kslt(*keyid)) {
*keyid = tegra_keyslot_alloc();
if (!(*keyid))
if (!(*keyid)) {
dev_dbg(se->dev, "failed to allocate key slot\n");
return -ENOMEM;
}
}
ret = tegra_key_insert(se, key, keylen, *keyid, alg);
@@ -130,3 +158,20 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3
return 0;
}
void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg)
{
u8 zkey[AES_MAX_KEY_SIZE] = {0};
if (!keyid)
return;
/* Overwrite the key with 0s */
tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
}
inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
return tegra_key_insert(se, key, keylen, *keyid, alg);
}

View File

@@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver for NVIDIA Security Engine in Tegra Chips
*/
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
@@ -124,7 +123,7 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi
struct tegra_se_cmdbuf *cmdbuf;
struct device *dev = se->dev->parent;
cmdbuf = kzalloc(sizeof(struct tegra_se_cmdbuf), GFP_KERNEL);
cmdbuf = kzalloc(sizeof(*cmdbuf), GFP_KERNEL);
if (!cmdbuf)
return NULL;
@@ -142,7 +141,7 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi
return cmdbuf;
}
int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size)
{
struct host1x_job *job;
int ret;
@@ -153,7 +152,7 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
return -ENOMEM;
}
job->syncpt = host1x_syncpt_get(se->syncpt);
job->syncpt = host1x_syncpt_get(se->syncpt);
job->syncpt_incrs = 1;
job->client = &se->client;
job->class = se->client.class;
@@ -161,24 +160,24 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
job->engine_fallback_streamid = se->stream_id;
job->engine_streamid_offset = SE_STREAM_ID;
se->cmdbuf->words = size;
cmdbuf->words = size;
host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0);
host1x_job_add_gather(job, &cmdbuf->bo, size, 0);
ret = host1x_job_pin(job, se->dev);
if (ret) {
dev_err(se->dev, "failed to pin host1x job\n");
goto err_job_pin;
goto job_put;
}
ret = host1x_job_submit(job);
if (ret) {
dev_err(se->dev, "failed to submit host1x job\n");
goto err_job_submit;
goto job_unpin;
}
ret = host1x_syncpt_wait(job->syncpt, job->syncpt_end,
MAX_SCHEDULE_TIMEOUT, NULL);
MAX_SCHEDULE_TIMEOUT, NULL);
if (ret) {
dev_err(se->dev, "host1x job timed out\n");
return ret;
@@ -187,9 +186,9 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
host1x_job_put(job);
return 0;
err_job_submit:
job_unpin:
host1x_job_unpin(job);
err_job_pin:
job_put:
host1x_job_put(job);
return ret;
@@ -210,7 +209,7 @@ static int tegra_se_client_init(struct host1x_client *client)
if (!se->syncpt) {
dev_err(se->dev, "host1x syncpt allocation failed\n");
ret = -EINVAL;
goto err_syncpt;
goto channel_put;
}
se->syncpt_id = host1x_syncpt_id(se->syncpt);
@@ -218,22 +217,30 @@ static int tegra_se_client_init(struct host1x_client *client)
se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) {
ret = -ENOMEM;
goto err_bo;
goto syncpt_put;
}
se->keybuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) {
ret = -ENOMEM;
goto cmdbuf_put;
}
ret = se->hw->init_alg(se);
if (ret) {
dev_err(se->dev, "failed to register algorithms\n");
goto err_alg_reg;
goto keybuf_put;
}
return 0;
err_alg_reg:
keybuf_put:
tegra_se_cmdbuf_put(&se->keybuf->bo);
cmdbuf_put:
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
err_bo:
syncpt_put:
host1x_syncpt_put(se->syncpt);
err_syncpt:
channel_put:
host1x_channel_put(se->channel);
return ret;
@@ -243,7 +250,7 @@ static int tegra_se_client_deinit(struct host1x_client *client)
{
struct tegra_se *se = container_of(client, struct tegra_se, client);
se->hw->deinit_alg();
se->hw->deinit_alg(se);
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
host1x_syncpt_put(se->syncpt);
host1x_channel_put(se->channel);
@@ -256,7 +263,7 @@ static const struct host1x_client_ops tegra_se_client_ops = {
.exit = tegra_se_client_deinit,
};
int tegra_se_host1x_register(struct tegra_se *se)
static int tegra_se_host1x_register(struct tegra_se *se)
{
INIT_LIST_HEAD(&se->client.list);
se->client.dev = se->dev;
@@ -269,38 +276,6 @@ int tegra_se_host1x_register(struct tegra_se *se)
return 0;
}
static int tegra_se_clk_init(struct tegra_se *se)
{
int i, ret;
se->num_clks = devm_clk_bulk_get_all(se->dev, &se->clks);
if (se->num_clks < 0) {
dev_err(se->dev, "failed to get clocks\n");
return se->num_clks;
}
for (i = 0; i < se->num_clks; i++) {
ret = clk_set_rate(se->clks[i].clk, ULONG_MAX);
if (ret) {
dev_err(se->dev, "failed to set %d clock rate", i);
return ret;
}
}
ret = clk_bulk_prepare_enable(se->num_clks, se->clks);
if (ret) {
dev_err(se->dev, "failed to enable clocks\n");
return ret;
}
return 0;
}
static void tegra_se_clk_deinit(struct tegra_se *se)
{
clk_bulk_disable_unprepare(se->num_clks, se->clks);
}
static int tegra_se_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -312,61 +287,45 @@ static int tegra_se_probe(struct platform_device *pdev)
return -ENOMEM;
se->dev = dev;
se->owner = TEGRA_GPSE_ID;
se->hw = device_get_match_data(&pdev->dev);
se->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(se->base))
return PTR_ERR(se->base);
se->owner = TEGRA_GPSE_ID;
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
platform_set_drvdata(pdev, se);
ret = tegra_se_clk_init(se);
if (ret) {
dev_err(dev, "failed to init clocks\n");
return ret;
}
se->clk = devm_clk_get_enabled(se->dev, NULL);
if (IS_ERR(se->clk))
return dev_err_probe(dev, PTR_ERR(se->clk),
"failed to enable clocks\n");
if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id)) {
dev_err(dev, "failed to get IOMMU stream ID\n");
goto err_iommu_spec;
}
if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id))
return dev_err_probe(dev, -ENODEV,
"failed to get IOMMU stream ID\n");
se_writel(se, se->stream_id, SE_STREAM_ID);
writel(se->stream_id, se->base + SE_STREAM_ID);
se->engine = crypto_engine_alloc_init(dev, 0);
if (!se->engine) {
dev_err(dev, "failed to init crypto engine\n");
ret = -ENOMEM;
goto err_engine_alloc;
}
if (!se->engine)
return dev_err_probe(dev, -ENOMEM, "failed to init crypto engine\n");
ret = crypto_engine_start(se->engine);
if (ret) {
dev_err(dev, "failed to start crypto engine\n");
goto err_engine_start;
crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to start crypto engine\n");
}
ret = tegra_se_host1x_register(se);
if (ret) {
dev_err(dev, "failed to init host1x params\n");
goto err_host1x_init;
crypto_engine_stop(se->engine);
crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to init host1x params\n");
}
return 0;
err_host1x_init:
crypto_engine_stop(se->engine);
err_engine_start:
crypto_engine_exit(se->engine);
err_engine_alloc:
iommu_fwspec_free(se->dev);
err_iommu_spec:
tegra_se_clk_deinit(se);
return ret;
}
static int tegra_se_remove(struct platform_device *pdev)
@@ -377,7 +336,6 @@ static int tegra_se_remove(struct platform_device *pdev)
crypto_engine_exit(se->engine);
iommu_fwspec_free(se->dev);
host1x_client_unregister(&se->client);
tegra_se_clk_deinit(se);
return 0;
}
@@ -424,10 +382,10 @@ static const struct tegra_se_hw tegra234_hash_hw = {
static const struct of_device_id tegra_se_of_match[] = {
{
.compatible = "nvidia,tegra234-se2-aes",
.compatible = "nvidia,tegra234-se-aes",
.data = &tegra234_aes_hw
}, {
.compatible = "nvidia,tegra234-se4-hash",
.compatible = "nvidia,tegra234-se-hash",
.data = &tegra234_hash_hw,
},
{ },
@@ -486,4 +444,4 @@ module_exit(tegra_se_module_exit);
MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver");
MODULE_AUTHOR("Akhil R <akhilrajeev@nvidia.com>");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL");

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Header file for NVIDIA Security Engine driver.
*/
@@ -7,22 +7,18 @@
#ifndef _TEGRA_SE_H
#define _TEGRA_SE_H
#include <linux/clk.h>
#include <nvidia/conftest.h>
#include <linux/bitfield.h>
#include <linux/iommu.h>
#include <linux/host1x-next.h>
#include <linux/version.h>
#include <crypto/aead.h>
#include <crypto/engine.h>
#include <crypto/hash.h>
#include <crypto/sha1.h>
#include <crypto/sha3.h>
#include <crypto/sm3.h>
#include <crypto/skcipher.h>
#include <nvidia/conftest.h>
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#include <crypto/engine.h>
#endif
#define SE_MAX_INSTANCES 3
#define SE_OWNERSHIP 0x14
#define SE_OWNERSHIP_UID(x) FIELD_GET(GENMASK(7, 0), x)
#define TEGRA_GPSE_ID 3
@@ -67,11 +63,8 @@
#define SE_SHA_ENC_ALG_HMAC SE_SHA_CFG_ENC_ALG(7)
#define SE_SHA_ENC_ALG_KDF SE_SHA_CFG_ENC_ALG(8)
#define SE_SHA_ENC_ALG_KEY_INVLD SE_SHA_CFG_ENC_ALG(10)
#define SE_SHA_ENC_ALG_KEY_MOV SE_SHA_CFG_ENC_ALG(11)
#define SE_SHA_ENC_ALG_KEY_INQUIRE SE_SHA_CFG_ENC_ALG(12)
#define SE_SHA_ENC_ALG_INS SE_SHA_CFG_ENC_ALG(13)
#define SE_SHA_ENC_ALG_CLONE SE_SHA_CFG_ENC_ALG(14)
#define SE_SHA_ENC_ALG_LOCK SE_SHA_CFG_ENC_ALG(15)
#define SE_SHA_OP_LASTBUF FIELD_PREP(BIT(16), 1)
#define SE_SHA_OP_WRSTALL FIELD_PREP(BIT(15), 1)
@@ -311,12 +304,6 @@
SE_AES_CORE_SEL_DECRYPT | \
SE_AES_IV_SEL_REG)
#define SE_CRYPTO_CFG_OFB (SE_AES_INPUT_SEL_AESOUT | \
SE_AES_VCTRAM_SEL_MEMORY | \
SE_AES_XOR_POS_BOTTOM | \
SE_AES_CORE_SEL_ENCRYPT | \
SE_AES_IV_SEL_REG)
#define SE_CRYPTO_CFG_CTR (SE_AES_INPUT_SEL_LINEAR_CTR | \
SE_AES_VCTRAM_SEL_MEMORY | \
SE_AES_XOR_POS_BOTTOM | \
@@ -355,8 +342,9 @@
#define SE_CRYPTO_CTR_REG_COUNT 4
#define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M
#define SE_AES_BUFLEN 0x8000
#define SE_SHA_BUFLEN SZ_4M
#define TEGRA_AES_RESERVED_KSLT 14
#define TEGRA_XTS_RESERVED_KSLT 15
#define SHA_FIRST BIT(0)
#define SHA_UPDATE BIT(1)
@@ -383,7 +371,6 @@ enum se_aes_alg {
SE_ALG_CBC, /* Cipher Block Chaining (CBC) mode */
SE_ALG_ECB, /* Electronic Codebook (ECB) mode */
SE_ALG_CTR, /* Counter (CTR) mode */
SE_ALG_OFB, /* Output feedback (CFB) mode */
SE_ALG_XTS, /* XTS mode */
SE_ALG_GMAC, /* GMAC mode */
SE_ALG_GCM, /* GCM mode */
@@ -417,13 +404,13 @@ struct tegra_se_alg {
union {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct skcipher_alg skcipher;
struct aead_alg aead;
struct ahash_alg ahash;
struct skcipher_alg skcipher;
struct aead_alg aead;
struct ahash_alg ahash;
#else
struct skcipher_engine_alg skcipher;
struct aead_engine_alg aead;
struct ahash_engine_alg ahash;
struct skcipher_engine_alg skcipher;
struct aead_engine_alg aead;
struct ahash_engine_alg ahash;
#endif
} alg;
};
@@ -446,7 +433,7 @@ struct tegra_se_regs {
struct tegra_se_hw {
const struct tegra_se_regs *regs;
int (*init_alg)(struct tegra_se *se);
void (*deinit_alg)(void);
void (*deinit_alg)(struct tegra_se *se);
bool support_sm_alg;
u32 host1x_class;
u32 kac_ver;
@@ -455,18 +442,18 @@ struct tegra_se_hw {
struct tegra_se {
int (*manifest)(u32 user, u32 alg, u32 keylen);
const struct tegra_se_hw *hw;
struct crypto_engine *engine;
struct host1x_channel *channel;
struct host1x_client client;
struct host1x_syncpt *syncpt;
struct clk_bulk_data *clks;
struct host1x_channel *channel;
struct tegra_se_cmdbuf *cmdbuf;
struct tegra_se_cmdbuf *keybuf;
struct crypto_engine *engine;
struct host1x_syncpt *syncpt;
struct device *dev;
struct clk *clk;
unsigned int opcode_addr;
unsigned int stream_id;
unsigned int syncpt_id;
void __iomem *base;
int num_clks;
u32 owner;
};
@@ -476,8 +463,8 @@ struct tegra_se_cmdbuf {
struct device *dev;
struct kref ref;
struct host1x_bo bo;
u32 words;
ssize_t size;
u32 words;
};
struct tegra_se_datbuf {
@@ -492,8 +479,6 @@ static inline int se_algname_to_algid(const char *name)
return SE_ALG_CBC;
else if (!strcmp(name, "ecb(aes)"))
return SE_ALG_ECB;
else if (!strcmp(name, "ofb(aes)"))
return SE_ALG_OFB;
else if (!strcmp(name, "ctr(aes)"))
return SE_ALG_CTR;
else if (!strcmp(name, "xts(aes)"))
@@ -536,87 +521,85 @@ static inline int se_algname_to_algid(const char *name)
}
/* Functions */
int tegra_init_aead(struct tegra_se *se);
int tegra_init_aes(struct tegra_se *se);
int tegra_init_hash(struct tegra_se *se);
void tegra_deinit_aead(void);
void tegra_deinit_aes(void);
void tegra_deinit_hash(void);
void tegra_deinit_aes(struct tegra_se *se);
void tegra_deinit_hash(struct tegra_se *se);
int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size);
int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u32 *keyid);
unsigned int tegra_key_get_idx(struct tegra_se *se, u32 keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid);
int tegra_se_host1x_register(struct tegra_se *se);
int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
static inline void se_writel(struct tegra_se *se, unsigned int val,
unsigned int offset)
static inline int tegra_key_submit_reserved_aes(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
writel_relaxed(val, se->base + offset);
*keyid = TEGRA_AES_RESERVED_KSLT;
return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
}
static inline u32 se_readl(struct tegra_se *se, unsigned int offset)
static inline int tegra_key_submit_reserved_xts(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
return readl_relaxed(se->base + offset);
*keyid = TEGRA_XTS_RESERVED_KSLT;
return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
}
static inline bool tegra_key_is_reserved(u32 keyid)
{
return ((keyid == TEGRA_AES_RESERVED_KSLT) ||
(keyid == TEGRA_XTS_RESERVED_KSLT));
}
/****
*
* HOST1x OPCODES
*
****/
/* HOST1x OPCODES */
static inline u32 host1x_opcode_setpayload(unsigned int payload)
{
return (9 << 28) | payload;
}
#define host1x_opcode_incr_w(x) __host1x_opcode_incr_w((x) / 4)
static inline u32 __host1x_opcode_incr_w(unsigned int offset)
static inline u32 host1x_opcode_incr_w(unsigned int offset)
{
/* 22-bit offset supported */
return (10 << 28) | offset;
}
#define host1x_opcode_nonincr_w(x) __host1x_opcode_nonincr_w((x) / 4)
static inline u32 __host1x_opcode_nonincr_w(unsigned int offset)
static inline u32 host1x_opcode_nonincr_w(unsigned int offset)
{
/* 22-bit offset supported */
return (11 << 28) | offset;
}
#define host1x_opcode_incr(x, y) __host1x_opcode_incr((x) / 4, y)
static inline u32 __host1x_opcode_incr(unsigned int offset, unsigned int count)
static inline u32 host1x_opcode_incr(unsigned int offset, unsigned int count)
{
return (1 << 28) | (offset << 16) | count;
return (1 << 28) | (offset << 16) | count;
}
#define host1x_opcode_nonincr(x, y) __host1x_opcode_nonincr((x) / 4, y)
static inline u32 __host1x_opcode_nonincr(unsigned int offset, unsigned int count)
static inline u32 host1x_opcode_nonincr(unsigned int offset, unsigned int count)
{
return (2 << 28) | (offset << 16) | count;
return (2 << 28) | (offset << 16) | count;
}
static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
{
return (v & 0xff) << 10;
return (v & 0xff) << 10;
}
static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
{
return (v & 0x3ff) << 0;
return (v & 0x3ff) << 0;
}
static inline u32 host1x_uclass_wait_syncpt_r(void)
{
return 0x8;
return 0x8;
}
static inline u32 host1x_uclass_incr_syncpt_r(void)
{
return 0x0;
return 0x0;
}
#if !defined(NV_TEGRA_DEV_IOMMU_GET_STREAM_ID_PRESENT)
@@ -635,4 +618,9 @@ static inline bool tegra_dev_iommu_get_stream_id(struct device *dev, u32 *stream
}
#endif
#define se_host1x_opcode_incr_w(x) host1x_opcode_incr_w((x) / 4)
#define se_host1x_opcode_nonincr_w(x) host1x_opcode_nonincr_w((x) / 4)
#define se_host1x_opcode_incr(x, y) host1x_opcode_incr((x) / 4, y)
#define se_host1x_opcode_nonincr(x, y) host1x_opcode_nonincr((x) / 4, y)
#endif /*_TEGRA_SE_H*/

View File

@@ -12,6 +12,7 @@
#include <linux/console.h>
#include <linux/version.h>
#include <linux/fb.h>
#include <linux/vmalloc.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>

View File

@@ -15,6 +15,7 @@
#include <linux/dma-buf.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <drm/drm_drv.h>
#include <drm/drm_prime.h>

View File

@@ -43,11 +43,37 @@
#define NVDEC_TFBIF_ACTMON_ACTIVE_WEIGHT 0x2c54
#define NVDEC_AXI_RW_BANDWIDTH 512
#define NVDEC_CG_SLCG_CTRL 0x297c
#define NVDEC_CG_SLCG_CTRL_IDLE_SLCG_DIS BIT(9)
#define NVDEC_RISCV_CG 0x4398
#define NVDEC_RISCV_CG_SLCG BIT(0)
#define NVDEC_RISCV_CG_CORE_SLCG BIT(1)
#define NVDEC_PG 0x2314
#define NVDEC_PG_DEEP_ELPG_EN BIT(18)
#define NVDEC_PG1 0x2318
#define NVDEC_CG2 0x2328
#define NVDEC_CG3 0x232c
#define NVDEC_CG4 0x2950
#define NVDEC_CG5 0x2954
#define NVDEC_CG6 0x2958
#define NVDEC_CG7 0x295c
#define NVDEC_CG8 0x2960
#define NVDEC_CG9 0x2964
#define NVDEC_CG10 0x2968
#define NVDEC_CG11 0x296c
#define NVDEC_CG12 0x2970
#define NVDEC_TFBIF_ACTMON_ACTIVE_MASK_STARVED BIT(0)
#define NVDEC_TFBIF_ACTMON_ACTIVE_MASK_STALLED BIT(1)
#define NVDEC_TFBIF_ACTMON_ACTIVE_MASK_DELAYED BIT(2)
#define NVDEC_TFBIF_ACTMON_ACTIVE_BORPS_ACTIVE BIT(7)
struct nvdec_cg_reg {
u32 offset;
u32 value;
};
struct nvdec_config {
const char *firmware;
unsigned int version;
@@ -55,6 +81,7 @@ struct nvdec_config {
bool supports_timestamping;
bool has_riscv;
bool has_extra_clocks;
const struct nvdec_cg_reg *cg_regs;
};
struct nvdec {
@@ -91,6 +118,11 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
writel(value, nvdec->regs + offset);
}
static inline u32 nvdec_readl(struct nvdec *nvdec, unsigned int offset)
{
return readl(nvdec->regs + offset);
}
static int nvdec_set_rate(struct nvdec *nvdec, unsigned long rate)
{
unsigned long dev_rate;
@@ -557,6 +589,29 @@ static void nvdec_count_weight_init(struct nvdec *nvdec, unsigned long rate)
}
}
static void nvdec_enable_slcg(struct nvdec *nvdec)
{
const struct nvdec_cg_reg *cg;
u32 val;
if (!nvdec->config->cg_regs)
return;
/* Enable power gating */
nvdec_writel(nvdec, 0xff00a725, NVDEC_PG1);
nvdec_writel(nvdec, NVDEC_PG_DEEP_ELPG_EN | (9 << 20) | (2 << 27), NVDEC_PG);
/* Enable clock gating */
for (cg = nvdec->config->cg_regs; cg->offset; cg++)
nvdec_writel(nvdec, cg->value, cg->offset);
val = nvdec_readl(nvdec, NVDEC_CG_SLCG_CTRL);
val &= ~NVDEC_CG_SLCG_CTRL_IDLE_SLCG_DIS;
nvdec_writel(nvdec, val, NVDEC_CG_SLCG_CTRL);
nvdec_writel(nvdec, NVDEC_RISCV_CG_SLCG | NVDEC_RISCV_CG_CORE_SLCG, NVDEC_RISCV_CG);
}
static __maybe_unused int nvdec_runtime_resume(struct device *dev)
{
struct nvdec *nvdec = dev_get_drvdata(dev);
@@ -582,6 +637,8 @@ static __maybe_unused int nvdec_runtime_resume(struct device *dev)
goto disable;
}
nvdec_enable_slcg(nvdec);
/* Forcely set frequency as Fmax when device is resumed back */
nvdec->devfreq->resume_freq = nvdec->devfreq->scaling_max_freq;
err = devfreq_resume_device(nvdec->devfreq);
@@ -698,12 +755,28 @@ static const struct nvdec_config nvdec_t194_config = {
.supports_timestamping = true,
};
static const struct nvdec_cg_reg nvdec_t234_cg_regs[] = {
{ NVDEC_CG2, 0x00000000 },
{ NVDEC_CG3, 0xfc800000 },
{ NVDEC_CG4, 0xffffffc0 },
{ NVDEC_CG5, 0x00000040 },
{ NVDEC_CG6, 0x04004000 },
{ NVDEC_CG7, 0xfc000000 },
{ NVDEC_CG8, 0x00000000 },
{ NVDEC_CG9, 0x80000000 },
{ NVDEC_CG10, 0xfffffb00 },
{ NVDEC_CG11, 0xfff80000 },
{ NVDEC_CG12, 0xffffff80 },
{ },
};
static const struct nvdec_config nvdec_t234_config = {
.version = 0x23,
.supports_sid = true,
.supports_timestamping = true,
.has_riscv = true,
.has_extra_clocks = true,
.cg_regs = nvdec_t234_cg_regs,
};
static const struct of_device_id tegra_nvdec_of_match[] = {

View File

@@ -1,9 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Host1x fence UAPI
*
* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
*/
// SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -205,20 +201,28 @@ struct host1x_pollfd {
static int host1x_pollfd_release(struct inode *inode, struct file *file)
{
struct host1x_pollfd *pollfd = file->private_data;
struct host1x_pollfd_fence *pfd_fence;
struct host1x_pollfd_fence *pfd_fence, *pfd_fence_temp;
mutex_lock(&pollfd->lock);
list_for_each_entry(pfd_fence, &pollfd->fences, list) {
list_for_each_entry_safe(pfd_fence, pfd_fence_temp, &pollfd->fences, list) {
if (pfd_fence->callback_set) {
if (dma_fence_remove_callback(pfd_fence->fence, &pfd_fence->callback))
host1x_fence_cancel(pfd_fence->fence);
pfd_fence->callback_set = false;
}
/*The lock/unlock just ensures that the callback execution has finished*/
spin_lock(pfd_fence->fence->lock);
spin_unlock(pfd_fence->fence->lock);
dma_fence_put(pfd_fence->fence);
kfree(pfd_fence);
}
mutex_unlock(&pollfd->lock);
kfree(pollfd);
return 0;
}
@@ -235,8 +239,20 @@ static unsigned int host1x_pollfd_poll(struct file *file, poll_table *wait)
list_for_each_entry_safe(pfd_fence, pfd_fence_temp, &pollfd->fences, list) {
if (dma_fence_is_signaled(pfd_fence->fence)) {
mask = POLLPRI | POLLIN;
if (pfd_fence->callback_set) {
if (dma_fence_remove_callback(pfd_fence->fence,
&pfd_fence->callback))
host1x_fence_cancel(pfd_fence->fence);
pfd_fence->callback_set = false;
}
/*The lock/unlock just ensures that the callback execution has finished*/
spin_lock(pfd_fence->fence->lock);
spin_unlock(pfd_fence->fence->lock);
dma_fence_put(pfd_fence->fence);
list_del(&pfd_fence->list);
kfree(pfd_fence);
}
}

View File

@@ -335,7 +335,11 @@ static int host1x_del_client(struct host1x *host1x,
return -ENODEV;
}
#if defined(NV_BUS_TYPE_STRUCT_MATCH_HAS_CONST_DRV_ARG)
static int host1x_device_match(struct device *dev, const struct device_driver *drv)
#else
static int host1x_device_match(struct device *dev, struct device_driver *drv)
#endif
{
return strcmp(dev_name(dev), drv->name) == 0;
}

View File

@@ -35,14 +35,14 @@
/*
* Typically the commands written into the push buffer are a pair of words. We
* use slots to represent each of these pairs and to simplify things. Note the
* strange number of slots allocated here. 512 slots will fit exactly within a
* single memory page. We also need one additional word at the end of the push
* strange number of slots allocated here. 1024 slots will fit exactly within a
* two memory pages. We also need one additional word at the end of the push
* buffer for the RESTART opcode that will instruct the CDMA to jump back to
* the beginning of the push buffer. With 512 slots, this means that we'll use
* 2 memory pages and waste 4092 bytes of the second page that will never be
* the beginning of the push buffer. With 1024 slots, this means that we'll use
* 3 memory pages and waste 4092 bytes of the third page that will never be
* used.
*/
#define HOST1X_PUSHBUFFER_SLOTS 511
#define HOST1X_PUSHBUFFER_SLOTS 1023
/*
* Clean up push buffer resources

View File

@@ -177,7 +177,14 @@ static void show_gather(struct output *o, dma_addr_t phys_addr,
for (i = 0; i < words; i++) {
dma_addr_t addr = phys_addr + i * 4;
u32 val = *(map_addr + offset / 4 + i);
u32 voffset = offset + i * 4;
u32 val;
/* If we reach the RESTART opcode, continue at the beginning of pushbuffer */
if (cdma && voffset >= cdma->push_buffer.size)
voffset -= cdma->push_buffer.size;
val = *(map_addr + voffset / 4);
if (!data_count) {
host1x_debug_output(o, " %pad: %08x: ", &addr, val);
@@ -203,7 +210,7 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
job->num_slots, job->num_unpins);
show_gather(o, pb->dma + job->first_get, job->num_slots * 2, cdma,
pb->dma + job->first_get, pb->mapped + job->first_get);
pb->dma, pb->mapped);
for (i = 0; i < job->num_cmds; i++) {
struct host1x_job_gather *g;
@@ -227,7 +234,7 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
host1x_debug_output(o, " GATHER at %pad+%#x, %d words\n",
&g->base, g->offset, g->words);
show_gather(o, g->base + g->offset, g->words, cdma,
show_gather(o, g->base + g->offset, g->words, NULL,
g->base, mapped);
if (!job->gather_copy_mapped)

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -1093,8 +1093,10 @@ static int f75308_probe_child_from_dt(struct device *dev,
u32 reg_idx, seg_idx = 0, seg_val;
u8 seg5[F75308_MAX_FAN_SEG_CNT];
const char *val_str;
#if !defined(NV_OF_PROPERTY_FOR_EACH_REMOVED_INTERNAL_ARGS) /* Linux v6.11 */
struct property *prop;
const __be32 *p;
#endif
status = of_property_read_u32(child, "reg", &reg_idx);
if (status) {
@@ -1125,7 +1127,11 @@ static int f75308_probe_child_from_dt(struct device *dev,
if (status)
return status;
#if defined(NV_OF_PROPERTY_FOR_EACH_REMOVED_INTERNAL_ARGS) /* Linux v6.11 */
of_property_for_each_u32(child, "5seg", seg_val) {
#else
of_property_for_each_u32(child, "5seg", prop, p, seg_val) {
#endif
dev_dbg(dev, "%s: seg5[%u]: %u\n", __func__, seg_idx, seg_val);
if (seg_idx < F75308_MAX_FAN_SEG_CNT)
seg5[seg_idx++] = seg_val;

View File

@@ -20,6 +20,7 @@ obj-m += nv_imx477.o
obj-m += nv_ov5693.o
obj-m += nv_ar0234.o
obj-m += nv_hawk_owl.o
obj-m += max929x.o
endif
obj-m += pca9570.o

View File

File diff suppressed because it is too large Load Diff

194
drivers/media/i2c/max929x.c Normal file
View File

@@ -0,0 +1,194 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* max929x.c - max929x IO Expander driver
*/
#include <nvidia/conftest.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <media/camera_common.h>
#include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include "max929x.h"
struct max929x {
struct i2c_client *i2c_client;
struct regmap *regmap;
unsigned int pwdn_gpio;
unsigned short ser_addr;
};
struct max929x *priv;
static int max929x_write_reg(u8 slave_addr, u16 reg, u8 val)
{
struct i2c_client *i2c_client = priv->i2c_client;
int err;
i2c_client->addr = slave_addr;
err = regmap_write(priv->regmap, reg, val);
if (err)
dev_err(&i2c_client->dev, "%s:i2c write failed, slave_addr 0x%x, 0x%x = 0x%x\n",
__func__, slave_addr, reg, val);
return err;
}
static int max929x_write_reg_list(struct max929x_reg *table, int size)
{
struct device dev = priv->i2c_client->dev;
int err = 0;
int i;
u8 slave_addr;
u16 reg;
u8 val;
for (i = 0; i < size; i++) {
if (table[i].slave_addr == SER_SLAVE2)
slave_addr = priv->ser_addr;
else
slave_addr = table[i].slave_addr;
reg = table[i].reg;
val = table[i].val;
if (slave_addr == 0xf1) {
msleep(val);
msleep(2000);
continue;
}
dev_dbg(&dev, "%s: size %d, slave_addr 0x%x, reg 0x%x, val 0x%x\n",
__func__, size, slave_addr, reg, val);
err = max929x_write_reg(slave_addr, reg, val);
if (err != 0)
break;
mdelay(5);
}
return err;
}
static struct regmap_config max929x_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
};
#if defined(NV_I2C_DRIVER_STRUCT_PROBE_WITHOUT_I2C_DEVICE_ID_ARG) /* Linux 6.3 */
static int max929x_probe(struct i2c_client *client)
#else
static int max929x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
#endif
{
struct device dev = client->dev;
struct device_node *np = (&dev)->of_node;
unsigned short ser_addr = SER_SLAVE2;
int err;
dev_dbg(&dev, "%s: enter\n", __func__);
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
priv->i2c_client = client;
priv->regmap = devm_regmap_init_i2c(priv->i2c_client, &max929x_regmap_config);
if (IS_ERR(priv->regmap)) {
dev_err(&client->dev,
"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
return -ENODEV;
}
priv->pwdn_gpio = of_get_named_gpio(np, "pwdn-gpios", 0);
if (priv->pwdn_gpio < 0) {
dev_err(&dev, "pwdn-gpios not found\n");
return -EINVAL;
}
if (priv->pwdn_gpio) {
gpio_direction_output(priv->pwdn_gpio, 1);
gpio_set_value(priv->pwdn_gpio, 1);
msleep(100);
}
/*
* Try to find the I2C address of serializer by writting to register
* 0x00 at i2c slave address 0x62 and 0x40. When write is successful
* the slave address is saved and used when configuring serializer.
*/
if (max929x_write_reg(SER_SLAVE2, MAX9295_DEV_ADDR, SER_SLAVE2 << 1)) {
if (max929x_write_reg(SER_SLAVE1, MAX9295_DEV_ADDR, SER_SLAVE1 << 1)) {
dev_err(&dev, "%s: failed to find serializer at 0x%x or 0x%x\n",
__func__, SER_SLAVE2, SER_SLAVE1);
return -ENODEV;
}
ser_addr = SER_SLAVE1;
}
msleep(100);
priv->ser_addr = ser_addr;
err = max929x_write_reg_list(max929x_Double_Dser_Ser_init,
sizeof(max929x_Double_Dser_Ser_init)/sizeof(struct max929x_reg));
if (err == 0)
dev_dbg(&dev, "%s: success\n", __func__);
else
dev_err(&dev, "%s: fail\n", __func__);
dev_set_drvdata(&client->dev, priv);
return 0;
}
#if defined(NV_I2C_DRIVER_STRUCT_REMOVE_RETURN_TYPE_INT) /* Linux 6.1 */
static int max929x_remove(struct i2c_client *client)
#else
static void max929x_remove(struct i2c_client *client)
#endif
{
struct device dev = client->dev;
gpio_set_value(priv->pwdn_gpio, 0);
dev_dbg(&dev, "%s: \n", __func__);
#if defined(NV_I2C_DRIVER_STRUCT_REMOVE_RETURN_TYPE_INT) /* Linux 6.1 */
return 0;
#endif
}
static const struct i2c_device_id max929x_id[] = {
{ "max929x", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, max929x_id);
const struct of_device_id max929x_of_match[] = {
{ .compatible = "Maxim,max929x", },
{ },
};
MODULE_DEVICE_TABLE(of, max929x_of_match);
static struct i2c_driver max929x_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "max929x",
.of_match_table = of_match_ptr(max929x_of_match),
},
.probe = max929x_probe,
.remove = max929x_remove,
.id_table = max929x_id,
};
module_i2c_driver(max929x_i2c_driver);
MODULE_DESCRIPTION("IO Expander driver max929x");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL v2");

152
drivers/media/i2c/max929x.h Normal file
View File

@@ -0,0 +1,152 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-FileCopyrightText: Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#ifndef __MAX929X_H__
#define __MAX929X_H__
/* TI FPD Link III 954 deser I2C address */
#define TI954_ADDR (0x30)
/* TI FPD Link III 953 ser I2C address */
#define TI953_ADDR (0x18)
/* TI 953 alias address */
#define TI953_CAM1_ADDR (0x29)
#define TI953_CAM2_ADDR (0X2A)
#define MAX9295_DEV_ADDR 0x00
#define SENSOR_ADDR (0x1a)
/* CAM alias address */
#define CAM1_SENSOR_ADDR (0x1b)
#define CAM2_SENSOR_ADDR (0x1c)
#define TI954_RESET_ADDR (0x01)
#define TI954_RESET_VAL (0x02)
#define AFDRV_I2C_ADDR (0x3E)
/*AF ctrl*/
#define AFDRV1_I2C_ADDR (0x21)
#define AFDRV2_I2C_ADDR (0x20)
#define EEPROM_I2C_ADDR (0x50)
/*eeprom ctrl*/
#define EEPROM1_I2C_ADDR (0x51)
#define EEPROM2_I2C_ADDR (0x52)
struct max929x_reg {
u8 slave_addr;
u16 reg;
u8 val;
};
/* Serializer slave addresses */
#define SER_SLAVE1 0x40
#define SER_SLAVE2 0x62
/* Deserializer slave addresses */
#define DESER_SLAVE 0x48
/*
* MAX9296 i2c addr 0x90(8bits) 0x48(7bits)
* (MAX9296 link A) MAX9295 i2c addr 0xc4(8bits) 0x62(7bits)
*/
static struct max929x_reg max929x_Double_Dser_Ser_init[] = {
/* set MFP0 low to reset sensor */
{0x62, 0x02be, 0x80},
/* Set SER to 1x4 mode (phy_config = 0) */
{0x62, 0x0330, 0x00},
{0x62, 0x0332, 0xe4},
/* Additional lane map */
{0x62, 0x0333, 0xe4},
/* Set 4 lanes for serializer (ctrl1_num_lanes = 3) */
{0x62, 0x0331, 0x31},
/* Start video from both port A and port B. */
{0x62, 0x0311, 0x20},
/*
* Enable info lines. Additional start bits for Port A and B.
* Use data from port B for all pipelines
*/
{0x62, 0x0308, 0x62},
/* Route 16bit DCG (DT = 0x30) to VIDEO_X (Bit 6 enable) */
{0x62, 0x0314, 0x22},
/* Route 12bit RAW (DT = 0x2C) to VIDEO_Y (Bit 6 enable) */
{0x62, 0x0316, 0x6c},
/* Route EMBEDDED8 to VIDEO_Z (Bit 6 enable) */
{0x62, 0x0318, 0x22},
/* Unused VIDEO_U */
{0x62, 0x031A, 0x22},
/*
* Make sure all pipelines start transmission
* (VID_TX_EN_X/Y/Z/U = 1)
*/
{0x62, 0x0002, 0x22},
/* Set MIPI Phy Mode: 2x(1x4) mode */
{0x48, 0x0330, 0x04},
/* lane maps - all 4 ports mapped straight */
{0x48, 0x0333, 0x4E},
/* Additional lane map */
{0x48, 0x0334, 0xE4},
/*
* lane count - 0 lanes striping on controller 0
* (Port A slave in 2x1x4 mode).
*/
{0x48, 0x040A, 0x00},
/*
* lane count - 4 lanes striping on controller 1
* (Port A master in 2x1x4 mode).
*/
{0x48, 0x044A, 0xd0},
/*
* lane count - 4 lanes striping on controller 2
* (Port B master in 2x1x4 mode).
*/
{0x48, 0x048A, 0xd0},
/*
* lane count - 0 lanes striping on controller 3
* (Port B slave in 2x1x4 mode).
*/
{0x48, 0x04CA, 0x00},
/*
* MIPI clock rate - 1.5Gbps from controller 0 clock
* (Port A slave in 2x1x4 mode).
*/
{0x48, 0x031D, 0x2f},
/*
* MIPI clock rate - 1.5Gbps from controller 1 clock
* (Port A master in 2x1x4 mode).
*/
{0x48, 0x0320, 0x2f},
/*
* MIPI clock rate - 1.5Gbps from controller 2 clock
* (Port B master in 2x1x4 mode).
*/
{0x48, 0x0323, 0x2f},
/*
* MIPI clock rate - 1.5Gbps from controller 2 clock
* (Port B slave in 2x1x4 mode).
*/
{0x48, 0x0326, 0x2f},
/* Route data from stream 0 to pipe X */
{0x48, 0x0050, 0x00},
/* Route data from stream 0 to pipe Y */
{0x48, 0x0051, 0x01},
/* Route data from stream 0 to pipe Z */
{0x48, 0x0052, 0x02},
/* Route data from stream 0 to pipe U */
{0x48, 0x0053, 0x03},
/* Enable all PHYS. */
{0x48, 0x0332, 0xF0},
/* Enable sensor power down pin. Put imager in,Active mode */
{0x62, 0x02be, 0x90},
/* Output RCLK to sensor. */
{0x62, 0x03F1, 0x89},
/* MFP8 for FSIN */
{0x62, 0x02D8, 0x10},
{0x62, 0x02D6, 0x04},
/* need disable pixel clk out inb order to use MFP1 */
{0x48, 0x0005, 0x00},
/* GPIO TX compensation */
{0x48, 0x02B3, 0x83},
{0x48, 0x02B4, 0x10},
};
#endif

View File

@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* nv_imx219.c - imx219 sensor driver
*
* Copyright (c) 2015-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
*/
#include <nvidia/conftest.h>
@@ -747,6 +746,7 @@ static int imx219_probe(struct i2c_client *client,
err = tegracam_v4l2subdev_register(tc_dev, true);
if (err) {
tegracam_device_unregister(tc_dev);
dev_err(dev, "tegra camera subdev registration failed\n");
return err;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,911 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2018-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <media/max9295.h>
#include <media/max9296.h>
#include <media/tegracam_core.h>
#include "imx390_mode_tbls.h"
#define IMX390_MIN_GAIN (0)
#define IMX390_MAX_GAIN (30)
#define IMX390_MAX_GAIN_REG ((IMX390_MAX_GAIN - IMX390_MIN_GAIN) * 10 / 3)
#define IMX390_DEFAULT_FRAME_LENGTH (1125)
#define IMX390_FRAME_LENGTH_ADDR_MSB 0x200A
#define IMX390_FRAME_LENGTH_ADDR_MID 0x2009
#define IMX390_FRAME_LENGTH_ADDR_LSB 0x2008
#define IMX390_COARSE_TIME_SHS1_ADDR_MSB 0x000E
#define IMX390_COARSE_TIME_SHS1_ADDR_MID 0x000D
#define IMX390_COARSE_TIME_SHS1_ADDR_LSB 0x000C
#define IMX390_COARSE_TIME_SHS2_ADDR_MSB 0x0012
#define IMX390_COARSE_TIME_SHS2_ADDR_MID 0x0011
#define IMX390_COARSE_TIME_SHS2_ADDR_LSB 0x0010
#define IMX390_GROUP_HOLD_ADDR 0x0008
#define IMX390_ANALOG_GAIN_SP1H_ADDR 0x0018
#define IMX390_ANALOG_GAIN_SP1L_ADDR 0x001A
static const struct of_device_id imx390_of_match[] = {
{ .compatible = "sony,imx390",},
{ },
};
MODULE_DEVICE_TABLE(of, imx390_of_match);
static const u32 ctrl_cid_list[] = {
TEGRA_CAMERA_CID_GAIN,
TEGRA_CAMERA_CID_EXPOSURE,
TEGRA_CAMERA_CID_EXPOSURE_SHORT,
TEGRA_CAMERA_CID_FRAME_RATE,
TEGRA_CAMERA_CID_HDR_EN,
};
struct imx390 {
struct i2c_client *i2c_client;
const struct i2c_device_id *id;
struct v4l2_subdev *subdev;
struct device *ser_dev;
struct device *dser_dev;
struct gmsl_link_ctx g_ctx;
u32 frame_length;
struct camera_common_data *s_data;
struct tegracam_device *tc_dev;
};
static const struct regmap_config sensor_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
};
static inline void imx390_get_frame_length_regs(imx390_reg *regs,
u32 frame_length)
{
regs->addr = IMX390_FRAME_LENGTH_ADDR_MSB;
regs->val = (frame_length >> 16) & 0x01;
(regs + 1)->addr = IMX390_FRAME_LENGTH_ADDR_MID;
(regs + 1)->val = (frame_length >> 8) & 0xff;
(regs + 2)->addr = IMX390_FRAME_LENGTH_ADDR_LSB;
(regs + 2)->val = (frame_length) & 0xff;
}
static inline void imx390_get_coarse_time_regs_shs1(imx390_reg *regs,
u32 coarse_time)
{
regs->addr = IMX390_COARSE_TIME_SHS1_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x0f;
(regs + 1)->addr = IMX390_COARSE_TIME_SHS1_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS1_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx390_get_coarse_time_regs_shs2(imx390_reg *regs,
u32 coarse_time)
{
regs->addr = IMX390_COARSE_TIME_SHS2_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x0f;
(regs + 1)->addr = IMX390_COARSE_TIME_SHS2_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS2_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx390_get_gain_reg(imx390_reg *regs,
u16 gain)
{
regs->addr = IMX390_ANALOG_GAIN_SP1H_ADDR;
regs->val = (gain) & 0xff;
(regs + 1)->addr = IMX390_ANALOG_GAIN_SP1H_ADDR + 1;
(regs + 1)->val = (gain >> 8) & 0xff;
(regs + 2)->addr = IMX390_ANALOG_GAIN_SP1L_ADDR;
(regs + 2)->val = (gain) & 0xff;
(regs + 3)->addr = IMX390_ANALOG_GAIN_SP1L_ADDR + 1;
(regs + 3)->val = (gain >> 8) & 0xff;
}
static int test_mode;
module_param(test_mode, int, 0644);
static inline int imx390_read_reg(struct camera_common_data *s_data,
u16 addr, u8 *val)
{
int err = 0;
u32 reg_val = 0;
err = regmap_read(s_data->regmap, addr, &reg_val);
*val = reg_val & 0xFF;
return err;
}
static int imx390_write_reg(struct camera_common_data *s_data,
u16 addr, u8 val)
{
int err;
struct device *dev = s_data->dev;
err = regmap_write(s_data->regmap, addr, val);
if (err)
dev_err(dev, "%s:i2c write failed, 0x%x = %x\n",
__func__, addr, val);
return err;
}
static int imx390_write_table(struct imx390 *priv,
const imx390_reg table[])
{
struct camera_common_data *s_data = priv->s_data;
return regmap_util_write_table_8(s_data->regmap,
table,
NULL, 0,
IMX390_TABLE_WAIT_MS,
IMX390_TABLE_END);
}
static struct mutex serdes_lock__;
static int imx390_gmsl_serdes_setup(struct imx390 *priv)
{
int err = 0;
int des_err = 0;
struct device *dev;
if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client)
return -EINVAL;
dev = &priv->i2c_client->dev;
mutex_lock(&serdes_lock__);
/* For now no separate power on required for serializer device */
max9296_power_on(priv->dser_dev);
/* setup serdes addressing and control pipeline */
err = max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
if (err) {
dev_err(dev, "gmsl deserializer link config failed\n");
goto error;
}
err = max9295_setup_control(priv->ser_dev);
/* proceed even if ser setup failed, to setup deser correctly */
if (err)
dev_err(dev, "gmsl serializer setup failed\n");
des_err = max9296_setup_control(priv->dser_dev, &priv->i2c_client->dev);
if (des_err) {
dev_err(dev, "gmsl deserializer setup failed\n");
/* overwrite err only if deser setup also failed */
err = des_err;
}
error:
mutex_unlock(&serdes_lock__);
return err;
}
static void imx390_gmsl_serdes_reset(struct imx390 *priv)
{
mutex_lock(&serdes_lock__);
/* reset serdes addressing and control pipeline */
max9295_reset_control(priv->ser_dev);
max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev);
max9296_power_off(priv->dser_dev);
mutex_unlock(&serdes_lock__);
}
static int imx390_power_on(struct camera_common_data *s_data)
{
int err = 0;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
struct device *dev = s_data->dev;
dev_dbg(dev, "%s: power on\n", __func__);
if (pdata && pdata->power_on) {
err = pdata->power_on(pw);
if (err)
dev_err(dev, "%s failed.\n", __func__);
else
pw->state = SWITCH_ON;
return err;
}
pw->state = SWITCH_ON;
return 0;
}
static int imx390_power_off(struct camera_common_data *s_data)
{
int err = 0;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
struct device *dev = s_data->dev;
dev_dbg(dev, "%s:\n", __func__);
if (pdata && pdata->power_off) {
err = pdata->power_off(pw);
if (!err)
goto power_off_done;
else
dev_err(dev, "%s failed.\n", __func__);
return err;
}
power_off_done:
pw->state = SWITCH_OFF;
return 0;
}
static int imx390_power_get(struct tegracam_device *tc_dev)
{
struct device *dev = tc_dev->dev;
struct camera_common_data *s_data = tc_dev->s_data;
struct camera_common_power_rail *pw = s_data->power;
struct camera_common_pdata *pdata = s_data->pdata;
const char *mclk_name;
const char *parentclk_name;
struct clk *parent;
int err = 0;
mclk_name = pdata->mclk_name ?
pdata->mclk_name : "cam_mclk1";
pw->mclk = devm_clk_get(dev, mclk_name);
if (IS_ERR(pw->mclk)) {
dev_err(dev, "unable to get clock %s\n", mclk_name);
return PTR_ERR(pw->mclk);
}
parentclk_name = pdata->parentclk_name;
if (parentclk_name) {
parent = devm_clk_get(dev, parentclk_name);
if (IS_ERR(parent)) {
dev_err(dev, "unable to get parent clcok %s",
parentclk_name);
} else {
err = clk_set_parent(pw->mclk, parent);
if (err < 0)
dev_dbg(dev,
"%s failed to set parent clock %d\n",
__func__, err);
}
}
pw->state = SWITCH_OFF;
return err;
}
static int imx390_power_put(struct tegracam_device *tc_dev)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct camera_common_power_rail *pw = s_data->power;
if (unlikely(!pw))
return -EFAULT;
return 0;
}
static int imx390_set_group_hold(struct tegracam_device *tc_dev, bool val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
int err;
err = imx390_write_reg(s_data,
IMX390_GROUP_HOLD_ADDR, val);
if (err) {
dev_dbg(dev,
"%s: Group hold control error\n", __func__);
return err;
}
return 0;
}
static int imx390_set_gain(struct tegracam_device *tc_dev, s64 val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode_prop_idx];
imx390_reg reg_list[4];
int err, i;
u16 gain;
gain = (u16)(val / mode->control_properties.step_gain_val);
dev_dbg(dev, "%s: db: %d\n", __func__, gain);
if (gain > IMX390_MAX_GAIN_REG)
gain = IMX390_MAX_GAIN_REG;
imx390_get_gain_reg(reg_list, gain);
for (i = 0; i < 4; i++) {
err = imx390_write_reg(s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0;
fail:
dev_info(dev, "%s: GAIN control error\n", __func__);
return err;
}
static int imx390_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
/* fixed 30fps */
priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH;
return 0;
}
static int imx390_set_exposure(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode];
imx390_reg reg_list[3];
int err;
u32 coarse_time;
u32 shs1;
int i = 0;
if (priv->frame_length == 0)
priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH;
/* coarse time in lines */
coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] *
priv->frame_length / mode->control_properties.exposure_factor);
shs1 = priv->frame_length - coarse_time;
/* 0 and 1 are prohibited */
if (shs1 < 2)
shs1 = 2;
imx390_get_coarse_time_regs_shs1(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
imx390_get_coarse_time_regs_shs2(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0;
fail:
dev_dbg(&priv->i2c_client->dev,
"%s: set coarse time error\n", __func__);
return err;
}
static struct tegracam_ctrl_ops imx390_ctrl_ops = {
.numctrls = ARRAY_SIZE(ctrl_cid_list),
.ctrl_cid_list = ctrl_cid_list,
.set_gain = imx390_set_gain,
.set_exposure = imx390_set_exposure,
.set_exposure_short = imx390_set_exposure,
.set_frame_rate = imx390_set_frame_rate,
.set_group_hold = imx390_set_group_hold,
};
static struct camera_common_pdata
*imx390_parse_dt(struct tegracam_device *tc_dev)
{
struct device *dev = tc_dev->dev;
struct device_node *node = dev->of_node;
struct camera_common_pdata *board_priv_pdata;
const struct of_device_id *match;
int err;
if (!node)
return NULL;
match = of_match_device(imx390_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find matching dt id\n");
return NULL;
}
board_priv_pdata = devm_kzalloc(dev,
sizeof(*board_priv_pdata), GFP_KERNEL);
err = of_property_read_string(node, "mclk",
&board_priv_pdata->mclk_name);
if (err)
dev_err(dev, "mclk not in DT\n");
return board_priv_pdata;
}
static int imx390_set_mode(struct tegracam_device *tc_dev)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
const struct of_device_id *match;
match = of_match_device(imx390_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find matching dt id\n");
return -EINVAL;
}
if (s_data->mode_prop_idx < 0)
return -EINVAL;
return imx390_write_table(priv, mode_table[s_data->mode_prop_idx]);
}
static int imx390_start_streaming(struct tegracam_device *tc_dev)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct device *dev = tc_dev->dev;
int err;
/* enable serdes streaming */
err = max9295_setup_streaming(priv->ser_dev);
if (err)
goto exit;
err = max9296_setup_streaming(priv->dser_dev, dev);
if (err)
goto exit;
err = max9296_start_streaming(priv->dser_dev, dev);
if (err)
goto exit;
err = imx390_write_table(priv,
mode_table[IMX390_MODE_START_STREAM]);
if (err)
return err;
msleep(20);
return 0;
exit:
dev_err(dev, "%s: error setting stream\n", __func__);
return err;
}
static int imx390_stop_streaming(struct tegracam_device *tc_dev)
{
struct device *dev = tc_dev->dev;
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
/* disable serdes streaming */
max9296_stop_streaming(priv->dser_dev, dev);
return imx390_write_table(priv, mode_table[IMX390_MODE_STOP_STREAM]);
}
static struct camera_common_sensor_ops imx390_common_ops = {
.numfrmfmts = ARRAY_SIZE(imx390_frmfmt),
.frmfmt_table = imx390_frmfmt,
.power_on = imx390_power_on,
.power_off = imx390_power_off,
.write_reg = imx390_write_reg,
.read_reg = imx390_read_reg,
.parse_dt = imx390_parse_dt,
.power_get = imx390_power_get,
.power_put = imx390_power_put,
.set_mode = imx390_set_mode,
.start_streaming = imx390_start_streaming,
.stop_streaming = imx390_stop_streaming,
};
static int imx390_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
dev_dbg(&client->dev, "%s:\n", __func__);
return 0;
}
static const struct v4l2_subdev_internal_ops imx390_subdev_internal_ops = {
.open = imx390_open,
};
static int imx390_board_setup(struct imx390 *priv)
{
struct tegracam_device *tc_dev = priv->tc_dev;
struct device *dev = tc_dev->dev;
struct device_node *node = dev->of_node;
struct device_node *ser_node;
struct i2c_client *ser_i2c = NULL;
struct device_node *dser_node;
struct i2c_client *dser_i2c = NULL;
struct device_node *gmsl;
int value = 0xFFFF;
const char *str_value;
const char *str_value1[2];
int i;
int err;
err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_reg);
if (err < 0) {
dev_err(dev, "reg not found\n");
goto error;
}
err = of_property_read_u32(node, "def-addr",
&priv->g_ctx.sdev_def);
if (err < 0) {
dev_err(dev, "def-addr not found\n");
goto error;
}
ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
if (ser_node == NULL) {
dev_err(dev,
"missing %s handle\n",
"nvidia,gmsl-ser-device");
err = -EINVAL;
goto error;
}
err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
if (err < 0) {
dev_err(dev, "serializer reg not found\n");
goto error;
}
ser_i2c = of_find_i2c_device_by_node(ser_node);
of_node_put(ser_node);
if (ser_i2c == NULL) {
err = -EPROBE_DEFER;
goto error;
}
if (ser_i2c->dev.driver == NULL) {
dev_err(dev, "missing serializer driver\n");
err = -EINVAL;
goto error;
}
priv->ser_dev = &ser_i2c->dev;
dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
if (dser_node == NULL) {
dev_err(dev,
"missing %s handle\n",
"nvidia,gmsl-dser-device");
err = -EINVAL;
goto error;
}
dser_i2c = of_find_i2c_device_by_node(dser_node);
of_node_put(dser_node);
if (dser_i2c == NULL) {
err = -EPROBE_DEFER;
goto error;
}
if (dser_i2c->dev.driver == NULL) {
dev_err(dev, "missing deserializer driver\n");
err = -EINVAL;
goto error;
}
priv->dser_dev = &dser_i2c->dev;
/* populate g_ctx from DT */
gmsl = of_get_child_by_name(node, "gmsl-link");
if (gmsl == NULL) {
dev_err(dev, "missing gmsl-link device node\n");
err = -EINVAL;
goto error;
}
err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
if (err < 0) {
dev_err(dev, "No dst-csi-port found\n");
goto error;
}
priv->g_ctx.dst_csi_port =
(!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
err = of_property_read_string(gmsl, "src-csi-port", &str_value);
if (err < 0) {
dev_err(dev, "No src-csi-port found\n");
goto error;
}
priv->g_ctx.src_csi_port =
(!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
err = of_property_read_string(gmsl, "csi-mode", &str_value);
if (err < 0) {
dev_err(dev, "No csi-mode found\n");
goto error;
}
if (!strcmp(str_value, "1x4")) {
priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
} else if (!strcmp(str_value, "2x4")) {
priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
} else if (!strcmp(str_value, "4x2")) {
priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
} else if (!strcmp(str_value, "2x2")) {
priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
} else {
dev_err(dev, "invalid csi mode\n");
err = -EINVAL;
goto error;
}
err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
if (err < 0) {
dev_err(dev, "No serdes-csi-link found\n");
goto error;
}
priv->g_ctx.serdes_csi_link =
(!strcmp(str_value, "a")) ?
GMSL_SERDES_CSI_LINK_A : GMSL_SERDES_CSI_LINK_B;
err = of_property_read_u32(gmsl, "st-vc", &value);
if (err < 0) {
dev_err(dev, "No st-vc info\n");
goto error;
}
priv->g_ctx.st_vc = value;
err = of_property_read_u32(gmsl, "vc-id", &value);
if (err < 0) {
dev_err(dev, "No vc-id info\n");
goto error;
}
priv->g_ctx.dst_vc = value;
err = of_property_read_u32(gmsl, "num-lanes", &value);
if (err < 0) {
dev_err(dev, "No num-lanes info\n");
goto error;
}
priv->g_ctx.num_csi_lanes = value;
priv->g_ctx.num_streams =
of_property_count_strings(gmsl, "streams");
if (priv->g_ctx.num_streams <= 0) {
dev_err(dev, "No streams found\n");
err = -EINVAL;
goto error;
}
for (i = 0; i < priv->g_ctx.num_streams; i++) {
err = of_property_read_string_index(gmsl, "streams", i,
&str_value1[i]);
if (err < 0) {
dev_err(dev, "Failed to get streams index\n");
goto error;
}
if (!str_value1[i]) {
dev_err(dev, "invalid stream info\n");
err = -EINVAL;
goto error;
}
if (!strcmp(str_value1[i], "raw12")) {
priv->g_ctx.streams[i].st_data_type =
GMSL_CSI_DT_RAW_12;
} else if (!strcmp(str_value1[i], "embed")) {
priv->g_ctx.streams[i].st_data_type =
GMSL_CSI_DT_EMBED;
} else if (!strcmp(str_value1[i], "ued-u1")) {
priv->g_ctx.streams[i].st_data_type =
GMSL_CSI_DT_UED_U1;
} else {
dev_err(dev, "invalid stream data type\n");
err = -EINVAL;
goto error;
}
}
priv->g_ctx.s_dev = dev;
return 0;
error:
return err;
}
#if defined(NV_I2C_DRIVER_STRUCT_PROBE_WITHOUT_I2C_DEVICE_ID_ARG) /* Linux 6.3 */
static int imx390_probe(struct i2c_client *client)
#else
static int imx390_probe(struct i2c_client *client,
const struct i2c_device_id *id)
#endif
{
struct device *dev = &client->dev;
struct device_node *node = dev->of_node;
struct tegracam_device *tc_dev;
struct imx390 *priv;
int err;
dev_info(dev, "probing v4l2 sensor.\n");
if (!IS_ENABLED(CONFIG_OF) || !node)
return -EINVAL;
priv = devm_kzalloc(dev, sizeof(struct imx390), GFP_KERNEL);
if (!priv)
return -ENOMEM;
tc_dev = devm_kzalloc(dev,
sizeof(struct tegracam_device), GFP_KERNEL);
if (!tc_dev)
return -ENOMEM;
priv->i2c_client = tc_dev->client = client;
tc_dev->dev = dev;
strscpy(tc_dev->name, "imx390", sizeof(tc_dev->name));
tc_dev->dev_regmap_config = &sensor_regmap_config;
tc_dev->sensor_ops = &imx390_common_ops;
tc_dev->v4l2sd_internal_ops = &imx390_subdev_internal_ops;
tc_dev->tcctrl_ops = &imx390_ctrl_ops;
err = tegracam_device_register(tc_dev);
if (err) {
dev_err(dev, "tegra camera driver registration failed\n");
return err;
}
priv->tc_dev = tc_dev;
priv->s_data = tc_dev->s_data;
priv->subdev = &tc_dev->s_data->subdev;
tegracam_set_privdata(tc_dev, (void *)priv);
err = imx390_board_setup(priv);
if (err) {
tegracam_device_unregister(tc_dev);
dev_err(dev, "board setup failed\n");
return err;
}
mutex_init(&serdes_lock__);
/* Pair sensor to serializer dev */
err = max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
if (err) {
dev_err(&client->dev, "gmsl ser pairing failed\n");
return err;
}
/* Register sensor to deserializer dev */
err = max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
if (err) {
dev_err(&client->dev, "gmsl deserializer register failed\n");
return err;
}
/*
* gmsl serdes setup
*
* Sensor power on/off should be the right place for serdes
* setup/reset. But the problem is, the total required delay
* in serdes setup/reset exceeds the frame wait timeout, looks to
* be related to multiple channel open and close sequence
* issue (#BUG 200477330).
* Once this bug is fixed, these may be moved to power on/off.
* The delays in serdes is as per guidelines and can't be reduced,
* so it is placed in probe/remove, though for that, deserializer
* would be powered on always post boot, until 1.2v is supplied
* to deserializer from CVB.
*/
err = imx390_gmsl_serdes_setup(priv);
if (err) {
dev_err(&client->dev,
"%s gmsl serdes setup failed\n", __func__);
return err;
}
err = tegracam_v4l2subdev_register(tc_dev, true);
if (err) {
dev_err(dev, "tegra camera subdev registration failed\n");
return err;
}
dev_info(&client->dev, "Detected IMX390 sensor\n");
return 0;
}
#if defined(NV_I2C_DRIVER_STRUCT_REMOVE_RETURN_TYPE_INT) /* Linux 6.1 */
static int imx390_remove(struct i2c_client *client)
#else
static void imx390_remove(struct i2c_client *client)
#endif
{
struct camera_common_data *s_data = to_camera_common_data(&client->dev);
struct imx390 *priv;
if (!s_data)
#if defined(NV_I2C_DRIVER_STRUCT_REMOVE_RETURN_TYPE_INT) /* Linux 6.1 */
return -EINVAL;
#else
return;
#endif
priv = (struct imx390 *)s_data->priv;
imx390_gmsl_serdes_reset(priv);
mutex_destroy(&serdes_lock__);
tegracam_v4l2subdev_unregister(priv->tc_dev);
tegracam_device_unregister(priv->tc_dev);
#if defined(NV_I2C_DRIVER_STRUCT_REMOVE_RETURN_TYPE_INT) /* Linux 6.1 */
return 0;
#endif
}
static const struct i2c_device_id imx390_id[] = {
{ "imx390", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, imx390_id);
static struct i2c_driver imx390_i2c_driver = {
.driver = {
.name = "imx390",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(imx390_of_match),
},
.probe = imx390_probe,
.remove = imx390_remove,
.id_table = imx390_id,
};
module_i2c_driver(imx390_i2c_driver);
MODULE_DESCRIPTION("Media Controller driver for Sony IMX390");
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_AUTHOR("Sudhir Vyas <svyas@nvidia.com");
MODULE_LICENSE("GPL v2");

View File

@@ -775,6 +775,7 @@ static int imx477_probe(struct i2c_client *client,
err = tegracam_v4l2subdev_register(tc_dev, true);
if (err) {
tegracam_device_unregister(tc_dev);
dev_err(dev, "tegra camera subdev registration failed\n");
return err;
}

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* virtual_i2c_mux.c - virtual i2c mux driver for P3762 & P3783 GMSL boards.
*/
@@ -87,7 +87,11 @@ static int virtual_i2c_mux_probe(struct i2c_client *client,
for (chan = 0; chan < children; chan++) {
pr_info("%s: chan = %d\n",__func__, chan);
#if defined(NV_I2C_MUX_ADD_ADAPTER_HAS_NO_CLASS_ARG)
ret = i2c_mux_add_adapter(muxc, 0, chan);
#else
ret = i2c_mux_add_adapter(muxc, 0, chan, 0);
#endif
if (ret)
goto err_children;
}

View File

@@ -1,8 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
/*
* camera_common.c - utilities for tegra camera driver
// SPDX-License-Identifier: GPL-2.0 only
/* SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* Copyright (c) 2015-2023, NVIDIA CORPORATION. All rights reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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/>.
*/
#include <linux/types.h>
#include <media/tegra-v4l2-camera.h>
@@ -44,6 +54,11 @@ static const struct camera_common_colorfmt camera_common_color_fmts[] = {
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SGBRG12
},
{
MEDIA_BUS_FMT_SBGGR12_1X12,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SBGGR12
},
{
MEDIA_BUS_FMT_SRGGB10_1X10,
V4L2_COLORSPACE_SRGB,

View File

@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* NVIDIA Tegra CSI Device
*
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -687,7 +686,7 @@ static int tegra_csi_set_format(struct v4l2_subdev *subdev,
}
static int tegra_csi_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *vfi)
@@ -721,13 +720,13 @@ static int tegra_csi_enum_mbus_code(struct v4l2_subdev *sd,
static struct v4l2_subdev_video_ops tegra_csi_video_ops = {
.s_stream = tegra_csi_s_stream,
.g_input_status = tegra_csi_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = tegra_csi_g_frame_interval,
#endif
};
static struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = tegra_csi_g_frame_interval,
#endif
.get_fmt = tegra_csi_get_format,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2023 NVIDIA Corporation. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/**
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c
@@ -14,7 +14,7 @@
#include <linux/nvhost.h>
#include <linux/of_platform.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/tegra-capture-ivc.h>
#include <asm/arch_timer.h>
#include <soc/tegra/fuse.h>

View File

@@ -17,7 +17,7 @@
#include <linux/of_platform.h>
#include <linux/nvhost.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>

View File

@@ -1,5 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/* SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*/
/**
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c
@@ -12,7 +24,7 @@
#include <linux/nvhost.h>
#include <linux/of_platform.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/tegra-capture-ivc.h>
#include <linux/tegra-camera-rtcpu.h>
@@ -1438,7 +1450,12 @@ int vi_capture_status(
/* negative timeout means wait forever */
if (timeout_ms < 0) {
wait_for_completion(&capture->capture_resp);
ret = wait_for_completion_interruptible(&capture->capture_resp);
if (ret == -ERESTARTSYS) {
dev_dbg(chan->dev,
"capture status interrupted\n");
return -ETIMEDOUT;
}
} else {
ret = wait_for_completion_timeout(
&capture->capture_resp,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* Copyright (c) 2016-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* Tegra CSI5 device common APIs
*/
@@ -213,6 +213,7 @@ static int csi5_stream_set_config(struct tegra_csi_channel *chan, u32 stream_id,
struct CAPTURE_CONTROL_MSG msg;
struct nvcsi_brick_config brick_config;
struct nvcsi_cil_config cil_config;
struct nvcsi_error_config err_config;
u32 phy_mode = read_phy_mode_from_dt(chan);
bool is_cphy = (phy_mode == CSI_PHY_MODE_CPHY);
dev_dbg(csi->dev, "%s: stream_id=%u, csi_port=%u\n",
@@ -285,6 +286,7 @@ static int csi5_stream_set_config(struct tegra_csi_channel *chan, u32 stream_id,
else
cil_config.mipi_clock_rate = csi->clk_freq / 1000;
memset(&err_config, 0, sizeof(err_config));
/* Set NVCSI stream config */
memset(&msg, 0, sizeof(msg));
msg.header.msg_id = CAPTURE_CSI_STREAM_SET_CONFIG_REQ;
@@ -293,6 +295,9 @@ static int csi5_stream_set_config(struct tegra_csi_channel *chan, u32 stream_id,
msg.csi_stream_set_config_req.csi_port = csi_port;
msg.csi_stream_set_config_req.brick_config = brick_config;
msg.csi_stream_set_config_req.cil_config = cil_config;
msg.csi_stream_set_config_req.error_config = err_config;
msg.csi_stream_set_config_req.config_flags = NVCSI_CONFIG_FLAG_BRICK |
NVCSI_CONFIG_FLAG_CIL | NVCSI_CONFIG_FLAG_ERROR;
if (tegra_chan->valid_ports > 1)
vi_port = (stream_id > 0) ? 1 : 0;

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* tegracam_v4l2 - tegra camera framework for v4l2 support
*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/types.h>
#include <media/tegra-v4l2-camera.h>
#include <media/tegracam_core.h>
@@ -112,9 +114,30 @@ static int v4l2sd_g_input_status(struct v4l2_subdev *sd, u32 *status)
return 0;
}
static int cam_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *ival)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct camera_common_data *s_data = to_camera_common_data(&client->dev);
if (!s_data)
return -EINVAL;
ival->interval.denominator = s_data->frmfmt[s_data->mode_prop_idx].framerates[0];
ival->interval.numerator = 1;
return 0;
}
static struct v4l2_subdev_video_ops v4l2sd_video_ops = {
.s_stream = v4l2sd_stream,
.g_input_status = v4l2sd_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = cam_g_frame_interval,
.s_frame_interval = cam_g_frame_interval,
#endif
};
static struct v4l2_subdev_core_ops v4l2sd_core_ops = {
@@ -161,6 +184,10 @@ static int v4l2sd_set_fmt(struct v4l2_subdev *sd,
}
static struct v4l2_subdev_pad_ops v4l2sd_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = cam_g_frame_interval,
.set_frame_interval = cam_g_frame_interval,
#endif
.set_fmt = v4l2sd_set_fmt,
.get_fmt = v4l2sd_get_fmt,
.enum_mbus_code = camera_common_enum_mbus_code,

View File

@@ -4,6 +4,8 @@
* NVIDIA Tegra Video Input Device
*/
#include <nvidia/conftest.h>
#include <linux/atomic.h>
#include <linux/bitmap.h>
#include <linux/clk.h>
@@ -23,6 +25,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
#include <media/tegra-v4l2-camera.h>
@@ -689,16 +692,33 @@ tegra_channel_queue_setup(struct vb2_queue *vq,
{
struct tegra_channel *chan = vb2_get_drv_priv(vq);
struct tegra_mc_vi *vi = chan->vi;
int ret = 0;
/* In some cases, if nplanes is valid
* and the requested image size is less than the
* actual image size, we need to return EINVAL.
* Previously, we were just updating sizes[0] irrespective
* of the requested image size. Although this did not harm the
* flow, according to "v4l2-compliance", we need to check if
* the requested size is invalid.
*/
if (*nplanes) {
if (sizes[0] < chan->format.sizeimage) {
pr_err("%s: sizes[0] = %d chan->format.sizeimage = %d ...\n"
,__func__,sizes[0],chan->format.sizeimage);
return -EINVAL;
}
} else {
sizes[0] = chan->format.sizeimage;
}
*nplanes = 1;
sizes[0] = chan->format.sizeimage;
alloc_devs[0] = tegra_channel_get_vi_unit(chan);
if (vi->fops && vi->fops->vi_setup_queue)
return vi->fops->vi_setup_queue(chan, nbuffers);
else
return -EINVAL;
return ret;
}
int tegra_channel_alloc_buffer_queue(struct tegra_channel *chan,
@@ -1157,11 +1177,19 @@ tegra_channel_g_dv_timings(struct file *file, void *fh,
{
struct tegra_channel *chan = video_drvdata(file);
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
if (!v4l2_subdev_has_op(chan->subdev_on_csi, pad, g_dv_timings))
return -ENOTTY;
return v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, pad, g_dv_timings, 0, timings);
#else
if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, g_dv_timings))
return -ENOTTY;
return v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, video, g_dv_timings, timings);
#endif
}
static int
@@ -1173,7 +1201,11 @@ tegra_channel_s_dv_timings(struct file *file, void *fh,
struct v4l2_dv_timings curr_timings;
int ret;
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
if (!v4l2_subdev_has_op(chan->subdev_on_csi, pad, s_dv_timings))
#else
if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, s_dv_timings))
#endif
return -ENOTTY;
ret = tegra_channel_g_dv_timings(file, fh, &curr_timings);
@@ -1186,9 +1218,13 @@ tegra_channel_s_dv_timings(struct file *file, void *fh,
if (vb2_is_busy(&chan->queue))
return -EBUSY;
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
ret = v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, pad, s_dv_timings, 0, timings);
#else
ret = v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, video, s_dv_timings, timings);
#endif
if (!ret)
tegra_channel_update_format(chan, bt->width, bt->height,
chan->fmtinfo->fourcc, &chan->fmtinfo->bpp,
@@ -1206,11 +1242,19 @@ tegra_channel_query_dv_timings(struct file *file, void *fh,
{
struct tegra_channel *chan = video_drvdata(file);
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
if (!v4l2_subdev_has_op(chan->subdev_on_csi, pad, query_dv_timings))
return -ENOTTY;
return v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, pad, query_dv_timings, 0, timings);
#else
if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, query_dv_timings))
return -ENOTTY;
return v4l2_device_call_until_err(chan->video->v4l2_dev,
chan->grp_id, video, query_dv_timings, timings);
#endif
}
static int
@@ -1257,6 +1301,10 @@ int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
}
break;
case TEGRA_CAMERA_CID_VI_BYPASS_MODE:
/* Prevent changing the bypass mode while the device is still streaming */
if (vb2_is_busy(&chan->queue))
return -EBUSY;
if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON)
chan->bypass = true;
else if (chan->vi->bypass) {
@@ -1843,8 +1891,13 @@ static void tegra_channel_populate_dev_info(struct tegra_camera_dev_info *cdev,
if (chan->pg_mode) {
/* TPG mode */
cdev->sensor_type = SENSORTYPE_VIRTUAL;
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
} else if (v4l2_subdev_has_op(chan->subdev_on_csi,
pad, g_dv_timings)) {
#else
} else if (v4l2_subdev_has_op(chan->subdev_on_csi,
video, g_dv_timings)) {
#endif
/* HDMI-IN */
cdev->sensor_type = SENSORTYPE_OTHER;
pixelclock = tegra_channel_get_max_source_rate();
@@ -2171,7 +2224,11 @@ tegra_channel_enum_input(struct file *file, void *fh, struct v4l2_input *inp)
return -ENODEV;
inp->type = V4L2_INPUT_TYPE_CAMERA;
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_DV_TIMINGS) /* Linux v6.10 */
if (v4l2_subdev_has_op(sd_on_csi, pad, s_dv_timings)) {
#else
if (v4l2_subdev_has_op(sd_on_csi, video, s_dv_timings)) {
#endif
inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
len = snprintf(inp->name,
sizeof(inp->name), "HDMI %u",
@@ -2216,7 +2273,7 @@ static long tegra_channel_default_ioctl(struct file *file, void *fh,
{
struct tegra_channel *chan = video_drvdata(file);
struct tegra_mc_vi *vi = chan->vi;
long ret = 0;
long ret = -ENOTTY;
if (vi->fops && vi->fops->vi_default_ioctl)
ret = vi->fops->vi_default_ioctl(file, fh, use_prio, cmd, arg);
@@ -2224,10 +2281,32 @@ static long tegra_channel_default_ioctl(struct file *file, void *fh,
return ret;
}
/* Implemented vidioc_s_parm and vidioc_g_parm ioctl to support multiple frame
* rates */
static int tegra_channel_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_s_parm_cap(chan->video, sd, a);
}
static int tegra_channel_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_g_parm_cap(chan->video, sd, a);
}
static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = {
.vidioc_querycap = tegra_channel_querycap,
.vidioc_enum_framesizes = tegra_channel_enum_framesizes,
.vidioc_enum_frameintervals = tegra_channel_enum_frameintervals,
.vidioc_s_parm = tegra_channel_s_parm,
.vidioc_g_parm = tegra_channel_g_parm,
.vidioc_enum_fmt_vid_cap = tegra_channel_enum_format,
.vidioc_g_fmt_vid_cap = tegra_channel_get_format,
.vidioc_s_fmt_vid_cap = tegra_channel_set_format,

View File

@@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
/*
/* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* Tegra Video Input 5 device common APIs
*
* Copyright (c) 2016-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* Author: Frank Chen <frank@nvidia.com>
*
* 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 <linux/errno.h>
@@ -134,6 +140,9 @@ static int tegra_vi5_s_ctrl(struct v4l2_ctrl *ctrl)
case TEGRA_CAMERA_CID_WRITE_ISPFORMAT:
chan->write_ispformat = ctrl->val;
break;
case TEGRA_CAMERA_CID_VI_CAPTURE_TIMEOUT:
chan->capture_timeout_ms = ctrl->val;
break;
default:
dev_err(&chan->video->dev, "%s:Not valid ctrl\n", __func__);
return -EINVAL;
@@ -200,6 +209,16 @@ static const struct v4l2_ctrl_config vi5_custom_ctrls[] = {
.step = 1,
.dims = { SENSOR_CTRL_BLOB_SIZE },
},
{
.ops = &vi5_ctrl_ops,
.id = TEGRA_CAMERA_CID_VI_CAPTURE_TIMEOUT,
.name = "Override capture timeout ms",
.type = V4L2_CTRL_TYPE_INTEGER,
.def = CAPTURE_TIMEOUT_MS,
.min = -1,
.max = 0x7FFFFFFF,
.step = 1,
},
};
static int vi5_add_ctrls(struct tegra_channel *chan)
@@ -497,6 +516,7 @@ static void vi5_capture_dequeue(struct tegra_channel *chan,
unsigned long flags;
struct tegra_mc_vi *vi = chan->vi;
struct vb2_v4l2_buffer *vb = &buf->buf;
int timeout_ms = CAPTURE_TIMEOUT_MS;
struct timespec64 ts;
struct capture_descriptor *descr = NULL;
@@ -507,12 +527,21 @@ static void vi5_capture_dequeue(struct tegra_channel *chan,
goto rel_buf;
/* Dequeue a frame and check its capture status */
err = vi_capture_status(chan->tegra_vi_channel[vi_port], CAPTURE_TIMEOUT_MS);
timeout_ms = chan->capture_timeout_ms;
err = vi_capture_status(chan->tegra_vi_channel[vi_port], timeout_ms);
if (err) {
if (err == -ETIMEDOUT) {
dev_err(vi->dev,
"uncorr_err: request timed out after %d ms\n",
CAPTURE_TIMEOUT_MS);
if (timeout_ms < 0) {
spin_lock_irqsave(&chan->capture_state_lock, flags);
chan->capture_state = CAPTURE_ERROR_TIMEOUT;
spin_unlock_irqrestore(&chan->capture_state_lock, flags);
buf->vb2_state = VB2_BUF_STATE_ERROR;
goto rel_buf;
} else {
dev_err(vi->dev,
"uncorr_err: request timed out after %d ms\n",
timeout_ms);
}
} else {
dev_err(vi->dev, "uncorr_err: request err %d\n", err);
}
@@ -702,6 +731,7 @@ static int tegra_channel_kthread_capture_dequeue(void *data)
struct tegra_channel_buffer *buf;
set_freezable();
allow_signal(SIGINT);
while (1) {
try_to_freeze();
@@ -722,6 +752,12 @@ static int tegra_channel_kthread_capture_dequeue(void *data)
}
spin_lock_irqsave(&chan->capture_state_lock, flags);
if (chan->capture_state == CAPTURE_ERROR_TIMEOUT) {
spin_unlock_irqrestore(&chan->capture_state_lock,
flags);
break;
}
if (chan->capture_state == CAPTURE_ERROR) {
spin_unlock_irqrestore(&chan->capture_state_lock,
flags);
@@ -791,6 +827,7 @@ static void vi5_channel_stop_kthreads(struct tegra_channel *chan)
/* Stop the kthread for capture dequeue */
if (chan->kthread_capture_dequeue) {
send_sig(SIGINT, chan->kthread_capture_dequeue, 1);
kthread_stop(chan->kthread_capture_dequeue);
chan->kthread_capture_dequeue = NULL;
}

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */
/* Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */
/*
* cam_cdi_tsc.c - tsc driver.
*/
@@ -147,6 +147,8 @@ struct tsc_signal_controller {
} debugfs;
const struct tsc_signal_controller_features *features;
struct list_head generators;
bool opened;
};
static const struct tsc_signal_controller_features tegra234_tsc_features = {
@@ -458,22 +460,44 @@ static void cdi_tsc_debugfs_remove(struct tsc_signal_controller *controller)
static int cdi_tsc_chardev_open(struct inode *inode, struct file *file)
{
pr_info("%s:Device opened\n", __func__);
struct tsc_signal_controller *controller = dev_get_drvdata(tsc_charDevice);
int err = 0;
/* Set External Fsync */
Hawk_Owl_Fsync_program(EXTERNAL_FSYNC);
if (controller->opened)
return -EBUSY;
return 0;
/* Make sure device opened only once */
controller->opened = true;
/* Set External Fsync */
err = Hawk_Owl_Fsync_program(EXTERNAL_FSYNC);
if (err)
controller->opened = false;
else
dev_dbg(controller->dev, "%s:Device opened successfully!! \n", __func__);
return err;
}
static int cdi_tsc_chardev_release(struct inode *inode, struct file *file)
{
pr_info("%s:Device closed\n", __func__);
struct tsc_signal_controller *controller = dev_get_drvdata(tsc_charDevice);
int err = -EFAULT;
/* To make sure whenever the device is closed, tsc is also stopped
* to avoid inconsistency behaviour at app level i.e to avoid out of sync.
*/
err = cdi_tsc_stop_generators(controller);
if (err)
return err;
/* Set back to Internal Fsync */
Hawk_Owl_Fsync_program(INTERNAL_FSYNC);
err = Hawk_Owl_Fsync_program(INTERNAL_FSYNC);
return 0;
controller->opened = false;
dev_dbg(controller->dev, "%s Device closed ..\n", __func__);
return err;
}
static long cdi_tsc_chardev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -520,6 +544,7 @@ static int cdi_tsc_probe(struct platform_device *pdev)
if (!controller)
return -ENOMEM;
controller->opened = false;
controller->dev = &pdev->dev;
controller->features = of_device_get_match_data(&pdev->dev);
if (controller->features == NULL) {

View File

@@ -1,11 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#ifndef __CDI_PWM_PRIV_H__
#define __CDI_PWM_PRIV_H__
struct cdi_pwm_info {
#if !defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
struct pwm_chip chip;
#endif
struct pwm_device *pwm;
atomic_t in_use;
struct mutex mutex;

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -33,7 +33,11 @@ static int of_cdi_gpio_pdata(struct platform_device *pdev,
return err;
}
#if defined(NV_GPIO_DEVICE_FIND_HAS_CONST_DATA_ARG) /* Linux v6.9 */
static int cdi_gpio_chip_match(struct gpio_chip *chip, const void *data)
#else
static int cdi_gpio_chip_match(struct gpio_chip *chip, void *data)
#endif
{
return !strcmp(chip->label, data);
}
@@ -42,7 +46,8 @@ static struct gpio_chip *cdi_gpio_get_chip(struct platform_device *pdev,
struct cdi_gpio_plat_data *pd)
{
struct gpio_chip *gc = NULL;
#if !defined(NV_GPIOCHIP_FIND_PRESENT) /* Linux 6.7 */
#if defined(NV_GPIO_DEVICE_FIND_PRESENT) && \
defined(NV_GPIO_DEVICE_GET_CHIP_PRESENT) /* Linux 6.7 */
struct gpio_device *gdev;
#endif
char name[MAX_STR_SIZE];
@@ -54,14 +59,15 @@ static struct gpio_chip *cdi_gpio_get_chip(struct platform_device *pdev,
}
strcpy(name, pd->gpio_prnt_chip);
#if defined(NV_GPIOCHIP_FIND_PRESENT) /* Linux 6.7 */
gc = gpiochip_find(name, cdi_gpio_chip_match);
#else
#if defined(NV_GPIO_DEVICE_FIND_PRESENT) && \
defined(NV_GPIO_DEVICE_GET_CHIP_PRESENT) /* Linux 6.7 */
gdev = gpio_device_find(name, cdi_gpio_chip_match);
if (gdev) {
gc = gpio_device_get_chip(gdev);
gpio_device_put(gdev);
}
#else
gc = gpiochip_find(name, cdi_gpio_chip_match);
#endif
if (!gc) {
dev_err(&pdev->dev, "%s: unable to find gpio parent chip %s\n",

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -30,7 +30,11 @@ static const struct of_device_id cdi_pwm_of_match[] = {
static inline struct cdi_pwm_info *to_cdi_pwm_info(struct pwm_chip *chip)
{
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
return pwmchip_get_drvdata(chip);
#else
return container_of(chip, struct cdi_pwm_info, chip);
#endif
}
#if KERNEL_VERSION(6, 0, 0) > LINUX_VERSION_CODE
@@ -95,30 +99,38 @@ static struct pwm_device *of_cdi_pwm_xlate(struct pwm_chip *pc,
{
struct pwm_device *pwm;
struct cdi_pwm_info *info = to_cdi_pwm_info(pc);
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
struct device *dev = &pc->dev;
#else
struct device *dev = pc->dev;
#endif
int err = 0;
pwm = pwm_request_from_chip(pc, args->args[0], NULL);
if (!args->args[1]) {
dev_err(pc->dev, "Period should be larger than 0\n");
pwm = of_pwm_xlate_with_flags(pc, args);
if (IS_ERR(pwm))
return NULL;
if (!pwm->args.period) {
dev_err(dev, "Period should be larger than 0\n");
return NULL;
}
if (info->force_on) {
err = pwm_config(info->pwm, args->args[1]/4, args->args[1]);
if (err) {
dev_err(pc->dev, "can't config PWM: %d\n", err);
dev_err(dev, "can't config PWM: %d\n", err);
return NULL;
}
err = pwm_enable(info->pwm);
if (err) {
dev_err(pc->dev, "can't enable PWM: %d\n", err);
dev_err(dev, "can't enable PWM: %d\n", err);
return NULL;
}
} else {
err = pwm_config(pwm, args->args[1]/4, args->args[1]);
if (err) {
dev_err(pc->dev, "can't config PWM: %d\n", err);
dev_err(dev, "can't config PWM: %d\n", err);
return NULL;
}
}
@@ -140,50 +152,60 @@ static const struct pwm_ops cdi_pwm_ops = {
static int cdi_pwm_probe(struct platform_device *pdev)
{
struct cdi_pwm_info *info = NULL;
struct pwm_chip *chip;
int err = 0, npwm;
bool force_on = false;
dev_info(&pdev->dev, "%sing...\n", __func__);
info = devm_kzalloc(
&pdev->dev, sizeof(struct cdi_pwm_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
atomic_set(&info->in_use, 0);
mutex_init(&info->mutex);
err = of_property_read_u32(pdev->dev.of_node, "npwm", &npwm);
if (err < 0) {
dev_err(&pdev->dev, "npwm is not defined: %d\n", err);
return err;
}
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*info));
if (IS_ERR(chip))
return PTR_ERR(chip);
info = to_cdi_pwm_info(chip);
#else
info = devm_kzalloc(
&pdev->dev, sizeof(struct cdi_pwm_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
chip = &info->chip;
chip->dev = &pdev->dev;
chip->npwm = npwm;
#endif
atomic_set(&info->in_use, 0);
mutex_init(&info->mutex);
force_on = of_property_read_bool(pdev->dev.of_node, "force_on");
info->chip.dev = &pdev->dev;
info->chip.ops = &cdi_pwm_ops;
chip->ops = &cdi_pwm_ops;
#if defined(NV_PWM_CHIP_STRUCT_HAS_BASE_ARG)
info->chip.base = -1;
chip->base = -1;
#endif
info->chip.npwm = npwm;
info->chip.of_xlate = of_cdi_pwm_xlate;
chip->of_xlate = of_cdi_pwm_xlate;
info->force_on = force_on;
err = pwmchip_add(&info->chip);
err = pwmchip_add(chip);
if (err < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", err);
return err;
}
platform_set_drvdata(pdev, info);
platform_set_drvdata(pdev, chip);
info->pwm = devm_pwm_get(&pdev->dev, NULL);
if (!IS_ERR(info->pwm)) {
pwm_disable(info->pwm);
dev_info(&pdev->dev, "%s success to get PWM\n", __func__);
} else {
pwmchip_remove(&info->chip);
pwmchip_remove(chip);
err = PTR_ERR(info->pwm);
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev,
@@ -195,24 +217,24 @@ static int cdi_pwm_probe(struct platform_device *pdev)
static int cdi_pwm_remove(struct platform_device *pdev)
{
struct cdi_pwm_info *info = platform_get_drvdata(pdev);
struct pwm_chip *chip = platform_get_drvdata(pdev);
pwmchip_remove(&info->chip);
pwmchip_remove(chip);
return 0;
}
static int cdi_pwm_suspend(struct device *dev)
{
int err = 0;
struct cdi_pwm_info *info = dev_get_drvdata(dev);
struct pwm_chip *chip = dev_get_drvdata(dev);
struct cdi_pwm_info *info = to_cdi_pwm_info(chip);
if (info == NULL) {
dev_err(dev, "%s: fail to get info\n", __func__);
} else {
if (!IS_ERR(info->pwm)) {
pwm_disable(info->pwm);
err = pwm_config(info->pwm, PWM_SUSPEND_DUTY_RATIO,
pwm_config(info->pwm, PWM_SUSPEND_DUTY_RATIO,
PWM_SUSPEND_PERIOD);
}
}

View File

@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
/* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#ifndef __ISC_PWM_PRIV_H__
#define __ISC_PWM_PRIV_H__
struct isc_pwm_info {
#if !defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
struct pwm_chip chip;
#endif
struct pwm_device *pwm;
atomic_t in_use;
struct mutex mutex;

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -33,7 +33,11 @@ static int of_isc_gpio_pdata(struct platform_device *pdev,
return err;
}
#if defined(NV_GPIO_DEVICE_FIND_HAS_CONST_DATA_ARG) /* Linux v6.9 */
static int isc_gpio_chip_match(struct gpio_chip *chip, const void *data)
#else
static int isc_gpio_chip_match(struct gpio_chip *chip, void *data)
#endif
{
return !strcmp(chip->label, data);
}
@@ -43,7 +47,8 @@ static struct gpio_chip *isc_gpio_get_chip(struct platform_device *pdev,
{
struct gpio_chip *gc = NULL;
char name[MAX_STR_SIZE];
#if !defined(NV_GPIOCHIP_FIND_PRESENT) /* Linux 6.7 */
#if defined(NV_GPIO_DEVICE_FIND_PRESENT) && \
defined(NV_GPIO_DEVICE_GET_CHIP_PRESENT) /* Linux 6.7 */
struct gpio_device *gdev;
#endif
@@ -54,14 +59,15 @@ static struct gpio_chip *isc_gpio_get_chip(struct platform_device *pdev,
}
strcpy(name, pd->gpio_prnt_chip);
#if defined(NV_GPIOCHIP_FIND_PRESENT) /* Linux 6.7 */
gc = gpiochip_find(name, isc_gpio_chip_match);
#else
#if defined(NV_GPIO_DEVICE_FIND_PRESENT) && \
defined(NV_GPIO_DEVICE_GET_CHIP_PRESENT) /* Linux 6.7 */
gdev = gpio_device_find(name, isc_gpio_chip_match);
if (gdev) {
gc = gpio_device_get_chip(gdev);
gpio_device_put(gdev);
}
#else
gc = gpiochip_find(name, isc_gpio_chip_match);
#endif
if (!gc) {
dev_err(&pdev->dev, "%s: unable to find gpio parent chip %s\n",

View File

@@ -30,7 +30,11 @@ static const struct of_device_id isc_pwm_of_match[] = {
static inline struct isc_pwm_info *to_isc_pwm_info(struct pwm_chip *chip)
{
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
return pwmchip_get_drvdata(chip);
#else
return container_of(chip, struct isc_pwm_info, chip);
#endif
}
#if KERNEL_VERSION(6, 0, 0) > LINUX_VERSION_CODE
@@ -95,30 +99,38 @@ static struct pwm_device *of_isc_pwm_xlate(struct pwm_chip *pc,
{
struct pwm_device *pwm;
struct isc_pwm_info *info = to_isc_pwm_info(pc);
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
struct device *dev = &pc->dev;
#else
struct device *dev = pc->dev;
#endif
int err = 0;
pwm = pwm_request_from_chip(pc, args->args[0], NULL);
if (!args->args[1]) {
dev_err(pc->dev, "Period should be larger than 0\n");
pwm = of_pwm_xlate_with_flags(pc, args);
if (IS_ERR(pwm))
return NULL;
if (!pwm->args.period) {
dev_err(dev, "Period should be larger than 0\n");
return NULL;
}
if (info->force_on) {
err = pwm_config(info->pwm, args->args[1]/4, args->args[1]);
if (err) {
dev_err(pc->dev, "can't config PWM: %d\n", err);
dev_err(dev, "can't config PWM: %d\n", err);
return NULL;
}
err = pwm_enable(info->pwm);
if (err) {
dev_err(pc->dev, "can't enable PWM: %d\n", err);
dev_err(dev, "can't enable PWM: %d\n", err);
return NULL;
}
} else {
err = pwm_config(pwm, args->args[1]/4, args->args[1]);
if (err) {
dev_err(pc->dev, "can't config PWM: %d\n", err);
dev_err(dev, "can't config PWM: %d\n", err);
return NULL;
}
}
@@ -140,50 +152,60 @@ static const struct pwm_ops isc_pwm_ops = {
static int isc_pwm_probe(struct platform_device *pdev)
{
struct isc_pwm_info *info = NULL;
struct pwm_chip *chip;
int err = 0, npwm;
bool force_on = false;
dev_info(&pdev->dev, "%sing...\n", __func__);
info = devm_kzalloc(
&pdev->dev, sizeof(struct isc_pwm_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
atomic_set(&info->in_use, 0);
mutex_init(&info->mutex);
err = of_property_read_u32(pdev->dev.of_node, "npwm", &npwm);
if (err < 0) {
dev_err(&pdev->dev, "npwm is not defined: %d\n", err);
return err;
}
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*info));
if (IS_ERR(chip))
return PTR_ERR(chip);
info = to_isc_pwm_info(chip);
#else
info = devm_kzalloc(
&pdev->dev, sizeof(struct isc_pwm_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
chip = &info->chip;
chip->dev = &pdev->dev;
chip->npwm = npwm;
#endif
atomic_set(&info->in_use, 0);
mutex_init(&info->mutex);
force_on = of_property_read_bool(pdev->dev.of_node, "force_on");
info->chip.dev = &pdev->dev;
info->chip.ops = &isc_pwm_ops;
chip->ops = &isc_pwm_ops;
#if defined(NV_PWM_CHIP_STRUCT_HAS_BASE_ARG)
info->chip.base = -1;
chip->base = -1;
#endif
info->chip.npwm = npwm;
info->chip.of_xlate = of_isc_pwm_xlate;
chip->of_xlate = of_isc_pwm_xlate;
info->force_on = force_on;
err = pwmchip_add(&info->chip);
err = pwmchip_add(chip);
if (err < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", err);
return err;
}
platform_set_drvdata(pdev, info);
platform_set_drvdata(pdev, chip);
info->pwm = devm_pwm_get(&pdev->dev, NULL);
if (!IS_ERR(info->pwm)) {
pwm_disable(info->pwm);
dev_info(&pdev->dev, "%s success to get PWM\n", __func__);
} else {
pwmchip_remove(&info->chip);
pwmchip_remove(chip);
err = PTR_ERR(info->pwm);
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev,
@@ -195,24 +217,24 @@ static int isc_pwm_probe(struct platform_device *pdev)
static int isc_pwm_remove(struct platform_device *pdev)
{
struct isc_pwm_info *info = platform_get_drvdata(pdev);
struct pwm_chip *chip = platform_get_drvdata(pdev);
pwmchip_remove(&info->chip);
pwmchip_remove(chip);
return 0;
}
static int isc_pwm_suspend(struct device *dev)
{
int err = 0;
struct isc_pwm_info *info = dev_get_drvdata(dev);
struct pwm_chip *chip = dev_get_drvdata(dev);
struct isc_pwm_info *info = to_isc_pwm_info(chip);
if (info == NULL) {
dev_err(dev, "%s: fail to get info\n", __func__);
} else {
if (!IS_ERR(info->pwm)) {
pwm_disable(info->pwm);
err = pwm_config(info->pwm, PWM_SUSPEND_DUTY_RATIO,
pwm_config(info->pwm, PWM_SUSPEND_DUTY_RATIO,
PWM_SUSPEND_PERIOD);
}
}

View File

@@ -297,7 +297,7 @@ static int __init tpg_probe_t19x(void)
return -EINVAL;
mc_csi->get_tpg_settings = get_tpg_settings_t23x;
mc_csi->tpg_gain_ctrl = true;
mc_csi->tpg_gain_ctrl = false;
mc_csi->tpg_emb_data_config = emb_data;
dev_info(mc_csi->dev, "%s\n", __func__);
@@ -310,7 +310,7 @@ static int __init tpg_probe_t19x(void)
mc_csi->tpg_frmfmt_table_size = table_size;
memcpy(frmfmt_table, tegra19x_csi_tpg_frmfmt,
table_size * sizeof(struct tpg_frmfmt));
table_size * sizeof(struct tpg_frmfmt));
if (override_frmfmt) {
for (i = 0; i < table_size; i++)

View File

@@ -1,9 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_11 := $(shell expr 6 \* 256 + 11)
# MODS is currently broken for Linux v6.11 and later
ifeq ($(shell test $(LINUX_VERSION) -lt $(LINUX_VERSION_6_11); echo $$?),0)
ifeq ($(findstring ack_src,$(NV_BUILD_KERNEL_OPTIONS)),)
obj-m += mods/
endif
endif
obj-m += nvsciipc/
ifdef CONFIG_PCI
obj-m += tegra-pcie-dma-test.o

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#define pr_fmt(fmt) "nvscic2c-pcie: comm-channel: " fmt
#include <nvidia/conftest.h>
#include <linux/atomic.h>
#include <linux/dma-fence.h>
#include <linux/errno.h>
@@ -215,7 +217,11 @@ send_msg(struct comm_channel_ctx_t *comm_ctx, struct comm_msg *msg)
if (peer_cpu == NVCPU_X86_64) {
/* comm-channel irq verctor always take from index 0 */
#if defined(PCI_EPC_IRQ_TYPE_ENUM_PRESENT) /* Dropped from Linux 6.8 */
ret = pci_client_raise_irq(comm_ctx->pci_client_h, PCI_EPC_IRQ_MSI, 0);
#else
ret = pci_client_raise_irq(comm_ctx->pci_client_h, PCI_IRQ_MSI, 0);
#endif
} else {
/* notify peer for each write.*/
writel(0x1, syncpt->peer_mem.pva);

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#define pr_fmt(fmt) "nvscic2c-pcie: endpoint: " fmt
@@ -501,8 +501,13 @@ ioctl_notify_remote_impl(struct endpoint_t *endpoint)
return -ENOLINK;
if (peer_cpu == NVCPU_X86_64) {
#if defined(PCI_EPC_IRQ_TYPE_ENUM_PRESENT) /* Dropped from Linux 6.8 */
ret = pci_client_raise_irq(endpoint->pci_client_h, PCI_EPC_IRQ_MSI,
endpoint->msi_irq);
#else
ret = pci_client_raise_irq(endpoint->pci_client_h, PCI_IRQ_MSI,
endpoint->msi_irq);
#endif
} else {
/*
* Ordering between message/data and host1x syncpoints is not

View File

@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#define pr_fmt(fmt) "nvscic2c-pcie: epf: " fmt
@@ -169,6 +171,7 @@ allocate_outbound_area(struct pci_epf *epf, size_t win_size,
return ret;
}
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
static void
clear_inbound_translation(struct pci_epf *epf)
{
@@ -178,6 +181,7 @@ clear_inbound_translation(struct pci_epf *epf)
/* no api to clear epf header.*/
}
#endif
static int
set_inbound_translation(struct pci_epf *epf)
@@ -490,6 +494,7 @@ deinit_work(struct work_struct *work)
* @DRV_MODE_EPC would have already gone then by the time
* struct pci_epc_event_ops.core_deinit is called.
*/
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
static int
nvscic2c_pcie_epf_core_deinit(struct pci_epf *epf)
{
@@ -517,6 +522,7 @@ nvscic2c_pcie_epf_core_deinit(struct pci_epf *epf)
return 0;
}
#endif
/* Handle link message from @DRV_MODE_EPC. */
static void
@@ -729,7 +735,9 @@ get_driverdata(const struct pci_epf_device_id *id,
static const struct pci_epc_event_ops nvscic2c_event_ops = {
.core_init = nvscic2c_pcie_epf_core_init,
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
.core_deinit = nvscic2c_pcie_epf_core_deinit,
#endif
};
static int

View File

@@ -3,6 +3,8 @@
#define pr_fmt(fmt) "nvscic2c-pcie: pci-client: " fmt
#include <nvidia/conftest.h>
#include <linux/dma-buf.h>
#include <linux/dma-map-ops.h>
#include <linux/errno.h>
@@ -246,7 +248,12 @@ allocate_edma_rx_desc_iova(struct pci_client_t *ctx)
goto err;
}
prot = (IOMMU_CACHE | IOMMU_READ | IOMMU_WRITE);
ret = iommu_map(ctx->domain, ctx->edma_ch_desc_iova, phys_addr, EDMA_CH_DESC_SZ, prot);
ret = iommu_map(ctx->domain, ctx->edma_ch_desc_iova, phys_addr,
#if defined(NV_IOMMU_MAP_HAS_GFP_ARG)
EDMA_CH_DESC_SZ, prot, GFP_KERNEL);
#else
EDMA_CH_DESC_SZ, prot);
#endif
if (ret) {
pr_err("pci client failed to map iova to 60K physical backing\n");
goto err;
@@ -408,7 +415,12 @@ pci_client_map_addr(void *pci_client_h, u64 to_iova, phys_addr_t paddr,
if (WARN_ON(!ctx || !to_iova || !paddr || !size))
return -EINVAL;
return iommu_map(ctx->domain, to_iova, paddr, size, prot);
return iommu_map(ctx->domain, to_iova, paddr, size,
#if defined(NV_IOMMU_MAP_HAS_GFP_ARG)
prot, GFP_KERNEL);
#else
prot);
#endif
}
size_t
@@ -751,7 +763,7 @@ pci_client_get_drv_mode(void *pci_client_h)
return DRV_MODE_INVALID;
drv_ctx = pci_client_ctx->drv_ctx;
if (WARN_ON(!drv_ctx))
return NVCPU_MAXIMUM;
return DRV_MODE_INVALID;
return drv_ctx->drv_mode;
}
@@ -800,7 +812,11 @@ pci_client_get_edma_rx_desc_iova(void *pci_client_h)
}
int
#if defined(PCI_EPC_IRQ_TYPE_ENUM_PRESENT) /* Dropped from Linux 6.8 */
pci_client_raise_irq(void *pci_client_h, enum pci_epc_irq_type type, u16 num)
#else
pci_client_raise_irq(void *pci_client_h, int type, u16 num)
#endif
{
int ret = 0;
struct pci_client_t *pci_client_ctx = (struct pci_client_t *)pci_client_h;

View File

@@ -4,6 +4,8 @@
#ifndef __PCI_CLIENT_H__
#define __PCI_CLIENT_H__
#include <nvidia/conftest.h>
#include <uapi/misc/nvscic2c-pcie-ioctl.h>
#include "common.h"
@@ -133,5 +135,9 @@ pci_client_get_edma_rx_desc_iova(void *pci_client_h);
/* pci client raise irq to rp */
int
#if defined(PCI_EPC_IRQ_TYPE_ENUM_PRESENT) /* Dropped from Linux 6.8 */
pci_client_raise_irq(void *pci_client_h, enum pci_epc_irq_type type, u16 num);
#else
pci_client_raise_irq(void *pci_client_h, int type, u16 num);
#endif
#endif // __PCI_CLIENT_H__

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#define pr_fmt(fmt) "nvscic2c-pcie: stream-ext: " fmt
@@ -14,6 +14,7 @@
#include <linux/host1x-next.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/tegra-pcie-edma.h>

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -505,7 +505,8 @@ static int mttcan_state_change(struct net_device *dev,
*/
ttcan_set_intrpts(priv->ttcan, 0);
priv->can.can_stats.bus_off++;
priv->ttcan->tx_object = 0;
netif_stop_queue(dev);
netif_carrier_off(dev);
if (priv->can.restart_ms)
@@ -1114,6 +1115,7 @@ restart:
priv->can.can_stats.restarts++;
mttcan_start(dev);
netif_start_queue(dev);
netif_carrier_on(dev);
}

View File

@@ -1,10 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only
obj-m += nvidia/
ifdef CONFIG_PCI
obj-m += marvell/
obj-m += microchip/
ifeq ($(VERSION).$(PATCHLEVEL),5.15)
obj-m += realtek/
endif
endif

View File

@@ -3030,15 +3030,15 @@ static int ether_close(struct net_device *ndev)
reset_control_assert(pdata->xpcs_rst);
}
/* All MDIO interfaces must be disabled before resetting the MAC */
if (pdata->mii)
mdiobus_unregister(pdata->mii);
/* Assert MAC RST gpio */
if (pdata->mac_rst) {
reset_control_assert(pdata->mac_rst);
}
if (pdata->mii != NULL) {
mdiobus_unregister(pdata->mii);
}
/* Disable clock */
ether_disable_clks(pdata);
@@ -3309,10 +3309,10 @@ static int ether_tx_swcx_alloc(struct ether_priv_data *pdata,
}
size = min(len, max_data_len_per_txd);
page_idx = (frag->bv_offset + offset) >> PAGE_SHIFT;
page_offset = (frag->bv_offset + offset) & ~PAGE_MASK;
page_idx = (skb_frag_off(frag) + offset) >> PAGE_SHIFT;
page_offset = (skb_frag_off(frag) + offset) & ~PAGE_MASK;
tx_swcx->buf_phy_addr = dma_map_page(dev,
(frag->bv_page + page_idx),
(skb_frag_page(frag) + page_idx),
page_offset, size,
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev,
@@ -6666,7 +6666,7 @@ static int ether_probe(struct platform_device *pdev)
goto err_macsec;
} else if (ret == 1) {
/* Nothing to do, macsec is not supported */
dev_info(&pdev->dev, "Macsec not supported/Not enabled in DT\n");
dev_info(&pdev->dev, "Macsec not supported/Not enabled\n");
} else {
dev_info(&pdev->dev, "Macsec not enabled\n");
/* Macsec is supported, reduce MTU */

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -863,7 +863,11 @@ static int ether_set_pauseparam(struct net_device *ndev,
* @return zero on success
*/
static int ether_get_ts_info(struct net_device *ndev,
#if defined(NV_ETHTOOL_KERNEL_ETHTOOL_TS_INFO_STRUCT_PRESENT) /* Linux v6.11 */
struct kernel_ethtool_ts_info *info)
#else
struct ethtool_ts_info *info)
#endif
{
struct ether_priv_data *pdata = netdev_priv(ndev);
@@ -1095,7 +1099,11 @@ static int ether_get_coalesce(struct net_device *dev,
* @retval -ve on Failure
*/
static int ether_get_eee(struct net_device *ndev,
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
struct ethtool_keee *cur_eee)
#else
struct ethtool_eee *cur_eee)
#endif
{
int ret;
struct ether_priv_data *pdata = netdev_priv(ndev);
@@ -1136,8 +1144,13 @@ static int ether_get_eee(struct net_device *ndev,
* @retval none
*/
static inline void validate_eee_conf(struct net_device *ndev,
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
struct ethtool_keee *eee_req,
struct ethtool_keee cur_eee)
#else
struct ethtool_eee *eee_req,
struct ethtool_eee cur_eee)
#endif
{
/* These are the invalid combinations that can be requested.
* EEE | Tx LPI | Rx LPI
@@ -1152,10 +1165,18 @@ static inline void validate_eee_conf(struct net_device *ndev,
* on whether EEE has toggled or not.
*/
if (!eee_req->eee_enabled && !eee_req->tx_lpi_enabled &&
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
!linkmode_empty(eee_req->advertised)) {
#else
eee_req->advertised) {
#endif
if (eee_req->eee_enabled != cur_eee.eee_enabled) {
netdev_warn(ndev, "EEE off. Set Rx LPI off\n");
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_zero(eee_req->advertised);
#else
eee_req->advertised = OSI_DISABLE;
#endif
} else {
netdev_warn(ndev, "Rx LPI on. Set EEE on\n");
eee_req->eee_enabled = OSI_ENABLE;
@@ -1163,7 +1184,11 @@ static inline void validate_eee_conf(struct net_device *ndev,
}
if (!eee_req->eee_enabled && eee_req->tx_lpi_enabled &&
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_empty(eee_req->advertised)) {
#else
!eee_req->advertised) {
#endif
if (eee_req->eee_enabled != cur_eee.eee_enabled) {
netdev_warn(ndev, "EEE off. Set Tx LPI off\n");
eee_req->tx_lpi_enabled = OSI_DISABLE;
@@ -1174,16 +1199,28 @@ static inline void validate_eee_conf(struct net_device *ndev,
*/
netdev_warn(ndev, "Tx LPI on. Set EEE & Rx LPI on\n");
eee_req->eee_enabled = OSI_ENABLE;
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_copy(eee_req->advertised, eee_req->supported);
#else
eee_req->advertised = eee_req->supported;
#endif
}
}
if (!eee_req->eee_enabled && eee_req->tx_lpi_enabled &&
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
!linkmode_empty(eee_req->advertised)) {
#else
eee_req->advertised) {
#endif
if (eee_req->eee_enabled != cur_eee.eee_enabled) {
netdev_warn(ndev, "EEE off. Set Tx & Rx LPI off\n");
eee_req->tx_lpi_enabled = OSI_DISABLE;
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_zero(eee_req->advertised);
#else
eee_req->advertised = OSI_DISABLE;
#endif
} else {
netdev_warn(ndev, "Tx & Rx LPI on. Set EEE on\n");
eee_req->eee_enabled = OSI_ENABLE;
@@ -1191,11 +1228,19 @@ static inline void validate_eee_conf(struct net_device *ndev,
}
if (eee_req->eee_enabled && !eee_req->tx_lpi_enabled &&
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_empty(eee_req->advertised)) {
#else
!eee_req->advertised) {
#endif
if (eee_req->eee_enabled != cur_eee.eee_enabled) {
netdev_warn(ndev, "EEE on. Set Tx & Rx LPI on\n");
eee_req->tx_lpi_enabled = OSI_ENABLE;
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
linkmode_copy(eee_req->advertised, eee_req->supported);
#else
eee_req->advertised = eee_req->supported;
#endif
} else {
netdev_warn(ndev, "Tx,Rx LPI off. Set EEE off\n");
eee_req->eee_enabled = OSI_DISABLE;
@@ -1218,11 +1263,19 @@ static inline void validate_eee_conf(struct net_device *ndev,
* @retval -ve on Failure
*/
static int ether_set_eee(struct net_device *ndev,
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
struct ethtool_keee *eee_req)
#else
struct ethtool_eee *eee_req)
#endif
{
struct ether_priv_data *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phydev;
#if defined(NV_ETHTOOL_KEEE_STRUCT_PRESENT) /* Linux v6.9 */
struct ethtool_keee cur_eee;
#else
struct ethtool_eee cur_eee;
#endif
if (!pdata->hw_feat.eee_sel) {
return -EOPNOTSUPP;

View File

@@ -9,6 +9,11 @@
#ifdef HSI_SUPPORT
#include <linux/tegra-epl.h>
#endif
static bool macsec_enable = true;
module_param(macsec_enable, bool, 0644);
MODULE_PARM_DESC(macsec_enable, "Enable Macsec for nvethernet module");
static int macsec_get_tx_next_pn(struct sk_buff *skb, struct genl_info *info);
#ifndef MACSEC_KEY_PROGRAM
@@ -1365,9 +1370,10 @@ int macsec_probe(struct ether_priv_data *pdata)
/* Read if macsec is enabled in DT */
ret = of_property_read_u32(np, "nvidia,macsec-enable",
&macsec_pdata->is_macsec_enabled_in_dt);
if ((ret != 0) || (macsec_pdata->is_macsec_enabled_in_dt == 0U)) {
if (ret != 0 || !macsec_enable ||
macsec_pdata->is_macsec_enabled_in_dt == 0U) {
dev_info(dev,
"macsec param in DT is missing or disabled\n");
"macsec parameter is missing or disabled\n");
ret = 1;
goto init_err;
}

View File

@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved */
// SPDX-FileCopyrightText: Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/version.h>
#include "ether_linux.h"
/**
@@ -130,11 +129,7 @@ static int ether_adjust_time(struct ptp_clock_info *ptp, s64 nsec_delta)
* @retval 0 on success
* @retval "negative value" on failure.
*/
#if KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE
static int ether_adjust_clock(struct ptp_clock_info *ptp, s32 ppb)
#else
static int ether_adjust_clock(struct ptp_clock_info *ptp, long scaled_ppm)
#endif
{
struct ether_priv_data *pdata = container_of(ptp,
struct ether_priv_data,
@@ -143,14 +138,11 @@ static int ether_adjust_clock(struct ptp_clock_info *ptp, long scaled_ppm)
struct osi_ioctl ioctl_data = {};
unsigned long flags;
int ret = -1;
#if KERNEL_VERSION(6, 2, 0) <= LINUX_VERSION_CODE
s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
#endif
raw_spin_lock_irqsave(&pdata->ptp_lock, flags);
ioctl_data.cmd = OSI_CMD_ADJ_FREQ;
ioctl_data.arg6_32 = ppb;
ioctl_data.arg6_32 = scaled_ppm_to_ppb(scaled_ppm);
ret = osi_handle_ioctl(osi_core, &ioctl_data);
if (ret < 0) {
dev_err(pdata->dev,
@@ -253,11 +245,7 @@ static struct ptp_clock_info ether_ptp_clock_ops = {
.n_ext_ts = 0,
.n_per_out = 0,
.pps = 0,
#if KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE
.adjfreq = ether_adjust_clock,
#else
.adjfine = ether_adjust_clock,
#endif
.adjtime = ether_adjust_time,
.gettime64 = ether_get_time,
.settime64 = ether_set_time,

View File

@@ -183,6 +183,11 @@ static void tvnet_host_alloc_empty_buffers(struct tvnet_priv *tvnet)
break;
}
/* The PCIe link is stable and dependable,
* so it's not necessary to perform a software checksum.
*/
skb->ip_summed = CHECKSUM_UNNECESSARY;
ep2h_empty_ptr = kmalloc(sizeof(*ep2h_empty_ptr), GFP_ATOMIC);
if (!ep2h_empty_ptr) {
dma_unmap_single(d, iova, len, DMA_FROM_DEVICE);
@@ -651,16 +656,18 @@ static int tvnet_host_process_ep2h_msg(struct tvnet_priv *tvnet)
list_for_each_entry(ep2h_empty_ptr, &tvnet->ep2h_empty_list,
list) {
if (ep2h_empty_ptr->iova == pcie_address) {
list_del(&ep2h_empty_ptr->list);
found = 1;
break;
}
}
WARN_ON(!found);
list_del(&ep2h_empty_ptr->list);
spin_unlock_irqrestore(&tvnet->ep2h_empty_lock, flags);
/* Advance H2EP full buffer after search in local list */
tvnet_ivc_advance_rd(&tvnet->ep2h_full);
if (WARN_ON(!found))
continue;
/* If EP2H network queue is stopped due to lack of EP2H_FULL
* queue, raising ctrl irq will help.
*/

View File

@@ -1,100 +1,10 @@
# 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) 2022 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
#
################################################################################
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
################################################################################
# This product is covered by one or more of the following patents:
# US6,570,884, US6,115,776, and US6,327,625.
################################################################################
CONFIG_SOC_LAN = n
ENABLE_FIBER_SUPPORT = n
ENABLE_REALWOW_SUPPORT = n
ENABLE_DASH_SUPPORT = n
ENABLE_DASH_PRINTER_SUPPORT = n
CONFIG_DOWN_SPEED_100 = n
CONFIG_ASPM = y
ENABLE_S5WOL = y
ENABLE_S5_KEEP_CURR_MAC = n
ENABLE_EEE = y
ENABLE_S0_MAGIC_PACKET = n
CONFIG_DYNAMIC_ASPM = y
ENABLE_USE_FIRMWARE_FILE = n
CONFIG_CTAP_SHORT_OFF = n
obj-m += r8168.o
r8168-objs += r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o
ifeq ($(CONFIG_SOC_LAN), y)
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
endif
ifeq ($(ENABLE_FIBER_SUPPORT), y)
r8168-objs += r8168_fiber.o
EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
endif
ifeq ($(ENABLE_REALWOW_SUPPORT), y)
r8168-objs += r8168_realwow.o
EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
endif
ifeq ($(ENABLE_DASH_SUPPORT), y)
r8168-objs += r8168_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
endif
ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y)
r8168-objs += r8168_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
endif
EXTRA_CFLAGS += -DCONFIG_R8168_NAPI
EXTRA_CFLAGS += -DCONFIG_R8168_VLAN
ifeq ($(CONFIG_DOWN_SPEED_100), y)
EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
endif
ifeq ($(CONFIG_ASPM), y)
EXTRA_CFLAGS += -DCONFIG_ASPM
endif
ifeq ($(ENABLE_S5WOL), y)
EXTRA_CFLAGS += -DENABLE_S5WOL
endif
ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y)
EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
endif
ifeq ($(ENABLE_EEE), y)
EXTRA_CFLAGS += -DENABLE_EEE
endif
ifeq ($(ENABLE_S0_MAGIC_PACKET), y)
EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
endif
ifeq ($(CONFIG_DYNAMIC_ASPM), y)
EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM
endif
ifeq ($(ENABLE_USE_FIRMWARE_FILE), y)
r8168-objs += r8168_firmware.o
EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
endif
ifeq ($(CONFIG_CTAP_SHORT_OFF), y)
EXTRA_CFLAGS += -DCONFIG_CTAP_SHORT_OFF
ifneq ($(NV_OOT_REALTEK_R8168_SKIP_BUILD),y)
obj-m += r8168/
endif
ifneq ($(NV_OOT_REALTEK_R8126_SKIP_BUILD),y)
obj-m += r8126/
endif

View File

@@ -0,0 +1,143 @@
# SPDX-License-Identifier: GPL-2.0-only
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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.
################################################################################
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_9 := $(shell expr 6 \* 256 + 9)
# Use dummy R8126 driver for Kernel versions greater that K69
ifeq ($(shell test $(LINUX_VERSION) -gt $(LINUX_VERSION_6_9); echo $$?),0)
obj-m := r8126.o
r8126-objs := r8126_dummy.o
else
CONFIG_SOC_LAN = n
ENABLE_REALWOW_SUPPORT = n
ENABLE_DASH_SUPPORT = n
ENABLE_DASH_PRINTER_SUPPORT = n
CONFIG_DOWN_SPEED_100 = n
CONFIG_ASPM = y
ENABLE_S5WOL = y
ENABLE_S5_KEEP_CURR_MAC = n
ENABLE_EEE = y
ENABLE_S0_MAGIC_PACKET = n
ENABLE_TX_NO_CLOSE = y
ENABLE_MULTIPLE_TX_QUEUE = y
ENABLE_PTP_SUPPORT = y
ENABLE_PTP_MASTER_MODE = n
ENABLE_RSS_SUPPORT = y
ENABLE_LIB_SUPPORT = n
ENABLE_USE_FIRMWARE_FILE = n
DISABLE_WOL_SUPPORT = n
DISABLE_MULTI_MSIX_VECTOR = n
ENABLE_DOUBLE_VLAN = n
ENABLE_PAGE_REUSE = n
ENABLE_RX_PACKET_FRAGMENT = n
obj-m := r8126.o
r8126-objs := r8126_n.o rtl_eeprom.o rtltool.o
ifeq ($(CONFIG_SOC_LAN), y)
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
endif
ifeq ($(ENABLE_REALWOW_SUPPORT), y)
r8126-objs += r8126_realwow.o
EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
endif
ifeq ($(ENABLE_DASH_SUPPORT), y)
r8126-objs += r8126_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
endif
ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y)
r8126-objs += r8126_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
endif
EXTRA_CFLAGS += -DCONFIG_R8126_NAPI
EXTRA_CFLAGS += -DCONFIG_R8126_VLAN
ifeq ($(CONFIG_DOWN_SPEED_100), y)
EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100
endif
ifeq ($(CONFIG_ASPM), y)
EXTRA_CFLAGS += -DCONFIG_ASPM
endif
ifeq ($(ENABLE_S5WOL), y)
EXTRA_CFLAGS += -DENABLE_S5WOL
endif
ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y)
EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
endif
ifeq ($(ENABLE_EEE), y)
EXTRA_CFLAGS += -DENABLE_EEE
endif
ifeq ($(ENABLE_S0_MAGIC_PACKET), y)
EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
endif
ifeq ($(ENABLE_TX_NO_CLOSE), y)
EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE
endif
ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y)
EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE
endif
ifeq ($(ENABLE_PTP_SUPPORT), y)
r8126-objs += r8126_ptp.o
EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT
endif
ifeq ($(ENABLE_PTP_MASTER_MODE), y)
EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE
endif
ifeq ($(ENABLE_RSS_SUPPORT), y)
r8126-objs += r8126_rss.o
EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT
endif
ifeq ($(ENABLE_LIB_SUPPORT), y)
r8126-objs += r8126_lib.o
EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT
endif
ifeq ($(ENABLE_USE_FIRMWARE_FILE), y)
r8126-objs += r8126_firmware.o
EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
endif
ifeq ($(DISABLE_WOL_SUPPORT), y)
EXTRA_CFLAGS += -DDISABLE_WOL_SUPPORT
endif
ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y)
EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR
endif
ifeq ($(ENABLE_DOUBLE_VLAN), y)
EXTRA_CFLAGS += -DENABLE_DOUBLE_VLAN
endif
ifeq ($(ENABLE_PAGE_REUSE), y)
EXTRA_CFLAGS += -DENABLE_PAGE_REUSE
endif
ifeq ($(ENABLE_RX_PACKET_FRAGMENT), y)
EXTRA_CFLAGS += -DENABLE_RX_PACKET_FRAGMENT
endif
endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_R8126_DASH_H
#define _LINUX_R8126_DASH_H
#include <linux/if.h>
#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2
enum rtl_dash_cmd {
RTL_DASH_ARP_NS_OFFLOAD = 0,
RTL_DASH_SET_OOB_IPMAC,
RTL_DASH_NOTIFY_OOB,
RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW,
RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE,
RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA,
RTL_DASH_OOB_REQ,
RTL_DASH_OOB_ACK,
RTL_DASH_DETACH_OOB_REQ,
RTL_DASH_DETACH_OOB_ACK,
RTL_FW_SET_IPV4 = 0x10,
RTL_FW_GET_IPV4,
RTL_FW_SET_IPV6,
RTL_FW_GET_IPV6,
RTL_FW_SET_EXT_SNMP,
RTL_FW_GET_EXT_SNMP,
RTL_FW_SET_WAKEUP_PATTERN,
RTL_FW_GET_WAKEUP_PATTERN,
RTL_FW_DEL_WAKEUP_PATTERN,
RTLT_DASH_COMMAND_INVALID,
};
struct rtl_dash_ip_mac {
struct sockaddr ifru_addr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
};
struct rtl_dash_ioctl_struct {
__u32 cmd;
__u32 offset;
__u32 len;
union {
__u32 data;
void *data_buffer;
};
};
struct settings_ipv4 {
__u32 IPv4addr;
__u32 IPv4mask;
__u32 IPv4Gateway;
};
struct settings_ipv6 {
__u32 reserved;
__u32 prefixLen;
__u16 IPv6addr[8];
__u16 IPv6Gateway[8];
};
struct settings_ext_snmp {
__u16 index;
__u16 oid_get_len;
__u8 oid_for_get[24];
__u8 reserved0[26];
__u16 value_len;
__u8 value[256];
__u8 supported;
__u8 reserved1[27];
};
struct wakeup_pattern {
__u8 index;
__u8 valid;
__u8 start;
__u8 length;
__u8 name[36];
__u8 mask[16];
__u8 pattern[128];
__u32 reserved[2];
};
typedef struct _RX_DASH_FROM_FW_DESC {
u16 length;
u8 statusLowByte;
u8 statusHighByte;
u32 resv;
u64 BufferAddress;
}
RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC;
typedef struct _TX_DASH_SEND_FW_DESC {
u16 length;
u8 statusLowByte;
u8 statusHighByte;
u32 resv;
u64 BufferAddress;
}
TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC;
typedef struct _OSOOBHdr {
u32 len;
u8 type;
u8 flag;
u8 hostReqV;
u8 res;
}
OSOOBHdr, *POSOOBHdr;
typedef struct _RX_DASH_BUFFER_TYPE_2 {
OSOOBHdr oobhdr;
u8 RxDataBuffer[0];
}
RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2;
#define ALIGN_8 (0x7)
#define ALIGN_16 (0xf)
#define ALIGN_32 (0x1f)
#define ALIGN_64 (0x3f)
#define ALIGN_256 (0xff)
#define ALIGN_4096 (0xfff)
#define OCP_REG_CONFIG0 (0x10)
#define OCP_REG_CONFIG0_REV_F (0xB8)
#define OCP_REG_DASH_POLL (0x30)
#define OCP_REG_HOST_REQ (0x34)
#define OCP_REG_DASH_REQ (0x35)
#define OCP_REG_CR (0x36)
#define OCP_REG_DMEMSTA (0x38)
#define OCP_REG_GPHYAR (0x60)
#define OCP_REG_CONFIG0_DASHEN BIT_15
#define OCP_REG_CONFIG0_OOBRESET BIT_14
#define OCP_REG_CONFIG0_APRDY BIT_13
#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12
#define OCP_REG_CONFIG0_DRIVERRDY BIT_11
#define OCP_REG_CONFIG0_OOB_WDT BIT_9
#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8
#define OCP_REG_CONFIG0_TLSEN BIT_7
#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0)
#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 RECV_FROM_FW_BUF_SIZE (1520)
#define SEND_TO_FW_BUF_SIZE (1520)
#define RX_DASH_FROM_FW_OWN BIT_15
#define TX_DASH_SEND_FW_OWN BIT_15
#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7
#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3)
#define TXS_EXC BIT_4
#define TXS_LNKF BIT_5
#define TXS_OWC BIT_6
#define TXS_TES BIT_7
#define TXS_UNF BIT_9
#define TXS_LGSEN BIT_11
#define TXS_LS BIT_12
#define TXS_FS BIT_13
#define TXS_EOR BIT_14
#define TXS_OWN BIT_15
#define TPPool_HRDY 0x20
#define HostReqReg (0xC0)
#define SystemMasterDescStartAddrLow (0xF0)
#define SystemMasterDescStartAddrHigh (0xF4)
#define SystemSlaveDescStartAddrLow (0xF8)
#define SystemSlaveDescStartAddrHigh (0xFC)
//DASH Request Type
#define WSMANREG 0x01
#define OSPUSHDATA 0x02
#define RXS_OWN BIT_15
#define RXS_EOR BIT_14
#define RXS_FS BIT_13
#define RXS_LS BIT_12
#define ISRIMR_DP_DASH_OK BIT_15
#define ISRIMR_DP_HOST_OK BIT_13
#define ISRIMR_DP_REQSYS_OK BIT_11
#define ISRIMR_DASH_INTR_EN BIT_12
#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15
#define ISRIMR_DASH_TYPE2_ROK BIT_0
#define ISRIMR_DASH_TYPE2_RDU BIT_1
#define ISRIMR_DASH_TYPE2_TOK BIT_2
#define ISRIMR_DASH_TYPE2_TDU BIT_3
#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4
#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5
#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6
#define CMAC_OOB_STOP 0x25
#define CMAC_OOB_INIT 0x26
#define CMAC_OOB_RESET 0x2a
#define NO_BASE_ADDRESS 0x00000000
#define RTL8168FP_OOBMAC_BASE 0xBAF70000
#define RTL8168FP_CMAC_IOBASE 0xBAF20000
#define RTL8168FP_KVM_BASE 0xBAF80400
#define CMAC_SYNC_REG 0x20
#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98
#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F
/* cmac write/read MMIO register */
#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg))
#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg)))
int rtl8126_dash_ioctl(struct net_device *dev, struct ifreq *ifr);
void HandleDashInterrupt(struct net_device *dev);
int AllocateDashShareMemory(struct net_device *dev);
void FreeAllocatedDashShareMemory(struct net_device *dev);
void DashHwInit(struct net_device *dev);
#endif /* _LINUX_R8126_DASH_H */

View File

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/module.h>
/* Dummy implementation for module */
static int __init r8126_dummy_dummy_init(void)
{
return 0;
}
device_initcall(r8126_dummy_dummy_init);
MODULE_AUTHOR("Revanth Kumar Uppala <ruppala@nvidia.com>");
MODULE_DESCRIPTION("Dummy R8126 dummy driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,264 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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 <linux/delay.h>
#include <linux/firmware.h>
#include "r8126_firmware.h"
enum rtl_fw_opcode {
PHY_READ = 0x0,
PHY_DATA_OR = 0x1,
PHY_DATA_AND = 0x2,
PHY_BJMPN = 0x3,
PHY_MDIO_CHG = 0x4,
PHY_CLEAR_READCOUNT = 0x7,
PHY_WRITE = 0x8,
PHY_READCOUNT_EQ_SKIP = 0x9,
PHY_COMP_EQ_SKIPN = 0xa,
PHY_COMP_NEQ_SKIPN = 0xb,
PHY_WRITE_PREVIOUS = 0xc,
PHY_SKIPN = 0xd,
PHY_DELAY_MS = 0xe,
};
struct fw_info {
u32 magic;
char version[RTL8126_VER_SIZE];
__le32 fw_start;
__le32 fw_len;
u8 chksum;
} __packed;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0)
#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
#endif
#define FW_OPCODE_SIZE sizeof_field(struct rtl8126_fw_phy_action, code[0])
static bool rtl8126_fw_format_ok(struct rtl8126_fw *rtl_fw)
{
const struct firmware *fw = rtl_fw->fw;
struct fw_info *fw_info = (struct fw_info *)fw->data;
struct rtl8126_fw_phy_action *pa = &rtl_fw->phy_action;
if (fw->size < FW_OPCODE_SIZE)
return false;
if (!fw_info->magic) {
size_t i, size, start;
u8 checksum = 0;
if (fw->size < sizeof(*fw_info))
return false;
for (i = 0; i < fw->size; i++)
checksum += fw->data[i];
if (checksum != 0)
return false;
start = le32_to_cpu(fw_info->fw_start);
if (start > fw->size)
return false;
size = le32_to_cpu(fw_info->fw_len);
if (size > (fw->size - start) / FW_OPCODE_SIZE)
return false;
strscpy(rtl_fw->version, fw_info->version, RTL8126_VER_SIZE);
pa->code = (__le32 *)(fw->data + start);
pa->size = size;
} else {
if (fw->size % FW_OPCODE_SIZE)
return false;
strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8126_VER_SIZE);
pa->code = (__le32 *)fw->data;
pa->size = fw->size / FW_OPCODE_SIZE;
}
return true;
}
static bool rtl8126_fw_data_ok(struct rtl8126_fw *rtl_fw)
{
struct rtl8126_fw_phy_action *pa = &rtl_fw->phy_action;
size_t index;
for (index = 0; index < pa->size; index++) {
u32 action = le32_to_cpu(pa->code[index]);
u32 val = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
switch (action >> 28) {
case PHY_READ:
case PHY_DATA_OR:
case PHY_DATA_AND:
case PHY_CLEAR_READCOUNT:
case PHY_WRITE:
case PHY_WRITE_PREVIOUS:
case PHY_DELAY_MS:
break;
case PHY_MDIO_CHG:
if (val > 1)
goto out;
break;
case PHY_BJMPN:
if (regno > index)
goto out;
break;
case PHY_READCOUNT_EQ_SKIP:
if (index + 2 >= pa->size)
goto out;
break;
case PHY_COMP_EQ_SKIPN:
case PHY_COMP_NEQ_SKIPN:
case PHY_SKIPN:
if (index + 1 + regno >= pa->size)
goto out;
break;
default:
dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
return false;
}
}
return true;
out:
dev_err(rtl_fw->dev, "Out of range of firmware\n");
return false;
}
void rtl8126_fw_write_firmware(struct rtl8126_private *tp, struct rtl8126_fw *rtl_fw)
{
struct rtl8126_fw_phy_action *pa = &rtl_fw->phy_action;
rtl8126_fw_write_t fw_write = rtl_fw->phy_write;
rtl8126_fw_read_t fw_read = rtl_fw->phy_read;
int predata = 0, count = 0;
size_t index;
for (index = 0; index < pa->size; index++) {
u32 action = le32_to_cpu(pa->code[index]);
u32 data = action & 0x0000ffff;
u32 regno = (action & 0x0fff0000) >> 16;
enum rtl_fw_opcode opcode = action >> 28;
if (!action)
break;
switch (opcode) {
case PHY_READ:
predata = fw_read(tp, regno);
count++;
break;
case PHY_DATA_OR:
predata |= data;
break;
case PHY_DATA_AND:
predata &= data;
break;
case PHY_BJMPN:
index -= (regno + 1);
break;
case PHY_MDIO_CHG:
if (data) {
fw_write = rtl_fw->mac_mcu_write;
fw_read = rtl_fw->mac_mcu_read;
} else {
fw_write = rtl_fw->phy_write;
fw_read = rtl_fw->phy_read;
}
break;
case PHY_CLEAR_READCOUNT:
count = 0;
break;
case PHY_WRITE:
fw_write(tp, regno, data);
break;
case PHY_READCOUNT_EQ_SKIP:
if (count == data)
index++;
break;
case PHY_COMP_EQ_SKIPN:
if (predata == data)
index += regno;
break;
case PHY_COMP_NEQ_SKIPN:
if (predata != data)
index += regno;
break;
case PHY_WRITE_PREVIOUS:
fw_write(tp, regno, predata);
break;
case PHY_SKIPN:
index += regno;
break;
case PHY_DELAY_MS:
mdelay(data);
break;
}
}
}
void rtl8126_fw_release_firmware(struct rtl8126_fw *rtl_fw)
{
release_firmware(rtl_fw->fw);
}
int rtl8126_fw_request_firmware(struct rtl8126_fw *rtl_fw)
{
int rc;
rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
if (rc < 0)
goto out;
if (!rtl8126_fw_format_ok(rtl_fw) || !rtl8126_fw_data_ok(rtl_fw)) {
release_firmware(rtl_fw->fw);
rc = -EINVAL;
goto out;
}
return 0;
out:
dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
rtl_fw->fw_name, rc);
return rc;
}

View File

@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_R8126_FIRMWARE_H
#define _LINUX_R8126_FIRMWARE_H
#include <linux/device.h>
#include <linux/firmware.h>
struct rtl8126_private;
typedef void (*rtl8126_fw_write_t)(struct rtl8126_private *tp, u16 reg, u16 val);
typedef u32 (*rtl8126_fw_read_t)(struct rtl8126_private *tp, u16 reg);
#define RTL8126_VER_SIZE 32
struct rtl8126_fw {
rtl8126_fw_write_t phy_write;
rtl8126_fw_read_t phy_read;
rtl8126_fw_write_t mac_mcu_write;
rtl8126_fw_read_t mac_mcu_read;
const struct firmware *fw;
const char *fw_name;
struct device *dev;
char version[RTL8126_VER_SIZE];
struct rtl8126_fw_phy_action {
__le32 *code;
size_t size;
} phy_action;
};
int rtl8126_fw_request_firmware(struct rtl8126_fw *rtl_fw);
void rtl8126_fw_release_firmware(struct rtl8126_fw *rtl_fw);
void rtl8126_fw_write_firmware(struct rtl8126_private *tp, struct rtl8126_fw *rtl_fw);
#endif /* _LINUX_R8126_FIRMWARE_H */

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,892 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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/module.h>
#include <linux/version.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/mii.h>
#include <linux/in.h>
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include "r8126.h"
#include "r8126_ptp.h"
static void rtl8126_wait_clkadj_ready(struct rtl8126_private *tp)
{
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CLK_CFG_8126) & CLKADJ_MODE_SET))
break;
}
static void rtl8126_set_clkadj_mode(struct rtl8126_private *tp, u16 cmd)
{
rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
PTP_CLK_CFG_8126,
BIT_3 | BIT_2 | BIT_1,
CLKADJ_MODE_SET | cmd);
rtl8126_wait_clkadj_ready(tp);
}
static int _rtl8126_phc_gettime(struct rtl8126_private *tp, struct timespec64 *ts64)
{
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
//Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
/* nanoseconds */
//Ns[29:16] E414[13:0]
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_HI_8126) & 0x3fff;
ts64->tv_nsec <<= 16;
//Ns[15:0] E412[15:0]
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_NS_LO_8126);
/* seconds */
//S[47:32] E41A[15:0]
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
ts64->tv_sec <<= 16;
//S[31:16] E418[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
ts64->tv_sec <<= 16;
//S[15:0] E416[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0;
}
static int _rtl8126_phc_settime(struct rtl8126_private *tp, const struct timespec64 *ts64)
{
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
/* nanoseconds */
//Ns[15:0] E412[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, ts64->tv_nsec);
//Ns[29:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (ts64->tv_nsec & 0x3fff0000) >> 16);
/* seconds */
//S[15:0] E416[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, ts64->tv_sec);
//S[31:16] E418[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (ts64->tv_sec >> 16));
//S[47:32] E41A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (ts64->tv_sec >> 32));
//Direct Write
rtl8126_set_clkadj_mode(tp, DIRECT_WRITE);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0;
}
static int _rtl8126_phc_adjtime(struct rtl8126_private *tp, s64 delta)
{
unsigned long flags;
struct timespec64 d;
bool negative;
u64 tohw;
u32 nsec;
u64 sec;
if (delta < 0) {
negative = true;
tohw = -delta;
} else {
negative = false;
tohw = delta;
}
d = ns_to_timespec64(tohw);
nsec = d.tv_nsec;
sec = d.tv_sec;
nsec &= 0x3fffffff;
sec &= 0x0000ffffffffffff;
spin_lock_irqsave(&tp->phy_lock, flags);
/* nanoseconds */
//Ns[15:0] E412[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, nsec);
//Ns[29:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (nsec >> 16));
/* seconds */
//S[15:0] E416[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_LO_8126, sec);
//S[31:16] E418[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_MI_8126, (sec >> 16));
//S[47:32] E41A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_S_HI_8126, (sec >> 32));
if (negative)
rtl8126_set_clkadj_mode(tp, DECREMENT_STEP);
else
rtl8126_set_clkadj_mode(tp, INCREMENT_STEP);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0;
}
static int rtl8126_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
int ret;
//netif_info(tp, drv, tp->dev, "phc adjust time\n");
ret = _rtl8126_phc_adjtime(tp, delta);
return ret;
}
/*
* delta = delta * 10^6 ppm = delta * 10^9 ppb (in this equation ppm and ppb are not variable)
*
* in adjfreq ppb is a variable
* ppb = delta * 10^9
* delta = ppb / 10^9
* rate_value = |delta| * 2^32 = |ppb| / 10^9 * 2^32 = (|ppb| << 32) / 10^9
*/
static int _rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
unsigned long flags;
u32 rate_value;
if (ppb < 0) {
rate_value = ((u64)-ppb << 32) / 1000000000;
rate_value = ~rate_value + 1;
} else
rate_value = ((u64)ppb << 32) / 1000000000;
spin_lock_irqsave(&tp->phy_lock, flags);
/* nanoseconds */
//Ns[15:0] E412[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_LO_8126, rate_value);
//Ns[22:16] E414[13:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CFG_NS_HI_8126, (rate_value & 0x003f0000) >> 16);
rtl8126_set_clkadj_mode(tp, RATE_WRITE);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
static int rtl8126_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
if (ppb > ptp->max_adj || ppb < -ptp->max_adj)
return -EINVAL;
_rtl8126_phc_adjfreq(ptp, ppb);
return 0;
}
#else
static int rtl8126_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
{
//struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
//netif_info(tp, drv, tp->dev, "phc adjust freq\n");
if (delta > ptp->max_adj || delta < -ptp->max_adj)
return -EINVAL;
_rtl8126_phc_adjfreq(ptp, delta);
return 0;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64,
struct ptp_system_timestamp *sts)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
int ret;
//netif_info(tp, drv, tp->dev, "phc get ts\n");
ptp_read_system_prets(sts);
ret = _rtl8126_phc_gettime(tp, ts64);
ptp_read_system_postts(sts);
return ret;
}
#else
static int rtl8126_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
int ret;
//netif_info(tp, drv, tp->dev, "phc get ts\n");
ret = _rtl8126_phc_gettime(tp, ts64);
return ret;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
static int rtl8126_phc_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts64)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
int ret;
//netif_info(tp, drv, tp->dev, "phc set ts\n");
ret = _rtl8126_phc_settime(tp, ts64);
return ret;
}
static void _rtl8126_phc_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
struct rtl8126_private *tp = container_of(ptp, struct rtl8126_private, ptp_clock_info);
unsigned long flags;
u16 phy_ocp_data;
if (on) {
tp->pps_enable = 1;
rtl8126_clear_mac_ocp_bit(tp, 0xDC00, BIT_6);
rtl8126_clear_mac_ocp_bit(tp, 0xDC20, BIT_1);
spin_lock_irqsave(&tp->phy_lock, flags);
/* Set periodic pulse 1pps */
/* E432[8:0] = 0x017d */
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE432);
phy_ocp_data &= 0xFE00;
phy_ocp_data |= 0x017d;
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE432, phy_ocp_data);
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE434, 0x7840);
/* E436[8:0] = 0xbe */
phy_ocp_data = rtl8126_mdio_direct_read_phy_ocp(tp, 0xE436);
phy_ocp_data &= 0xFE00;
phy_ocp_data |= 0xbe;
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE436, phy_ocp_data);
rtl8126_mdio_direct_write_phy_ocp(tp, 0xE438, 0xbc20);
spin_unlock_irqrestore(&tp->phy_lock, flags);
/* start hrtimer */
hrtimer_start(&tp->pps_timer, 1000000000, HRTIMER_MODE_REL);
} else
tp->pps_enable = 0;
}
static int rtl8126_phc_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
switch (rq->type) {
case PTP_CLK_REQ_PPS:
_rtl8126_phc_enable(ptp, rq, on);
return 0;
default:
return -EOPNOTSUPP;
}
}
static void rtl8126_ptp_enable_config(struct rtl8126_private *tp)
{
u16 ptp_ctrl;
if (tp->syncE_en)
rtl8126_set_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
else
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
ptp_ctrl = BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 | BIT_12;
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_CTL, ptp_ctrl);
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
}
int rtl8126_get_ts_info(struct net_device *netdev,
struct ethtool_ts_info *info)
{
struct rtl8126_private *tp = netdev_priv(netdev);
/* we always support timestamping disabled */
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
if (tp->HwSuppPtpVer == 0)
return ethtool_op_get_ts_info(netdev, info);
info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
if (tp->ptp_clock)
info->phc_index = ptp_clock_index(tp->ptp_clock);
else
info->phc_index = -1;
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
return 0;
}
static const struct ptp_clock_info rtl_ptp_clock_info = {
.owner = THIS_MODULE,
.n_alarm = 0,
.n_ext_ts = 0,
.n_per_out = 0,
.n_pins = 0,
.pps = 1,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
.adjfine = rtl8126_ptp_adjfine,
#else
.adjfreq = rtl8126_phc_adjfreq,
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0) */
.adjtime = rtl8126_phc_adjtime,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
.gettimex64 = rtl8126_phc_gettime,
#else
.gettime64 = rtl8126_phc_gettime,
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) */
.settime64 = rtl8126_phc_settime,
.enable = rtl8126_phc_enable,
};
static u16 rtl8126_ptp_get_tx_msgtype(struct rtl8126_private *tp)
{
u16 tx_ts_ready = 0;
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
tx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0xF000;
if (tx_ts_ready)
break;
}
switch (tx_ts_ready) {
case TX_TS_PDLYRSP_RDY:
return 3;
case TX_TS_PDLYREQ_RDY:
return 2;
case TX_TS_DLYREQ_RDY:
return 1;
case TX_TS_SYNC_RDY:
default:
return 0;
}
}
static u16 rtl8126_ptp_get_rx_msgtype(struct rtl8126_private *tp)
{
u16 rx_ts_ready = 0;
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++) {
rx_ts_ready = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & 0x0F00;
if (rx_ts_ready)
break;
}
switch (rx_ts_ready) {
case RX_TS_PDLYRSP_RDY:
return 3;
case RX_TS_PDLYREQ_RDY:
return 2;
case RX_TS_DLYREQ_RDY:
return 1;
case RX_TS_SYNC_RDY:
default:
return 0;
}
}
static void rtl8126_wait_trx_ts_ready(struct rtl8126_private *tp)
{
int i;
for (i = 0; i < R8126_CHANNEL_WAIT_COUNT; i++)
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_STA) & TRX_TS_RD))
break;
}
static void rtl8126_set_trx_ts_cmd(struct rtl8126_private *tp, u16 cmd)
{
rtl8126_clear_and_set_eth_phy_ocp_bit(tp,
PTP_TRX_TS_STA,
TRXTS_SEL | BIT_3 | BIT_2,
TRX_TS_RD | cmd);
rtl8126_wait_trx_ts_ready(tp);
}
static void rtl8126_ptp_egresstime(struct rtl8126_private *tp, struct timespec64 *ts64)
{
u16 msgtype;
msgtype = rtl8126_ptp_get_tx_msgtype(tp);
msgtype <<= 2;
rtl8126_set_trx_ts_cmd(tp, (msgtype | BIT_4));
/* nanoseconds */
//Ns[29:16] E448[13:0]
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
ts64->tv_nsec <<= 16;
//Ns[15:0] E446[15:0]
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
/* seconds */
//S[47:32] E44E[15:0]
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
ts64->tv_sec <<= 16;
//S[31:16] E44C[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
ts64->tv_sec <<= 16;
//S[15:0] E44A[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
}
static void rtl8126_ptp_ingresstime(struct rtl8126_private *tp, struct timespec64 *ts64)
{
u16 msgtype;
msgtype = rtl8126_ptp_get_rx_msgtype(tp);
msgtype <<= 2;
rtl8126_set_trx_ts_cmd(tp, (TRXTS_SEL | msgtype | BIT_4));
/* nanoseconds */
//Ns[29:16] E448[13:0]
ts64->tv_nsec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_HI) & 0x3fff;
ts64->tv_nsec <<= 16;
//Ns[15:0] E446[15:0]
ts64->tv_nsec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_NS_LO);
/* seconds */
//S[47:32] E44E[15:0]
ts64->tv_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_HI);
ts64->tv_sec <<= 16;
//S[31:16] E44C[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_MI);
ts64->tv_sec <<= 16;
//S[15:0] E44A[15:0]
ts64->tv_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_TRX_TS_S_LO);
}
static void rtl8126_ptp_tx_hwtstamp(struct rtl8126_private *tp)
{
struct sk_buff *skb = tp->ptp_tx_skb;
struct skb_shared_hwtstamps shhwtstamps = { 0 };
struct timespec64 ts64;
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
rtl8126_ptp_egresstime(tp, &ts64);
/* Upper 32 bits contain s, lower 32 bits contain ns. */
shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec,
ts64.tv_nsec);
/* Clear the lock early before calling skb_tstamp_tx so that
* applications are not woken up before the lock bit is clear. We use
* a copy of the skb pointer to ensure other threads can't change it
* while we're notifying the stack.
*/
tp->ptp_tx_skb = NULL;
clear_bit_unlock(__RTL8126_PTP_TX_IN_PROGRESS, &tp->state);
/* Notify the stack and free the skb after we've unlocked */
skb_tstamp_tx(skb, &shhwtstamps);
dev_kfree_skb_any(skb);
}
#define RTL8126_PTP_TX_TIMEOUT (HZ * 15)
static void rtl8126_ptp_tx_work(struct work_struct *work)
{
struct rtl8126_private *tp = container_of(work, struct rtl8126_private,
ptp_tx_work);
unsigned long flags;
if (!tp->ptp_tx_skb)
return;
if (time_is_before_jiffies(tp->ptp_tx_start +
RTL8126_PTP_TX_TIMEOUT)) {
dev_kfree_skb_any(tp->ptp_tx_skb);
tp->ptp_tx_skb = NULL;
clear_bit_unlock(__RTL8126_PTP_TX_IN_PROGRESS, &tp->state);
tp->tx_hwtstamp_timeouts++;
/* Clear the tx valid bit in TSYNCTXCTL register to enable
* interrupt
*/
spin_lock_irqsave(&tp->phy_lock, flags);
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, TX_TX_INTR);
spin_unlock_irqrestore(&tp->phy_lock, flags);
return;
}
spin_lock_irqsave(&tp->phy_lock, flags);
if (rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & TX_TX_INTR) {
rtl8126_ptp_tx_hwtstamp(tp);
spin_unlock_irqrestore(&tp->phy_lock, flags);
} else {
spin_unlock_irqrestore(&tp->phy_lock, flags);
/* reschedule to check later */
schedule_work(&tp->ptp_tx_work);
}
}
static int rtl8126_hwtstamp_enable(struct rtl8126_private *tp, bool enable)
{
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
if (enable) {
//trx timestamp interrupt enable
rtl8126_set_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
//set isr clear mode
rtl8126_set_eth_phy_ocp_bit(tp, PTP_GEN_CFG, BIT_0);
//clear ptp isr
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, 0xFFFF);
//enable ptp
rtl8126_ptp_enable_config(tp);
//rtl8126_set_local_time(tp);
} else {
/* trx timestamp interrupt disable */
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_INER, BIT_2 | BIT_3);
/* disable ptp */
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_SYNCE_CTL, BIT_0);
rtl8126_clear_eth_phy_ocp_bit(tp, PTP_CTL, BIT_0);
rtl8126_set_eth_phy_ocp_bit(tp, 0xA640, BIT_15);
}
spin_unlock_irqrestore(&tp->phy_lock, flags);
return 0;
}
void rtl8126_set_local_time(struct rtl8126_private *tp)
{
struct timespec64 ts64;
//set system time
ktime_get_real_ts64(&ts64);
_rtl8126_phc_settime(tp, &ts64);
}
static long rtl8126_ptp_create_clock(struct rtl8126_private *tp)
{
struct net_device *netdev = tp->dev;
long err;
if (!IS_ERR_OR_NULL(tp->ptp_clock))
return 0;
if (tp->HwSuppPtpVer == 0) {
tp->ptp_clock = NULL;
return -EOPNOTSUPP;
}
tp->ptp_clock_info = rtl_ptp_clock_info;
tp->ptp_clock_info.max_adj = 488281;//0x1FFFFF * 10^9 / 2^32
snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name),
"%pm", tp->dev->dev_addr);
tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev);
if (IS_ERR(tp->ptp_clock)) {
err = PTR_ERR(tp->ptp_clock);
tp->ptp_clock = NULL;
netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n");
return err;
} else
netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name);
return 0;
}
static enum hrtimer_restart
rtl8126_hrtimer_for_pps(struct hrtimer *timer) {
struct rtl8126_private *tp = container_of(timer, struct rtl8126_private, pps_timer);
u16 tai_cfg = BIT_8 | BIT_3 | BIT_1 | BIT_0;
s64 pps_sec;
if (tp->pps_enable)
{
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
//Direct Read
rtl8126_set_clkadj_mode(tp, DIRECT_READ);
pps_sec = rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_HI_8126);
pps_sec <<= 16;
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_MI_8126);
pps_sec <<= 16;
pps_sec |= rtl8126_mdio_direct_read_phy_ocp(tp, PTP_CFG_S_LO_8126);
pps_sec++;
//E42A[15:0]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_LO, pps_sec & 0xffff);
//E42C[31:16]
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_TS_S_HI, (pps_sec & 0xffff0000) >> 16);
//Periodic Tai start
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_TAI_CFG, tai_cfg);
spin_unlock_irqrestore(&tp->phy_lock, flags);
hrtimer_forward_now(&tp->pps_timer, 1000000000); //rekick
return HRTIMER_RESTART;
} else
return HRTIMER_NORESTART;
}
void rtl8126_ptp_reset(struct rtl8126_private *tp)
{
if (!tp->ptp_clock)
return;
netif_info(tp, drv, tp->dev, "reset PHC clock\n");
rtl8126_hwtstamp_enable(tp, false);
}
void rtl8126_ptp_init(struct rtl8126_private *tp)
{
/* obtain a PTP device, or re-use an existing device */
if (rtl8126_ptp_create_clock(tp))
return;
/* we have a clock so we can initialize work now */
INIT_WORK(&tp->ptp_tx_work, rtl8126_ptp_tx_work);
/* init a hrtimer for pps */
tp->pps_enable = 0;
hrtimer_init(&tp->pps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
tp->pps_timer.function = rtl8126_hrtimer_for_pps;
/* reset the PTP related hardware bits */
rtl8126_ptp_reset(tp);
return;
}
void rtl8126_ptp_suspend(struct rtl8126_private *tp)
{
if (!tp->ptp_clock)
return;
netif_info(tp, drv, tp->dev, "suspend PHC clock\n");
rtl8126_hwtstamp_enable(tp, false);
/* ensure that we cancel any pending PTP Tx work item in progress */
cancel_work_sync(&tp->ptp_tx_work);
hrtimer_cancel(&tp->pps_timer);
}
void rtl8126_ptp_stop(struct rtl8126_private *tp)
{
struct net_device *netdev = tp->dev;
netif_info(tp, drv, tp->dev, "stop PHC clock\n");
/* first, suspend PTP activity */
rtl8126_ptp_suspend(tp);
/* disable the PTP clock device */
if (tp->ptp_clock) {
ptp_clock_unregister(tp->ptp_clock);
tp->ptp_clock = NULL;
netif_info(tp, drv, tp->dev, "removed PHC on %s\n",
netdev->name);
}
}
static int rtl8126_set_tstamp(struct net_device *netdev, struct ifreq *ifr)
{
struct rtl8126_private *tp = netdev_priv(netdev);
struct hwtstamp_config config;
bool hwtstamp = 0;
//netif_info(tp, drv, tp->dev, "ptp set ts\n");
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
if (config.flags)
return -EINVAL;
switch (config.tx_type) {
case HWTSTAMP_TX_ON:
hwtstamp = 1;
break;
case HWTSTAMP_TX_OFF:
break;
case HWTSTAMP_TX_ONESTEP_SYNC:
default:
return -ERANGE;
}
switch (config.rx_filter) {
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
hwtstamp = 1;
tp->flags |= RTL_FLAG_RX_HWTSTAMP_ENABLED;
break;
case HWTSTAMP_FILTER_NONE:
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
break;
default:
tp->flags &= ~RTL_FLAG_RX_HWTSTAMP_ENABLED;
return -ERANGE;
}
if (tp->hwtstamp_config.tx_type != config.tx_type ||
tp->hwtstamp_config.rx_filter != config.rx_filter) {
tp->hwtstamp_config = config;
rtl8126_hwtstamp_enable(tp, hwtstamp);
}
return copy_to_user(ifr->ifr_data, &config,
sizeof(config)) ? -EFAULT : 0;
}
static int rtl8126_get_tstamp(struct net_device *netdev, struct ifreq *ifr)
{
struct rtl8126_private *tp = netdev_priv(netdev);
//netif_info(tp, drv, tp->dev, "ptp get ts\n");
return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config,
sizeof(tp->hwtstamp_config)) ? -EFAULT : 0;
}
int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
int ret;
//netif_info(tp, drv, tp->dev, "ptp ioctl\n");
switch (cmd) {
#ifdef ENABLE_PTP_SUPPORT
case SIOCSHWTSTAMP:
ret = rtl8126_set_tstamp(netdev, ifr);
break;
case SIOCGHWTSTAMP:
ret = rtl8126_get_tstamp(netdev, ifr);
break;
#endif
default:
ret = -EOPNOTSUPP;
break;
}
return ret;
}
void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb)
{
struct timespec64 ts64;
unsigned long flags;
spin_lock_irqsave(&tp->phy_lock, flags);
if (!(rtl8126_mdio_direct_read_phy_ocp(tp, PTP_INSR) & RX_TS_INTR)) {
spin_unlock_irqrestore(&tp->phy_lock, flags);
return;
}
rtl8126_mdio_direct_write_phy_ocp(tp, PTP_INSR, RX_TS_INTR);
rtl8126_ptp_ingresstime(tp, &ts64);
spin_unlock_irqrestore(&tp->phy_lock, flags);
skb_hwtstamps(skb)->hwtstamp = ktime_set(ts64.tv_sec, ts64.tv_nsec);
return;
}

View File

@@ -0,0 +1,113 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_R8126_PTP_H
#define _LINUX_R8126_PTP_H
#include <linux/ktime.h>
#include <linux/timecounter.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/ptp_classify.h>
struct rtl8126_ptp_info {
s64 time_sec;
u32 time_ns;
u16 ts_info;
};
#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
struct timespec {
__kernel_old_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
enum PTP_CMD_TYPE {
PTP_CMD_SET_LOCAL_TIME = 0,
PTP_CMD_DRIFT_LOCAL_TIME,
PTP_CMD_LATCHED_LOCAL_TIME,
};
enum PTP_CLKADJ_MOD_TYPE {
NO_FUNCTION = 0,
CLKADJ_MODE_SET = 1,
RESERVED = 2,
DIRECT_READ = 4,
DIRECT_WRITE = 6,
INCREMENT_STEP = 8,
DECREMENT_STEP = 10,
RATE_READ = 12,
RATE_WRITE = 14,
};
enum PTP_INSR_TYPE {
EVENT_CAP_INTR = (1 << 0),
TRIG_GEN_INTR = (1 << 1),
RX_TS_INTR = (1 << 2),
TX_TX_INTR = (1 << 3),
};
enum PTP_TRX_TS_STA_REG {
TRX_TS_RD = (1 << 0),
TRXTS_SEL = (1 << 1),
RX_TS_PDLYRSP_RDY = (1 << 8),
RX_TS_PDLYREQ_RDY = (1 << 9),
RX_TS_DLYREQ_RDY = (1 << 10),
RX_TS_SYNC_RDY = (1 << 11),
TX_TS_PDLYRSP_RDY = (1 << 12),
TX_TS_PDLYREQ_RDY = (1 << 13),
TX_TS_DLYREQ_RDY = (1 << 14),
TX_TS_SYNC_RDY = (1 << 15),
};
struct rtl8126_private;
struct RxDescV3;
int rtl8126_get_ts_info(struct net_device *netdev,
struct ethtool_ts_info *info);
void rtl8126_ptp_reset(struct rtl8126_private *tp);
void rtl8126_ptp_init(struct rtl8126_private *tp);
void rtl8126_ptp_suspend(struct rtl8126_private *tp);
void rtl8126_ptp_stop(struct rtl8126_private *tp);
int rtl8126_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
void rtl8126_rx_ptp_pktstamp(struct rtl8126_private *tp, struct sk_buff *skb);
void rtl8126_set_local_time(struct rtl8126_private *tp);
#endif /* _LINUX_R8126_PTP_H */

View File

@@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_R8126_REALWOW_H
#define _LINUX_R8126_REALWOW_H
#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3
#define MAX_RealWoW_KCP_SIZE (100)
#define MAX_RealWoW_Payload (64)
#define KA_TX_PACKET_SIZE (100)
#define KA_WAKEUP_PATTERN_SIZE (120)
//HwSuppKeepAliveOffloadVer
#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0)
enum rtl_realwow_cmd {
RTL_REALWOW_SET_KCP_DISABLE=0,
RTL_REALWOW_SET_KCP_INFO,
RTL_REALWOW_SET_KCP_CONTENT,
RTL_REALWOW_SET_KCP_ACKPKTINFO,
RTL_REALWOW_SET_KCP_WPINFO,
RTL_REALWOW_SET_KCPDHCP_TIMEOUT,
RTLT_REALWOW_COMMAND_INVALID
};
struct rtl_realwow_ioctl_struct {
__u32 cmd;
__u32 offset;
__u32 len;
union {
__u32 data;
void *data_buffer;
};
};
typedef struct _MP_KCPInfo {
u8 DIPv4[4];
u8 MacID[6];
u16 UdpPort[2];
u8 PKTLEN[2];
u16 ackLostCnt;
u8 KCP_WakePattern[MAX_RealWoW_Payload];
u8 KCP_AckPacket[MAX_RealWoW_Payload];
u32 KCP_interval;
u8 KCP_WakePattern_Len;
u8 KCP_AckPacket_Len;
u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE];
} MP_KCP_INFO, *PMP_KCP_INFO;
typedef struct _KCPInfo {
u32 nId; // = id
u8 DIPv4[4];
u8 MacID[6];
u16 UdpPort;
u16 PKTLEN;
} KCPInfo, *PKCPInfo;
typedef struct _KCPContent {
u32 id; // = id
u32 mSec; // = msec
u32 size; // =size
u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here
} KCPContent, *PKCPContent;
typedef struct _RealWoWAckPktInfo {
u16 ackLostCnt;
u16 patterntSize;
u8 pattern[MAX_RealWoW_Payload];
} RealWoWAckPktInfo,*PRealWoWAckPktInfo;
typedef struct _RealWoWWPInfo {
u16 patterntSize;
u8 pattern[MAX_RealWoW_Payload];
} RealWoWWPInfo,*PRealWoWWPInfo;
int rtl8126_realwow_ioctl(struct net_device *dev, struct ifreq *ifr);
void rtl8126_realwow_hw_init(struct net_device *dev);
void rtl8126_get_realwow_hw_version(struct net_device *dev);
void rtl8126_set_realwow_d3_para(struct net_device *dev);
#endif /* _LINUX_R8126_REALWOW_H */

View File

@@ -0,0 +1,601 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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 "r8126.h"
enum rtl8126_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_CTRL_UDP_IPV4_SUPP = (1 << 11),
RSS_CTRL_UDP_IPV6_SUPP = (1 << 12),
RSS_CTRL_UDP_IPV6_EXT_SUPP = (1 << 13),
RSS_QUAD_CPU_EN = (1 << 16),
RSS_HQ_Q_SUP_R = (1 << 31),
};
static int rtl8126_get_rss_hash_opts(struct rtl8126_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 UDP_V4_FLOW:
if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4)
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 UDP_V6_FLOW:
if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6)
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 rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct rtl8126_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP;
netif_info(tp, drv, tp->dev, "rss get rxnfc\n");
if (!(dev->features & NETIF_F_RXHASH))
return ret;
switch (cmd->cmd) {
case ETHTOOL_GRXRINGS:
cmd->data = rtl8126_tot_rx_rings(tp);
ret = 0;
break;
case ETHTOOL_GRXFH:
ret = rtl8126_get_rss_hash_opts(tp, cmd);
break;
default:
break;
}
return ret;
}
u32 rtl8126_rss_indir_tbl_entries(struct rtl8126_private *tp)
{
return tp->HwSuppIndirTblEntries;
}
#define RSS_MASK_BITS_OFFSET (8)
#define RSS_CPU_NUM_OFFSET (16)
#define RTL8126_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \
RTL_8125_RSS_FLAG_HASH_UDP_IPV6)
static int _rtl8126_set_rss_hash_opt(struct rtl8126_private *tp)
{
u32 rss_flags = tp->rss_flags;
u32 hash_mask_len;
u32 rss_ctrl;
rss_ctrl = ilog2(rtl8126_tot_rx_rings(tp));
rss_ctrl &= (BIT_0 | BIT_1 | BIT_2);
rss_ctrl <<= RSS_CPU_NUM_OFFSET;
/* 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 (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4)
rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP;
if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6)
rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP |
RSS_CTRL_UDP_IPV6_EXT_SUPP;
hash_mask_len = ilog2(rtl8126_rss_indir_tbl_entries(tp));
hash_mask_len &= (BIT_0 | BIT_1 | BIT_2);
rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET;
RTL_W32(tp, RSS_CTRL_8125, rss_ctrl);
return 0;
}
static int rtl8126_set_rss_hash_opt(struct rtl8126_private *tp,
struct ethtool_rxnfc *nfc)
{
u32 rss_flags = tp->rss_flags;
netif_info(tp, drv, tp->dev, "rss set hash\n");
/*
* 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 UDP_V4_FLOW:
if (!(nfc->data & RXH_IP_SRC) ||
!(nfc->data & RXH_IP_DST))
return -EINVAL;
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
case 0:
rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4;
break;
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4;
break;
default:
return -EINVAL;
}
break;
case UDP_V6_FLOW:
if (!(nfc->data & RXH_IP_SRC) ||
!(nfc->data & RXH_IP_DST))
return -EINVAL;
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
case 0:
rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6;
break;
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6;
break;
default:
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;
break;
default:
return -EINVAL;
}
/* if we changed something we need to update flags */
if (rss_flags != tp->rss_flags) {
u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125);
if ((rss_flags & RTL8126_UDP_RSS_FLAGS) &&
!(tp->rss_flags & RTL8126_UDP_RSS_FLAGS))
netdev_warn(tp->dev,
"enabling UDP RSS: fragmented packets may "
"arrive out of order to the stack above\n");
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;
rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP |
RSS_CTRL_UDP_IPV6_SUPP |
RSS_CTRL_UDP_IPV6_EXT_SUPP);
if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4)
rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP;
if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6)
rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP |
RSS_CTRL_UDP_IPV6_EXT_SUPP;
RTL_W32(tp, RSS_CTRL_8125, rss_ctrl);
}
return 0;
}
int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
struct rtl8126_private *tp = netdev_priv(dev);
int ret = -EOPNOTSUPP;
netif_info(tp, drv, tp->dev, "rss set rxnfc\n");
if (!(dev->features & NETIF_F_RXHASH))
return ret;
switch (cmd->cmd) {
case ETHTOOL_SRXFH:
ret = rtl8126_set_rss_hash_opt(tp, cmd);
break;
default:
break;
}
return ret;
}
static u32 _rtl8126_get_rxfh_key_size(struct rtl8126_private *tp)
{
return sizeof(tp->rss_key);
}
u32 rtl8126_get_rxfh_key_size(struct net_device *dev)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get key size\n");
if (!(dev->features & NETIF_F_RXHASH))
return 0;
return _rtl8126_get_rxfh_key_size(tp);
}
u32 rtl8126_rss_indir_size(struct net_device *dev)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get indir tbl size\n");
if (!(dev->features & NETIF_F_RXHASH))
return 0;
return rtl8126_rss_indir_tbl_entries(tp);
}
static void rtl8126_get_reta(struct rtl8126_private *tp, u32 *indir)
{
int i, reta_size = rtl8126_rss_indir_tbl_entries(tp);
for (i = 0; i < reta_size; i++)
indir[i] = tp->rss_indir_tbl[i];
}
static u32 rtl8126_rss_key_reg(struct rtl8126_private *tp)
{
return RSS_KEY_8125;
}
static u32 rtl8126_rss_indir_tbl_reg(struct rtl8126_private *tp)
{
return RSS_INDIRECTION_TBL_8125_V2;
}
static void rtl8126_store_reta(struct rtl8126_private *tp)
{
u16 indir_tbl_reg = rtl8126_rss_indir_tbl_reg(tp);
u32 i, reta_entries = rtl8126_rss_indir_tbl_entries(tp);
u32 reta = 0;
u8 *indir_tbl = tp->rss_indir_tbl;
/* Write redirection table to HW */
for (i = 0; i < reta_entries; i++) {
reta |= indir_tbl[i] << (i & 0x3) * 8;
if ((i & 3) == 3) {
RTL_W32(tp, indir_tbl_reg, reta);
indir_tbl_reg += 4;
reta = 0;
}
}
}
static void rtl8126_store_rss_key(struct rtl8126_private *tp)
{
const u16 rss_key_reg = rtl8126_rss_key_reg(tp);
u32 i, rss_key_size = _rtl8126_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)
RTL_W32(tp, rss_key_reg + i, *rss_key++);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->indir)
rtl8126_get_reta(tp, rxfh->indir);
if (rxfh->key)
memcpy(rxfh->key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
return 0;
}
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct rtl8126_private *tp = netdev_priv(dev);
int i;
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp);
netif_info(tp, drv, tp->dev, "rss set rxfh\n");
/* 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, RTL8126_RSS_KEY_SIZE);
rtl8126_store_reta(tp);
rtl8126_store_rss_key(tp);
return 0;
}
#else
int rtl8126_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct rtl8126_private *tp = netdev_priv(dev);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
if (!(dev->features & NETIF_F_RXHASH))
return -EOPNOTSUPP;
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;
if (indir)
rtl8126_get_reta(tp, indir);
if (key)
memcpy(key, tp->rss_key, RTL8126_RSS_KEY_SIZE);
return 0;
}
int rtl8126_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct rtl8126_private *tp = netdev_priv(dev);
int i;
u32 reta_entries = rtl8126_rss_indir_tbl_entries(tp);
netif_info(tp, drv, tp->dev, "rss set rxfh\n");
/* 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, RTL8126_RSS_KEY_SIZE);
rtl8126_store_reta(tp);
rtl8126_store_rss_key(tp);
return 0;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
static u32 rtl8126_get_rx_desc_hash(struct rtl8126_private *tp,
struct RxDesc *desc)
{
switch (tp->InitRxDescType) {
case RX_DESC_RING_TYPE_3:
return le32_to_cpu(((struct RxDescV3 *)desc)->RxDescNormalDDWord2.RSSResult);
case RX_DESC_RING_TYPE_4:
return le32_to_cpu(((struct RxDescV4 *)desc)->RxDescNormalDDWord1.RSSResult);
default:
return 0;
}
}
#define RXS_8125B_RSS_UDP BIT(9)
#define RXS_8125_RSS_IPV4 BIT(10)
#define RXS_8125_RSS_IPV6 BIT(12)
#define RXS_8125_RSS_TCP BIT(13)
#define RTL8126_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6)
#define RTL8126_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP)
#define RXS_8125B_RSS_UDP_V4 BIT(27)
#define RXS_8125_RSS_IPV4_V4 BIT(28)
#define RXS_8125_RSS_IPV6_V4 BIT(29)
#define RXS_8125_RSS_TCP_V4 BIT(30)
#define RTL8126_RXS_RSS_L3_TYPE_MASK_V4 (RXS_8125_RSS_IPV4_V4 | RXS_8125_RSS_IPV6_V4)
#define RTL8126_RXS_RSS_L4_TYPE_MASK_V4 (RXS_8125_RSS_TCP_V4 | RXS_8125B_RSS_UDP_V4)
static void rtl8126_rx_hash_v3(struct rtl8126_private *tp,
struct RxDescV3 *descv3,
struct sk_buff *skb)
{
u16 rss_header_info;
if (!(tp->dev->features & NETIF_F_RXHASH))
return;
rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo);
if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK))
return;
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv3),
(RTL8126_RXS_RSS_L4_TYPE_MASK & rss_header_info) ?
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
}
static void rtl8126_rx_hash_v4(struct rtl8126_private *tp,
struct RxDescV4 *descv4,
struct sk_buff *skb)
{
u32 rss_header_info;
if (!(tp->dev->features & NETIF_F_RXHASH))
return;
rss_header_info = le32_to_cpu(descv4->RxDescNormalDDWord1.RSSInfo);
if (!(rss_header_info & RTL8126_RXS_RSS_L3_TYPE_MASK_V4))
return;
skb_set_hash(skb, rtl8126_get_rx_desc_hash(tp, (struct RxDesc *)descv4),
(RTL8126_RXS_RSS_L4_TYPE_MASK_V4 & rss_header_info) ?
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
}
void rtl8126_rx_hash(struct rtl8126_private *tp,
struct RxDesc *desc,
struct sk_buff *skb)
{
switch (tp->InitRxDescType) {
case RX_DESC_RING_TYPE_3:
rtl8126_rx_hash_v3(tp, (struct RxDescV3 *)desc, skb);
break;
case RX_DESC_RING_TYPE_4:
rtl8126_rx_hash_v4(tp, (struct RxDescV4 *)desc, skb);
break;
default:
return;
}
}
void rtl8126_disable_rss(struct rtl8126_private *tp)
{
RTL_W32(tp, RSS_CTRL_8125, 0x00);
}
void _rtl8126_config_rss(struct rtl8126_private *tp)
{
_rtl8126_set_rss_hash_opt(tp);
rtl8126_store_reta(tp);
rtl8126_store_rss_key(tp);
}
void rtl8126_config_rss(struct rtl8126_private *tp)
{
if (!tp->EnableRss) {
rtl8126_disable_rss(tp);
return;
}
_rtl8126_config_rss(tp);
}
void rtl8126_init_rss(struct rtl8126_private *tp)
{
int i;
for (i = 0; i < rtl8126_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, RTL8126_RSS_KEY_SIZE);
}

View File

@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_R8126_RSS_H
#define _LINUX_R8126_RSS_H
#include <linux/netdevice.h>
#include <linux/types.h>
#define RTL8126_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
#define RTL8126_MAX_INDIRECTION_TABLE_ENTRIES 128
enum rtl8126_rss_flag {
RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0),
RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1),
};
struct rtl8126_private;
struct RxDesc;
int rtl8126_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs);
int rtl8126_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd);
u32 rtl8126_get_rxfh_key_size(struct net_device *netdev);
u32 rtl8126_rss_indir_size(struct net_device *netdev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0)
int rtl8126_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh);
int rtl8126_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack);
#else
int rtl8126_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc);
int rtl8126_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 rtl8126_rx_hash(struct rtl8126_private *tp,
struct RxDesc *desc,
struct sk_buff *skb);
void _rtl8126_config_rss(struct rtl8126_private *tp);
void rtl8126_config_rss(struct rtl8126_private *tp);
void rtl8126_init_rss(struct rtl8126_private *tp);
u32 rtl8126_rss_indir_tbl_entries(struct rtl8126_private *tp);
void rtl8126_disable_rss(struct rtl8126_private *tp);
#endif /* _LINUX_R8126_RSS_H */

View File

@@ -0,0 +1,285 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "r8126.h"
#include "rtl_eeprom.h"
//-------------------------------------------------------------------
//rtl8126_eeprom_type():
// tell the eeprom type
//return value:
// 0: the eeprom type is 93C46
// 1: the eeprom type is 93C56 or 93C66
//-------------------------------------------------------------------
void rtl8126_eeprom_type(struct rtl8126_private *tp)
{
u16 magic = 0;
if (tp->mcfg == CFG_METHOD_DEFAULT)
goto out_no_eeprom;
if(RTL_R8(tp, 0xD2)&0x04) {
//not support
//tp->eeprom_type = EEPROM_TWSI;
//tp->eeprom_len = 256;
goto out_no_eeprom;
} else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) {
tp->eeprom_type = EEPROM_TYPE_93C56;
tp->eeprom_len = 256;
} else {
tp->eeprom_type = EEPROM_TYPE_93C46;
tp->eeprom_len = 128;
}
magic = rtl8126_eeprom_read_sc(tp, 0);
out_no_eeprom:
if ((magic != 0x8129) && (magic != 0x8128)) {
tp->eeprom_type = EEPROM_TYPE_NONE;
tp->eeprom_len = 0;
}
}
void rtl8126_eeprom_cleanup(struct rtl8126_private *tp)
{
u8 x;
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EECS);
RTL_W8(tp, Cfg9346, x);
rtl8126_raise_clock(tp, &x);
rtl8126_lower_clock(tp, &x);
}
static int rtl8126_eeprom_cmd_done(struct rtl8126_private *tp)
{
u8 x;
int i;
rtl8126_stand_by(tp);
for (i = 0; i < 50000; i++) {
x = RTL_R8(tp, Cfg9346);
if (x & Cfg9346_EEDO) {
udelay(RTL_CLOCK_RATE * 2 * 3);
return 0;
}
udelay(1);
}
return -1;
}
//-------------------------------------------------------------------
//rtl8126_eeprom_read_sc():
// read one word from eeprom
//-------------------------------------------------------------------
u16 rtl8126_eeprom_read_sc(struct rtl8126_private *tp, u16 reg)
{
int addr_sz = 6;
u8 x;
u16 data;
if(tp->eeprom_type == EEPROM_TYPE_NONE)
return -1;
if (tp->eeprom_type==EEPROM_TYPE_93C46)
addr_sz = 6;
else if (tp->eeprom_type==EEPROM_TYPE_93C56)
addr_sz = 8;
x = Cfg9346_EEM1 | Cfg9346_EECS;
RTL_W8(tp, Cfg9346, x);
rtl8126_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3);
rtl8126_shift_out_bits(tp, reg, addr_sz);
data = rtl8126_shift_in_bits(tp);
rtl8126_eeprom_cleanup(tp);
RTL_W8(tp, Cfg9346, 0);
return data;
}
//-------------------------------------------------------------------
//rtl8126_eeprom_write_sc():
// write one word to a specific address in the eeprom
//-------------------------------------------------------------------
void rtl8126_eeprom_write_sc(struct rtl8126_private *tp, u16 reg, u16 data)
{
u8 x;
int addr_sz = 6;
int w_dummy_addr = 4;
if(tp->eeprom_type == EEPROM_TYPE_NONE)
return;
if (tp->eeprom_type==EEPROM_TYPE_93C46) {
addr_sz = 6;
w_dummy_addr = 4;
} else if (tp->eeprom_type==EEPROM_TYPE_93C56) {
addr_sz = 8;
w_dummy_addr = 6;
}
x = Cfg9346_EEM1 | Cfg9346_EECS;
RTL_W8(tp, Cfg9346, x);
rtl8126_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5);
rtl8126_shift_out_bits(tp, reg, w_dummy_addr);
rtl8126_stand_by(tp);
rtl8126_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
rtl8126_shift_out_bits(tp, reg, addr_sz);
if (rtl8126_eeprom_cmd_done(tp) < 0)
return;
rtl8126_stand_by(tp);
rtl8126_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
rtl8126_shift_out_bits(tp, reg, addr_sz);
rtl8126_shift_out_bits(tp, data, 16);
if (rtl8126_eeprom_cmd_done(tp) < 0)
return;
rtl8126_stand_by(tp);
rtl8126_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
rtl8126_shift_out_bits(tp, reg, w_dummy_addr);
rtl8126_eeprom_cleanup(tp);
RTL_W8(tp, Cfg9346, 0);
}
void rtl8126_raise_clock(struct rtl8126_private *tp, u8 *x)
{
*x = *x | Cfg9346_EESK;
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
}
void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x)
{
*x = *x & ~Cfg9346_EESK;
RTL_W8(tp, Cfg9346, *x);
udelay(RTL_CLOCK_RATE);
}
void rtl8126_shift_out_bits(struct rtl8126_private *tp, int data, int count)
{
u8 x;
int mask;
mask = 0x01 << (count - 1);
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
do {
if (data & mask)
x |= Cfg9346_EEDI;
else
x &= ~Cfg9346_EEDI;
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
rtl8126_raise_clock(tp, &x);
rtl8126_lower_clock(tp, &x);
mask = mask >> 1;
} while(mask);
x &= ~Cfg9346_EEDI;
RTL_W8(tp, Cfg9346, x);
}
u16 rtl8126_shift_in_bits(struct rtl8126_private *tp)
{
u8 x;
u16 d, i;
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
d = 0;
for (i = 0; i < 16; i++) {
d = d << 1;
rtl8126_raise_clock(tp, &x);
x = RTL_R8(tp, Cfg9346);
x &= ~Cfg9346_EEDI;
if (x & Cfg9346_EEDO)
d |= 1;
rtl8126_lower_clock(tp, &x);
}
return d;
}
void rtl8126_stand_by(struct rtl8126_private *tp)
{
u8 x;
x = RTL_R8(tp, Cfg9346);
x &= ~(Cfg9346_EECS | Cfg9346_EESK);
RTL_W8(tp, Cfg9346, x);
udelay(RTL_CLOCK_RATE);
x |= Cfg9346_EECS;
RTL_W8(tp, Cfg9346, x);
}
void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp)
{
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
udelay(20);
RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
}

View File

@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_RTLEEPROM_H
#define _LINUX_RTLEEPROM_H
//EEPROM opcodes
#define RTL_EEPROM_READ_OPCODE 06
#define RTL_EEPROM_WRITE_OPCODE 05
#define RTL_EEPROM_ERASE_OPCODE 07
#define RTL_EEPROM_EWEN_OPCODE 19
#define RTL_EEPROM_EWDS_OPCODE 16
#define RTL_CLOCK_RATE 3
void rtl8126_eeprom_type(struct rtl8126_private *tp);
void rtl8126_eeprom_cleanup(struct rtl8126_private *tp);
u16 rtl8126_eeprom_read_sc(struct rtl8126_private *tp, u16 reg);
void rtl8126_eeprom_write_sc(struct rtl8126_private *tp, u16 reg, u16 data);
void rtl8126_shift_out_bits(struct rtl8126_private *tp, int data, int count);
u16 rtl8126_shift_in_bits(struct rtl8126_private *tp);
void rtl8126_raise_clock(struct rtl8126_private *tp, u8 *x);
void rtl8126_lower_clock(struct rtl8126_private *tp, u8 *x);
void rtl8126_stand_by(struct rtl8126_private *tp);
void rtl8126_set_eeprom_sel_low(struct rtl8126_private *tp);
#endif /* _LINUX_RTLEEPROM_H */

View File

@@ -0,0 +1,260 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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/module.h>
#include <linux/version.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/in.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include "r8126.h"
#include "rtl_eeprom.h"
#include "rtltool.h"
int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr)
{
struct rtltool_cmd my_cmd;
int ret;
if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd)))
return -EFAULT;
ret = 0;
switch (my_cmd.cmd) {
case RTLTOOL_READ_MAC:
if (my_cmd.len==1)
my_cmd.data = readb(tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2)
my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1));
else if (my_cmd.len==4)
my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3));
else {
ret = -EOPNOTSUPP;
break;
}
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_MAC:
if (my_cmd.len==1)
writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset);
else if (my_cmd.len==2)
writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1));
else if (my_cmd.len==4)
writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3));
else {
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_PHY:
my_cmd.data = rtl8126_mdio_prot_read(tp, my_cmd.offset);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_PHY:
rtl8126_mdio_prot_write(tp, my_cmd.offset, my_cmd.data);
break;
case RTLTOOL_READ_EPHY:
my_cmd.data = rtl8126_ephy_read(tp, my_cmd.offset);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_EPHY:
rtl8126_ephy_write(tp, my_cmd.offset, my_cmd.data);
break;
case RTLTOOL_READ_ERI:
my_cmd.data = 0;
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
my_cmd.data = rtl8126_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC);
} else {
ret = -EOPNOTSUPP;
break;
}
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_ERI:
if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) {
rtl8126_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC);
} else {
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_PCI:
my_cmd.data = 0;
if (my_cmd.len==1)
pci_read_config_byte(tp->pci_dev, my_cmd.offset,
(u8 *)&my_cmd.data);
else if (my_cmd.len==2)
pci_read_config_word(tp->pci_dev, my_cmd.offset,
(u16 *)&my_cmd.data);
else if (my_cmd.len==4)
pci_read_config_dword(tp->pci_dev, my_cmd.offset,
&my_cmd.data);
else {
ret = -EOPNOTSUPP;
break;
}
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_PCI:
if (my_cmd.len==1)
pci_write_config_byte(tp->pci_dev, my_cmd.offset,
my_cmd.data);
else if (my_cmd.len==2)
pci_write_config_word(tp->pci_dev, my_cmd.offset,
my_cmd.data);
else if (my_cmd.len==4)
pci_write_config_dword(tp->pci_dev, my_cmd.offset,
my_cmd.data);
else {
ret = -EOPNOTSUPP;
break;
}
break;
case RTLTOOL_READ_EEPROM:
my_cmd.data = rtl8126_eeprom_read_sc(tp, my_cmd.offset);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTLTOOL_WRITE_EEPROM:
rtl8126_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data);
break;
case RTL_READ_OOB_MAC:
rtl8126_oob_mutex_lock(tp);
my_cmd.data = rtl8126_ocp_read(tp, my_cmd.offset, 4);
rtl8126_oob_mutex_unlock(tp);
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;
rtl8126_oob_mutex_lock(tp);
rtl8126_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data);
rtl8126_oob_mutex_unlock(tp);
break;
case RTL_ENABLE_PCI_DIAG:
tp->rtk_enable_diag = 1;
dprintk("enable rtk diag\n");
break;
case RTL_DISABLE_PCI_DIAG:
tp->rtk_enable_diag = 0;
dprintk("disable rtk diag\n");
break;
case RTL_READ_MAC_OCP:
if (my_cmd.offset % 2)
return -EOPNOTSUPP;
my_cmd.data = rtl8126_mac_ocp_read(tp, my_cmd.offset);
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;
rtl8126_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data);
break;
case RTL_DIRECT_READ_PHY_OCP:
my_cmd.data = rtl8126_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset);
if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) {
ret = -EFAULT;
break;
}
break;
case RTL_DIRECT_WRITE_PHY_OCP:
rtl8126_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data);
break;
default:
ret = -EOPNOTSUPP;
break;
}
return ret;
}

View File

@@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
################################################################################
#
# r8126 is the Linux device driver released for Realtek 5 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_RTLTOOL_H
#define _LINUX_RTLTOOL_H
#define SIOCRTLTOOL SIOCDEVPRIVATE+1
enum rtl_cmd {
RTLTOOL_READ_MAC=0,
RTLTOOL_WRITE_MAC,
RTLTOOL_READ_PHY,
RTLTOOL_WRITE_PHY,
RTLTOOL_READ_EPHY,
RTLTOOL_WRITE_EPHY,
RTLTOOL_READ_ERI,
RTLTOOL_WRITE_ERI,
RTLTOOL_READ_PCI,
RTLTOOL_WRITE_PCI,
RTLTOOL_READ_EEPROM,
RTLTOOL_WRITE_EEPROM,
RTL_READ_OOB_MAC,
RTL_WRITE_OOB_MAC,
RTL_ENABLE_PCI_DIAG,
RTL_DISABLE_PCI_DIAG,
RTL_READ_MAC_OCP,
RTL_WRITE_MAC_OCP,
RTL_DIRECT_READ_PHY_OCP,
RTL_DIRECT_WRITE_PHY_OCP,
RTLTOOL_INVALID
};
struct rtltool_cmd {
__u32 cmd;
__u32 offset;
__u32 len;
__u32 data;
};
enum mode_access {
MODE_NONE=0,
MODE_READ,
MODE_WRITE
};
#ifdef __KERNEL__
int rtl8126_tool_ioctl(struct rtl8126_private *tp, struct ifreq *ifr);
#endif
#endif /* _LINUX_RTLTOOL_H */

View File

@@ -0,0 +1,205 @@
# 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.
################################################################################
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_9 := $(shell expr 6 \* 256 + 9)
# Use dummy R8168 driver for K69 and later
ifeq ($(shell test $(LINUX_VERSION) -ge $(LINUX_VERSION_6_9); echo $$?),0)
obj-m := r8168.o
r8168-objs := r8168_dummy.o
else
CONFIG_SOC_LAN = n
ENABLE_FIBER_SUPPORT = n
ENABLE_REALWOW_SUPPORT = n
ENABLE_DASH_SUPPORT = n
ENABLE_DASH_PRINTER_SUPPORT = n
CONFIG_DOWN_SPEED_100 = n
CONFIG_ASPM = y
ENABLE_S5WOL = y
ENABLE_S5_KEEP_CURR_MAC = n
ENABLE_EEE = y
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
ifneq ($(KERNELRELEASE),)
obj-m := r8168.o
r8168-objs := r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o
ifeq ($(CONFIG_SOC_LAN), y)
EXTRA_CFLAGS += -DCONFIG_SOC_LAN
endif
ifeq ($(ENABLE_FIBER_SUPPORT), y)
r8168-objs += r8168_fiber.o
EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT
endif
ifeq ($(ENABLE_REALWOW_SUPPORT), y)
r8168-objs += r8168_realwow.o
EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT
endif
ifeq ($(ENABLE_DASH_SUPPORT), y)
r8168-objs += r8168_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT
endif
ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y)
r8168-objs += r8168_dash.o
EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT
endif
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
endif
ifeq ($(CONFIG_ASPM), y)
EXTRA_CFLAGS += -DCONFIG_ASPM
endif
ifeq ($(ENABLE_S5WOL), y)
EXTRA_CFLAGS += -DENABLE_S5WOL
endif
ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y)
EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC
endif
ifeq ($(ENABLE_EEE), y)
EXTRA_CFLAGS += -DENABLE_EEE
endif
ifeq ($(ENABLE_S0_MAGIC_PACKET), y)
EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET
endif
ifeq ($(CONFIG_DYNAMIC_ASPM), y)
EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM
endif
ifeq ($(ENABLE_USE_FIRMWARE_FILE), y)
r8168-objs += r8168_firmware.o
EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE
endif
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
else
BASEDIR := /lib/modules/$(shell uname -r)
KERNELDIR ?= $(BASEDIR)/build
PWD :=$(shell pwd)
DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net/ethernet -name realtek -type d)
ifeq ($(DRIVERDIR),)
DRIVERDIR := $(shell find $(BASEDIR)/kernel/drivers/net -name realtek -type d)
endif
ifeq ($(DRIVERDIR),)
DRIVERDIR := $(BASEDIR)/kernel/drivers/net
endif
RTKDIR := $(subst $(BASEDIR)/,,$(DRIVERDIR))
KERNEL_GCC_VERSION := $(shell cat /proc/version | sed -n 's/.*gcc version \([[:digit:]]\.[[:digit:]]\.[[:digit:]]\).*/\1/p')
CCVERSION = $(shell $(CC) -dumpversion)
KVER = $(shell uname -r)
KMAJ = $(shell echo $(KVER) | \
sed -e 's/^\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*.*/\1/')
KMIN = $(shell echo $(KVER) | \
sed -e 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*.*/\1/')
KREV = $(shell echo $(KVER) | \
sed -e 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/')
kver_ge = $(shell \
echo test | awk '{if($(KMAJ) < $(1)) {print 0} else { \
if($(KMAJ) > $(1)) {print 1} else { \
if($(KMIN) < $(2)) {print 0} else { \
if($(KMIN) > $(2)) {print 1} else { \
if($(KREV) < $(3)) {print 0} else { print 1 } \
}}}}}' \
)
.PHONY: all
all: print_vars clean modules install
print_vars:
@echo
@echo "CC: " $(CC)
@echo "CCVERSION: " $(CCVERSION)
@echo "KERNEL_GCC_VERSION: " $(KERNEL_GCC_VERSION)
@echo "KVER: " $(KVER)
@echo "KMAJ: " $(KMAJ)
@echo "KMIN: " $(KMIN)
@echo "KREV: " $(KREV)
@echo "BASEDIR: " $(BASEDIR)
@echo "DRIVERDIR: " $(DRIVERDIR)
@echo "PWD: " $(PWD)
@echo "RTKDIR: " $(RTKDIR)
@echo
.PHONY:modules
modules:
#ifeq ($(call kver_ge,5,0,0),1)
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#else
# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
#endif
.PHONY:clean
clean:
#ifeq ($(call kver_ge,5,0,0),1)
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
#else
# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) clean
#endif
.PHONY:install
install:
#ifeq ($(call kver_ge,5,0,0),1)
$(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install
#else
# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) INSTALL_MOD_DIR=$(RTKDIR) modules_install
#endif
endif
endif

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
@@ -247,6 +247,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

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/module.h>
/* Dummy implementation for module */
static int __init r8168_dummy_dummy_init(void)
{
return 0;
}
device_initcall(r8168_dummy_dummy_init);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_DESCRIPTION("Dummy R8168 dummy driver");
MODULE_LICENSE("GPL");

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

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,500 @@
// 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;
netif_info(tp, drv, tp->dev, "rss get rxnfc\n");
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;
netif_info(tp, drv, tp->dev, "rss set hash\n");
/*
* 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;
netif_info(tp, drv, tp->dev, "rss set rxnfc\n");
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);
netif_info(tp, drv, tp->dev, "rss get key size\n");
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);
netif_info(tp, drv, tp->dev, "rss get indir tbl size\n");
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);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
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;
netif_info(tp, drv, tp->dev, "rss set rxfh\n");
/* 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);
netif_info(tp, drv, tp->dev, "rss get rxfh\n");
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;
netif_info(tp, drv, tp->dev, "rss set rxfh\n");
/* 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)
udelay(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 */
/*
################################################################################
#
# r8125 is the Linux device driver released for Realtek 2.5Gigabit 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
@@ -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);

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)))
@@ -72,7 +71,6 @@ int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr)
break;
}
break;
case RTLTOOL_WRITE_MAC:
if (my_cmd.len==1)
writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset);
@@ -84,51 +82,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 +116,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 +146,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 +160,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

@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
ifeq ($(findstring ack_src,$(NV_BUILD_KERNEL_OPTIONS)),)
ifeq ($(VERSION).$(PATCHLEVEL),5.15)
ifneq ($(NV_OOT_REALTEK_RTL8822CE_SKIP_BUILD),y)
obj-m += rtl8822ce/
endif
endif
endif

View File

View File

@@ -1814,9 +1814,12 @@ void rtw_btcoex_connect_notify(PADAPTER padapter, u8 join_type)
pHalData = GET_HAL_DATA(padapter);
if (pHalData->EEPROMBluetoothCoexist == _TRUE)
if (pHalData->EEPROMBluetoothCoexist == _TRUE) {
_rtw_btcoex_connect_notify(padapter, join_type ? _FALSE : _TRUE);
else
if (join_type)
rtw_btcoex_SpecialPacketNotify(padapter, PACKET_EAPOL);
} else
#endif /* CONFIG_BT_COEXIST */
rtw_btcoex_wifionly_connect_notify(padapter);
}

View File

@@ -2825,6 +2825,10 @@ int proc_get_trx_info(struct seq_file *m, void *v)
struct recv_priv *precvpriv = &padapter->recvpriv;
struct hw_xmit *phwxmit;
u16 vo_params[4], vi_params[4], be_params[4], bk_params[4];
#ifdef CONFIG_LAYER2_ROAMING
_list *plist, *phead;
_irqL irqL;
#endif
padapter->hal_func.read_wmmedca_reg(padapter, vo_params, vi_params, be_params, bk_params);
@@ -2854,6 +2858,19 @@ int proc_get_trx_info(struct seq_file *m, void *v)
rtw_hal_get_hwreg(padapter, HW_VAR_DUMP_MAC_TXFIFO, (u8 *)m);
#ifdef CONFIG_LAYER2_ROAMING
i = 0;
_enter_critical_bh(&pxmitpriv->rpkt_queue.lock, &irqL);
phead = get_list_head(&pxmitpriv->rpkt_queue);
plist = get_next(phead);
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
i++;
plist = get_next(plist);
}
_exit_critical_bh(&pxmitpriv->rpkt_queue.lock, &irqL);
RTW_PRINT_SEL(m, "TX: roam_buf_pkt=%d:%d\n", padapter->mlmepriv.roam_buf_pkt, i);
#endif
#ifdef CONFIG_USB_HCI
RTW_PRINT_SEL(m, "rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
#ifdef CONFIG_USB_PROTECT_RX_CLONED_SKB

View File

@@ -175,12 +175,25 @@ u8 rtw_do_join(_adapter *padapter)
pmlmepriv->to_join = _FALSE;
#endif /* CONFIG_AP_MODE */
} else if (pmlmepriv->need_to_roam == _TRUE || rtw_to_roam(padapter) > 0) {
/* can't associate ; reset under-linking */
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
/* if all scanned candidates are fail, report to supplicant */
rtw_set_to_roam(padapter, 0);
rtw_indicate_disconnect(padapter, 0, TRUE);
pmlmepriv->to_join = _FALSE;
#ifdef CONFIG_LAYER2_ROAMING
flush_roam_buf_pkt(padapter, TRUE);
#endif
ret = _FAIL;
} else {
/* can't associate ; reset under-linking */
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
/* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
/* we try to issue sitesurvey firstly */
if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _FALSE
|| rtw_to_roam(padapter) > 0
) {

View File

@@ -786,9 +786,7 @@ void rtw_mbo_build_assoc_req_ies(
{
u32 len = 0;
#ifndef CONFIG_ECSA
rtw_mbo_build_supp_op_class_elem(padapter, pframe, pattrib);
#endif
len += rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_CELL_DATA_CAP_ID);
len += rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_NPREF_CH_RPT_ID);

Some files were not shown because too many files have changed in this diff Show More