[BCMSAI] Update BCMSAI debian to 4.3.0.10 with 6.5.21 SDK, and opennsl module to 6.5.21 (#6526)
BCMSAI 4.3.0.10, 6.5.21 SDK release with enhancements and fixes for vxlan, TD3 MMU, TD4-X9 EA support, etc.
This commit is contained in:
parent
c7d8faee18
commit
bc2a13136a
@ -1,6 +1,6 @@
|
||||
# Broadcom SAI modules
|
||||
|
||||
BRCM_OPENNSL_KERNEL_VERSION = 4.2.1.3-1
|
||||
BRCM_OPENNSL_KERNEL_VERSION = 4.3.0.10-2
|
||||
|
||||
BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb
|
||||
$(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules
|
||||
|
@ -1,8 +1,8 @@
|
||||
BRCM_SAI = libsaibcm_4.2.1.5-10_amd64.deb
|
||||
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.2/master/buster/libsaibcm_4.2.1.5-10_amd64.deb?sv=2019-12-12&st=2021-01-12T07%3A30%3A31Z&se=2035-01-13T07%3A30%3A00Z&sr=b&sp=r&sig=yCGwk%2FW%2Fg%2FaFxhr0oNSTZ%2BVy5B6kX1WDEsbbyz9J088%3D"
|
||||
BRCM_SAI_DEV = libsaibcm-dev_4.2.1.5-10_amd64.deb
|
||||
BRCM_SAI = libsaibcm_4.3.0.10-2_amd64.deb
|
||||
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm_4.3.0.10-2_amd64.deb?sv=2015-04-05&sr=b&sig=1L2kJwYBuXDc9ObuVBBUS%2F%2FBVIfAA651ig5k6O1ZztE%3D&se=2022-06-10T21%3A25%3A43Z&sp=r"
|
||||
BRCM_SAI_DEV = libsaibcm-dev_4.3.0.10-2_amd64.deb
|
||||
$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV)))
|
||||
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.2/master/buster/libsaibcm-dev_4.2.1.5-10_amd64.deb?sv=2019-12-12&st=2021-01-12T07%3A32%3A43Z&se=2035-01-13T07%3A32%3A00Z&sr=b&sp=r&sig=wuCNc6pa12JQCBi%2BM9rLWvVI92ldan9hKNF%2BfVfUWN8%3D"
|
||||
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm-dev_4.3.0.10-2_amd64.deb?sv=2015-04-05&sr=b&sig=2Vm6o8HtbjI%2BfVoHJUiO5b75USqGra9CLSFXViQm8yM%3D&se=2022-06-10T21%3A26%3A35Z&sp=r"
|
||||
|
||||
SONIC_ONLINE_DEBS += $(BRCM_SAI)
|
||||
$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)
|
||||
|
@ -1,3 +1,10 @@
|
||||
opennsl (4.3.0.10-2) unstable; urgency=medium
|
||||
|
||||
* Update to Broadcom SAI 4.3.0.10
|
||||
* Added SDKLT modules 4.3.0.10-2
|
||||
|
||||
-- Mahesh Maddikayala <samaddik@microsoft.com> Thu, 21 Jan 2021 18:36:38 +0000
|
||||
|
||||
opennsl (4.2.1.3-1) unstable; urgency=medium
|
||||
|
||||
* Update to Broadcom SAI 4.2.1.3
|
||||
|
@ -18,7 +18,9 @@ function create_devices()
|
||||
rm -f /dev/linux-bcm-knet
|
||||
rm -f /dev/linux-bcm-bde
|
||||
rm -f /dev/linux-kernel-bde
|
||||
rm -f /dev/linux_ngbde
|
||||
|
||||
mknod /dev/linux_ngbde c 120 0
|
||||
mknod /dev/linux-knet-cb c 121 0
|
||||
mknod /dev/linux-bcm-knet c 122 0
|
||||
mknod /dev/linux-bcm-bde c 126 0
|
||||
@ -57,8 +59,9 @@ function load_kernel_modules()
|
||||
# There is a different psample.ko module getting created at net/psample/psample.ko
|
||||
insmod /lib/modules/$(uname -r)/extra/psample.ko
|
||||
|
||||
modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020
|
||||
modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020 default_mtu=9100
|
||||
modprobe linux-knet-cb
|
||||
modprobe linux_ngbde
|
||||
}
|
||||
|
||||
function remove_kernel_modules()
|
||||
@ -68,6 +71,7 @@ function remove_kernel_modules()
|
||||
rmmod linux-bcm-knet
|
||||
rmmod linux-user-bde
|
||||
rmmod linux-kernel-bde
|
||||
rmmod linux_ngbde
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
|
@ -5,3 +5,4 @@ systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.19.0-9-
|
||||
systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.19.0-9-2-amd64/extra
|
||||
systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-ptp-clock.ko lib/modules/4.19.0-9-2-amd64/extra
|
||||
systemd/opennsl-modules.service lib/systemd/system
|
||||
sdklt/linux/bde/linux_ngbde.ko lib/modules/4.19.0-9-2-amd64/extra
|
||||
|
@ -67,6 +67,9 @@ kdist_clean: clean
|
||||
KERNDIR=/usr/src/linux-headers-$(KERNVERSION)-common \
|
||||
KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \
|
||||
$(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
|
||||
SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \
|
||||
KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \
|
||||
$(MAKE) -C sdklt/ clean
|
||||
# rm -f driver/*.o driver/*.ko
|
||||
#
|
||||
### end KERNEL SETUP
|
||||
@ -100,6 +103,10 @@ build-arch-stamp:
|
||||
KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \
|
||||
$(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6
|
||||
|
||||
SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \
|
||||
KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \
|
||||
$(MAKE) -C sdklt/ kmod
|
||||
|
||||
touch $@
|
||||
|
||||
#k = $(shell echo $(KVERS) | grep -q ^2.6 && echo k)
|
||||
@ -128,6 +135,10 @@ clean:
|
||||
KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \
|
||||
$(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
|
||||
|
||||
SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \
|
||||
KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \
|
||||
$(MAKE) -C sdklt/ clean
|
||||
|
||||
dh_clean
|
||||
|
||||
install: DH_OPTIONS=
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: ibde.h,v 1.27 Broadcom SDK $
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: kcom.h,v 1.9 Broadcom SDK $
|
||||
@ -341,6 +352,8 @@ typedef struct kcom_msg_version_s {
|
||||
#define KSYNC_M_HW_DEINIT 1
|
||||
#define KSYNC_M_VERSION 2
|
||||
#define KSYNC_M_HW_TS_DISABLE 3
|
||||
#define KSYNC_M_MTP_TS_UPDATE_ENABLE 4
|
||||
#define KSYNC_M_MTP_TS_UPDATE_DISABLE 5
|
||||
|
||||
typedef struct kcom_clock_info_s {
|
||||
uint8 cmd;
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: sync.h,v 1.1 Broadcom SDK $
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: thread.h,v 1.1 Broadcom SDK $
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: types.h,v 1.3 Broadcom SDK $
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* $Id: sdk_config.h,v 1.5 Broadcom SDK $
|
||||
|
@ -1,5 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017 Broadcom
|
||||
* Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
* Permission is granted to use, copy, modify and/or distribute this
|
||||
* software under either one of the licenses below.
|
||||
*
|
||||
* License Option 1: GPL
|
||||
*
|
||||
* 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
|
||||
@ -12,6 +17,12 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 (GPLv2) along with this source code.
|
||||
*
|
||||
*
|
||||
* License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
*
|
||||
* This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
* https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
*/
|
||||
/*
|
||||
* Copyright: (c) 2020 Broadcom.
|
||||
@ -1274,6 +1285,18 @@
|
||||
#define BCM56278_A0_REV_ID 1
|
||||
#define BCM56278_A1_REV_ID 2
|
||||
|
||||
#define BCM56279_DEVICE_ID 0xb279
|
||||
#define BCM56279_A1_REV_ID 2
|
||||
|
||||
#define BCM56575_DEVICE_ID 0xb575
|
||||
#define BCM56575_A1_REV_ID 2
|
||||
|
||||
#define BCM56175_DEVICE_ID 0xb175
|
||||
#define BCM56175_A1_REV_ID 2
|
||||
|
||||
#define BCM56176_DEVICE_ID 0xb176
|
||||
#define BCM56176_A1_REV_ID 2
|
||||
|
||||
#define BCM53440_DEVICE_ID 0x8440
|
||||
#define BCM53440_A0_REV_ID 1
|
||||
#define BCM53440_B0_REV_ID 0x11
|
||||
@ -1404,6 +1427,8 @@
|
||||
#define BCM56070_A0_REV_ID 1
|
||||
#define BCM56071_DEVICE_ID 0xb071
|
||||
#define BCM56071_A0_REV_ID 1
|
||||
#define BCM56072_DEVICE_ID 0xb072
|
||||
#define BCM56072_A0_REV_ID 1
|
||||
|
||||
|
||||
#define BCM56965_DEVICE_ID 0xb965
|
||||
@ -1499,6 +1524,8 @@
|
||||
#define BCM56471_A0_REV_ID 1
|
||||
#define BCM56472_DEVICE_ID 0xb472
|
||||
#define BCM56472_A0_REV_ID 1
|
||||
#define BCM56475_DEVICE_ID 0xb475
|
||||
#define BCM56475_A0_REV_ID 1
|
||||
|
||||
|
||||
#define BCM53540_DEVICE_ID 0x8540
|
||||
@ -1537,19 +1564,6 @@
|
||||
#define BCM88650_A0_REV_ID ARAD_A0_REV_ID
|
||||
#define BCM88650_B0_REV_ID ARAD_B0_REV_ID
|
||||
#define BCM88650_B1_REV_ID ARAD_B1_REV_ID
|
||||
#define BCM88750_DEVICE_ID 0x8750
|
||||
#define BCM88750_A0_REV_ID 0x0000
|
||||
#define BCM88750_B0_REV_ID 0x0011
|
||||
#define BCM88753_DEVICE_ID 0x8753
|
||||
#define BCM88753_A0_REV_ID 0x0000
|
||||
#define BCM88753_B0_REV_ID 0x0011
|
||||
#define BCM88754_DEVICE_ID 0x8754
|
||||
#define BCM88754_A0_REV_ID 0x0000
|
||||
#define BCM88754_ORIGINAL_VENDOR_ID 0x16FC
|
||||
#define BCM88754_ORIGINAL_DEVICE_ID 0x020F
|
||||
#define BCM88754_A0_ORIGINAL_REV_ID 0x0001
|
||||
#define BCM88755_DEVICE_ID 0x8755
|
||||
#define BCM88755_B0_REV_ID 0x0011
|
||||
#define BCM88770_DEVICE_ID 0x8770
|
||||
#define BCM88770_A1_REV_ID 0x0002
|
||||
#define BCM88773_DEVICE_ID 0x8773
|
||||
@ -1767,22 +1781,57 @@
|
||||
#define BCM88820_DEVICE_ID J2C_2ND_DEVICE_ID
|
||||
#define BCM88800_A0_REV_ID J2C_A0_REV_ID
|
||||
#define BCM88800_A1_REV_ID J2C_A1_REV_ID
|
||||
#define BCM88821_DEVICE_ID 0x8821
|
||||
#define BCM88826_DEVICE_ID 0x8826
|
||||
#define BCM88801_DEVICE_ID 0x8801
|
||||
#define BCM88802_DEVICE_ID 0x8802
|
||||
#define BCM88803_DEVICE_ID 0x8803
|
||||
#define BCM88804_DEVICE_ID 0x8804
|
||||
#define BCM88805_DEVICE_ID 0x8805
|
||||
#define BCM88806_DEVICE_ID 0x8806
|
||||
#define BCM88807_DEVICE_ID 0x8807
|
||||
#define BCM88808_DEVICE_ID 0x8808
|
||||
#define BCM88809_DEVICE_ID 0x8809
|
||||
#define BCM8880A_DEVICE_ID 0x880A
|
||||
#define BCM8880B_DEVICE_ID 0x880B
|
||||
#define BCM8880C_DEVICE_ID 0x880C
|
||||
#define BCM8880D_DEVICE_ID 0x880D
|
||||
#define BCM8880E_DEVICE_ID 0x880E
|
||||
#define BCM8880F_DEVICE_ID 0x880F
|
||||
#define BCM88821_DEVICE_ID 0x8821
|
||||
#define BCM88822_DEVICE_ID 0x8822
|
||||
#define BCM88823_DEVICE_ID 0x8823
|
||||
#define BCM88824_DEVICE_ID 0x8824
|
||||
#define BCM88825_DEVICE_ID 0x8825
|
||||
#define BCM88826_DEVICE_ID 0x8826
|
||||
#define BCM88827_DEVICE_ID 0x8827
|
||||
#define BCM88828_DEVICE_ID 0x8828
|
||||
#define BCM88829_DEVICE_ID 0x8829
|
||||
#define BCM8882A_DEVICE_ID 0x882A
|
||||
#define BCM8882B_DEVICE_ID 0x882B
|
||||
#define BCM8882C_DEVICE_ID 0x882C
|
||||
#define BCM8882D_DEVICE_ID 0x882D
|
||||
#define BCM8882E_DEVICE_ID 0x882E
|
||||
#define BCM8882F_DEVICE_ID 0x882F
|
||||
|
||||
#define J2P_DEVICE_ID 0x8850
|
||||
#define J2P_A0_REV_ID DNXC_A0_REV_ID
|
||||
#define BCM88850_DEVICE_ID J2P_DEVICE_ID
|
||||
#define BCM88850_A0_REV_ID J2P_A0_REV_ID
|
||||
#define BCM88851_DEVICE_ID 0x8851
|
||||
#define BCM88852_DEVICE_ID 0x8852
|
||||
#define BCM88853_DEVICE_ID 0x8853
|
||||
#define BCM88854_DEVICE_ID 0x8854
|
||||
#define BCM88855_DEVICE_ID 0x8855
|
||||
#define BCM88856_DEVICE_ID 0x8856
|
||||
#define BCM88857_DEVICE_ID 0x8857
|
||||
#define BCM88858_DEVICE_ID 0x8858
|
||||
#define BCM88859_DEVICE_ID 0x8859
|
||||
#define BCM8885A_DEVICE_ID 0x885A
|
||||
#define BCM8885B_DEVICE_ID 0x885B
|
||||
#define BCM8885C_DEVICE_ID 0x885C
|
||||
#define BCM8885D_DEVICE_ID 0x885D
|
||||
#define BCM8885E_DEVICE_ID 0x885E
|
||||
#define BCM8885F_DEVICE_ID 0x885F
|
||||
|
||||
|
||||
#define Q2A_DEVICE_ID 0x8480
|
||||
#define Q2A_A0_REV_ID DNXC_A0_REV_ID
|
||||
@ -1808,6 +1857,24 @@
|
||||
#define BCM8848E_DEVICE_ID 0x848E
|
||||
#define BCM8848F_DEVICE_ID 0x848F
|
||||
|
||||
#define Q2U_DEVICE_ID 0x8280
|
||||
#define BCM88280_DEVICE_ID Q2U_DEVICE_ID
|
||||
#define BCM88281_DEVICE_ID 0x8281
|
||||
#define BCM88282_DEVICE_ID 0x8282
|
||||
#define BCM88283_DEVICE_ID 0x8283
|
||||
#define BCM88284_DEVICE_ID 0x8284
|
||||
#define BCM88285_DEVICE_ID 0x8285
|
||||
#define BCM88286_DEVICE_ID 0x8286
|
||||
#define BCM88287_DEVICE_ID 0x8287
|
||||
#define BCM88288_DEVICE_ID 0x8288
|
||||
#define BCM88289_DEVICE_ID 0x8289
|
||||
#define BCM8828A_DEVICE_ID 0x828A
|
||||
#define BCM8828B_DEVICE_ID 0x828B
|
||||
#define BCM8828C_DEVICE_ID 0x828C
|
||||
#define BCM8828D_DEVICE_ID 0x828D
|
||||
#define BCM8828E_DEVICE_ID 0x828E
|
||||
#define BCM8828F_DEVICE_ID 0x828F
|
||||
|
||||
#define QAX_DEVICE_ID 0x8470
|
||||
#define QAX_A0_REV_ID 0x0001
|
||||
#define QAX_B0_REV_ID 0x0011
|
||||
@ -1833,9 +1900,11 @@
|
||||
#define BCM88270_DEVICE_ID QUX_DEVICE_ID
|
||||
#define BCM88270_A0_REV_ID QUX_A0_REV_ID
|
||||
#define BCM88270_A1_REV_ID QUX_A1_REV_ID
|
||||
#define BCM88271_DEVICE_ID 0x8271
|
||||
#define BCM88272_DEVICE_ID 0x8272
|
||||
#define BCM88273_DEVICE_ID 0x8273
|
||||
#define BCM88274_DEVICE_ID 0x8274
|
||||
#define BCM88276_DEVICE_ID 0x8276
|
||||
#define BCM88278_DEVICE_ID 0x8278
|
||||
#define BCM88279_DEVICE_ID 0x8279
|
||||
|
||||
@ -1844,16 +1913,6 @@
|
||||
#define BCM8206_DEVICE_ID FLAIR_DEVICE_ID
|
||||
#define BCM8206_A0_REV_ID FLAIR_A0_REV_ID
|
||||
|
||||
#define ARDON_DEVICE_ID 0x8202
|
||||
#define ARDON_A0_REV_ID 0x0000
|
||||
#define BCM88202_DEVICE_ID ARDON_DEVICE_ID
|
||||
#define BCM88202_A0_REV_ID ARDON_A0_REV_ID
|
||||
#define ARDON_A1_REV_ID 0x0001
|
||||
#define BCM88202_A1_REV_ID ARDON_A1_REV_ID
|
||||
#define ARDON_A2_REV_ID 0x0002
|
||||
#define BCM88202_A2_REV_ID ARDON_A2_REV_ID
|
||||
#define BCM2801PM_DEVICE_ID 0x2801
|
||||
#define BCM2801PM_A0_REV_ID 0x0000
|
||||
#define BCM88360_DEVICE_ID 0x8360
|
||||
#define BCM88360_A0_REV_ID ARADPLUS_A0_REV_ID
|
||||
#define BCM88361_DEVICE_ID 0x8361
|
||||
@ -1901,16 +1960,6 @@
|
||||
#define BCM88952_A0_REV_ID 0x0001
|
||||
#define BCM88952_A1_REV_ID 0x0002
|
||||
|
||||
#define BCM88752_DEVICE_ID 0x8752
|
||||
#define BCM88752_A0_REV_ID 0x0000
|
||||
#define BCM88752_B0_REV_ID 0x0011
|
||||
|
||||
|
||||
#define BCM83207_DEVICE_ID 0x3207
|
||||
#define BCM83208_DEVICE_ID 0x3208
|
||||
#define BCM83207_A0_REV_ID 0x0001
|
||||
#define BCM83208_A0_REV_ID 1
|
||||
|
||||
#define PCP_PCI_VENDOR_ID 0x1172
|
||||
#define PCP_PCI_DEVICE_ID 0x4
|
||||
|
||||
@ -1930,7 +1979,33 @@
|
||||
#define BCM56883_DEVICE_ID 0xb883
|
||||
#define BCM56883_A0_REV_ID 0x0001
|
||||
#define BCM56883_B0_REV_ID 0x0011
|
||||
#define BCM56889_DEVICE_ID 0xb889
|
||||
#define BCM56889_A0_REV_ID 0x0001
|
||||
#define BCM56889_B0_REV_ID 0x0011
|
||||
|
||||
#define BCM56780_DEVICE_ID 0xb780
|
||||
#define BCM56780_A0_REV_ID 0x0001
|
||||
#define BCM56782_DEVICE_ID 0xb782
|
||||
#define BCM56782_A0_REV_ID 0x0001
|
||||
#define BCM56784_DEVICE_ID 0xb784
|
||||
#define BCM56784_A0_REV_ID 0x0001
|
||||
#define BCM56786_DEVICE_ID 0xb786
|
||||
#define BCM56786_A0_REV_ID 0x0001
|
||||
#define BCM56788_DEVICE_ID 0xb788
|
||||
#define BCM56788_A0_REV_ID 0x0001
|
||||
#define BCM56789_DEVICE_ID 0xb789
|
||||
#define BCM56789_A0_REV_ID 0x0001
|
||||
|
||||
#define BCM56990_DEVICE_ID 0xb990
|
||||
#define BCM56990_A0_REV_ID 0x0001
|
||||
#define BCM56990_B0_REV_ID 0x0011
|
||||
#define BCM56992_DEVICE_ID 0xb992
|
||||
#define BCM56992_B0_REV_ID 0x0011
|
||||
|
||||
#define BCM56996_DEVICE_ID 0xb996
|
||||
#define BCM56996_A0_REV_ID 0x0001
|
||||
#define BCM56997_DEVICE_ID 0xb997
|
||||
#define BCM56997_A0_REV_ID 0x0001
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.config,v 1.3 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.depend,v 1.14 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.kernlib,v 1.7 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.lib,v 1.14 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
@ -62,7 +73,7 @@ endif
|
||||
ifeq ($(LINUX_MAKE_SHARED_LIB),1)
|
||||
$(CC) -shared -Wl,-soname,${lib}.${LIBSUFFIX}${EXTRA_LIB_LDFLAGS} -o ${targetlib} ${BOBJS} -lc
|
||||
else
|
||||
${Q}cd $(dir $(word 1,${BOBJS}));$(AR) ${ARFLAGS} $@ $(sort $(notdir ${BOBJS}))
|
||||
$(AR) ${ARFLAGS} $@ $(sort ${BOBJS})
|
||||
endif
|
||||
|
||||
endif # !Borland
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
#
|
||||
# $Id: Make.linux,v 1.18 Broadcom SDK $
|
||||
@ -85,7 +96,7 @@ endif
|
||||
build:
|
||||
$(MAKE) $(CMD)
|
||||
|
||||
DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user issu:
|
||||
DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user issu libopennsa:
|
||||
$(MAKE) $(CMD) $@
|
||||
|
||||
clean_d: clean
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.subdirs,v 1.8 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Make.tools,v 1.2 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $
|
||||
# $Copyright: (c) 2015 Broadcom Corp.
|
||||
@ -37,6 +48,8 @@
|
||||
# some basic path variables for tools and kernel source, etc #
|
||||
export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419
|
||||
TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr
|
||||
# Target machine for EDK-Host defconfig
|
||||
TARGET_MACHINE ?= x86_64
|
||||
KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux
|
||||
|
||||
# set up cross compile prefix, tools dir variables. #
|
||||
@ -125,12 +138,21 @@ OPENSRC_BUILD ?= fed21-x86_64
|
||||
# Hardware interface (see $SDKLT/bcma/sys/probe directory)
|
||||
SYSTEM_INTERFACE ?= ngbde
|
||||
|
||||
# Support BCMSIM in the same build
|
||||
ifeq (1,$(BCM_SIM_PATH_SUPPORT))
|
||||
EXTRA_SYSTEM_INTERFACES = plisim
|
||||
endif
|
||||
|
||||
# Turn on direct register access if running on real hardware.
|
||||
ifeq (ngbde,$(SYSTEM_INTERFACE))
|
||||
# Except if using multiple probe interfaces
|
||||
ifeq (,$(EXTRA_SYSTEM_INTERFACES))
|
||||
LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1
|
||||
endif
|
||||
endif
|
||||
|
||||
export SYSTEM_INTERFACE
|
||||
export EXTRA_SYSTEM_INTERFACES
|
||||
endif
|
||||
|
||||
ifneq ($(targetplat),user)
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-iproc Exp $
|
||||
# $Copyright: (c) 2007 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-iproc-3_6,v 1.1 Broadcom SDK $
|
||||
# $Copyright: (c) 2007 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-iproc Exp $
|
||||
# $Copyright: (c) 2007 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-iproc Exp $
|
||||
# $Copyright: (c) 2007 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-kernel,v 1.27 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-kernel-3_6,v 1.2 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-kmodule-3_6,v 1.2 Broadcom SDK $
|
||||
# $Copyright: (c) 2006 Broadcom Corp.
|
||||
@ -61,6 +72,13 @@ KERNBLDDIR ?= $(KERNDIR)
|
||||
# kernel symbols.
|
||||
|
||||
override EXTRA_CFLAGS = -I${SDK}/include -I${SDK}/systems/linux/kernel/modules/include -I${SDK}/systems/bde/linux/include
|
||||
#
|
||||
# If, for any reason, the definition of LD was erased, then
|
||||
# set it, again.
|
||||
#
|
||||
ifeq ($(LD),)
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
endif
|
||||
|
||||
# The precopiled object needs a dummy command file to avoid warnings
|
||||
# from the Kbuild scripts (modpost stage).
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-slk-3_14,v 1.2 Broadcom SDK $
|
||||
# $Copyright: (c) 2013 Broadcom Corp.
|
||||
@ -27,11 +38,15 @@ endif
|
||||
ifeq (BE,$(ENDIAN_MODE))
|
||||
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-be
|
||||
TARGET_ARCHITECTURE:=aarch64_be-linux-gnu
|
||||
# Target machine for EDK-Host defconfig
|
||||
TARGET_MACHINE ?= slk_be
|
||||
KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk-be/poky/brcm-released-source/git
|
||||
else
|
||||
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-le
|
||||
# Compiler for target architecture
|
||||
TARGET_ARCHITECTURE:= aarch64-linux-gnu
|
||||
# Target machine for EDK-Host defconfig
|
||||
TARGET_MACHINE ?= slk_le
|
||||
# Kernel directory
|
||||
KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk/poky/brcm-released-source/git
|
||||
endif
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-x86-common-2_6,v 1.13 Broadcom SDK $
|
||||
# $Copyright: (c) 2005 Broadcom Corp.
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-x86-generic-common-2_6,v 1.2 Broadcom SDK $
|
||||
# $Copyright: (c) 2008 Broadcom Corp.
|
||||
@ -48,5 +59,4 @@ AUTOCONF = $(KERNDIR)/include/linux/autoconf.h
|
||||
endif
|
||||
|
||||
# gcc system include path
|
||||
# SAI_FIXUP /* SDK-218654 */
|
||||
SYSINC = $(shell $(CC) -print-search-dirs | grep install | cut -c 10-)include
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-x86-smp_generic_64-2_6,v 1.5 Broadcom SDK $
|
||||
# $Copyright: (c) 2008 Broadcom Corp.
|
||||
@ -25,7 +36,7 @@ CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ
|
||||
include ${SDK}/make/Makefile.linux-x86-generic-common-2_6
|
||||
|
||||
ifeq (,$(KFLAGS))
|
||||
KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign
|
||||
KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -fno-pie -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign
|
||||
endif
|
||||
|
||||
ifeq ($(LINUX_MAKE_SHARED_LIB), 1)
|
||||
|
@ -1,5 +1,10 @@
|
||||
#
|
||||
# Copyright 2017 Broadcom
|
||||
# Copyright 2007-2020 Broadcom Inc. All rights reserved.
|
||||
#
|
||||
# Permission is granted to use, copy, modify and/or distribute this
|
||||
# software under either one of the licenses below.
|
||||
#
|
||||
# License Option 1: GPL
|
||||
#
|
||||
# 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
|
||||
@ -12,6 +17,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# version 2 (GPLv2) along with this source code.
|
||||
#
|
||||
#
|
||||
# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license
|
||||
#
|
||||
# This software is governed by the Broadcom Open Network Switch APIs license:
|
||||
# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa
|
||||
#
|
||||
# $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $
|
||||
# $Copyright: (c) 2015 Broadcom Corp.
|
||||
@ -37,6 +48,8 @@
|
||||
# some basic path variables for tools and kernel source, etc #
|
||||
export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419
|
||||
TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr
|
||||
# Target machine for EDK-Host defconfig
|
||||
TARGET_MACHINE ?= x86_64
|
||||
KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux
|
||||
|
||||
# set up cross compile prefix, tools dir variables. #
|
||||
@ -125,12 +138,21 @@ OPENSRC_BUILD ?= fed21-x86_64
|
||||
# Hardware interface (see $SDKLT/bcma/sys/probe directory)
|
||||
SYSTEM_INTERFACE ?= ngbde
|
||||
|
||||
# Support BCMSIM in the same build
|
||||
ifeq (1,$(BCM_SIM_PATH_SUPPORT))
|
||||
EXTRA_SYSTEM_INTERFACES = plisim
|
||||
endif
|
||||
|
||||
# Turn on direct register access if running on real hardware.
|
||||
ifeq (ngbde,$(SYSTEM_INTERFACE))
|
||||
# Except if using multiple probe interfaces
|
||||
ifeq (,$(EXTRA_SYSTEM_INTERFACES))
|
||||
LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1
|
||||
endif
|
||||
endif
|
||||
|
||||
export SYSTEM_INTERFACE
|
||||
export EXTRA_SYSTEM_INTERFACES
|
||||
endif
|
||||
|
||||
ifneq ($(targetplat),user)
|
||||
|
339
platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt
Normal file
339
platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
83
platform/broadcom/saibcm-modules/sdklt/Makefile
Normal file
83
platform/broadcom/saibcm-modules/sdklt/Makefile
Normal file
@ -0,0 +1,83 @@
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
help:
|
||||
@echo ''
|
||||
@echo 'Build Linux GPL kernel modules for SDKLT.'
|
||||
@echo ''
|
||||
@echo 'Available make targets:'
|
||||
@echo 'kmod - Build kernel modules'
|
||||
@echo 'clean - Remove object files'
|
||||
@echo ''
|
||||
@echo 'Supported make variables:'
|
||||
@echo 'KDIR - Linux kernel source directory (mandatory)'
|
||||
@echo 'CROSS_COPILE - Cross-compiler prefix (optional)'
|
||||
@echo ''
|
||||
@echo 'Examples:'
|
||||
@echo 'make -s KDIR=$$KERNEL/linux kmod'
|
||||
@echo 'make -s clean'
|
||||
@echo ''
|
||||
|
||||
ifndef KDIR
|
||||
nokdir:
|
||||
@echo 'Error: The $$KDIR environment variable is not set.'
|
||||
@echo '$$KDIR must point to a configured Linux kernel source tree.'
|
||||
exit 1
|
||||
endif
|
||||
|
||||
export KDIR
|
||||
export CROSS_COMPILE
|
||||
|
||||
override SDK := $(CURDIR)
|
||||
|
||||
ifeq ($(BUILD_PSAMPLE),1)
|
||||
PSAMPLE=psample
|
||||
PSAMPLE_SYMVERS=$(SDK)/linux/psample/Module.symvers
|
||||
endif
|
||||
|
||||
kmod: bde knet knetcb $(PSAMPLE)
|
||||
|
||||
bde:
|
||||
$(MAKE) -C $(SDK)/linux/bde SDK=$(SDK) \
|
||||
$(TARGET)
|
||||
ln -sf $(SDK)/linux/bde/*.ko
|
||||
|
||||
knet: bde
|
||||
$(MAKE) -C $(SDK)/linux/knet SDK=$(SDK) \
|
||||
KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/bde/Module.symvers \
|
||||
$(TARGET)
|
||||
ln -sf $(SDK)/linux/knet/*.ko
|
||||
|
||||
knetcb: knet $(PSAMPLE)
|
||||
$(MAKE) -C $(SDK)/linux/knetcb SDK=$(SDK) \
|
||||
KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/knet/Module.symvers \
|
||||
KBUILD_EXTRA_SYMBOLS+=$(PSAMPLE_SYMVERS) \
|
||||
$(TARGET)
|
||||
ln -sf $(SDK)/linux/knetcb/*.ko
|
||||
|
||||
ifeq ($(BUILD_PSAMPLE),1)
|
||||
$(PSAMPLE):
|
||||
$(MAKE) -C $(SDK)/linux/psample SDK=$(SDK) \
|
||||
$(TARGET)
|
||||
ln -sf $(SDK)/linux/psample/*.ko
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(MAKE) kmod TARGET=clean
|
||||
rm -f *.ko
|
||||
|
||||
.PHONY: help kmod bde knet knetcb $(PSAMPLE) clean
|
@ -0,0 +1,38 @@
|
||||
/*! \file bcm56780_a0_pdma_attach.c
|
||||
*
|
||||
* Initialize PDMA driver resources.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
int
|
||||
bcm56780_a0_cnet_pdma_attach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_attach(dev);
|
||||
}
|
||||
|
||||
int
|
||||
bcm56780_a0_cnet_pdma_detach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_detach(dev);
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*! \file bcm56880_a0_pdma_attach.c
|
||||
*
|
||||
* Initialize PDMA driver resources.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
int
|
||||
bcm56880_a0_cnet_pdma_attach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_attach(dev);
|
||||
}
|
||||
|
||||
int
|
||||
bcm56880_a0_cnet_pdma_detach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_detach(dev);
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*! \file bcm56990_a0_pdma_attach.c
|
||||
*
|
||||
* Initialize PDMA driver resources.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
int
|
||||
bcm56990_a0_cnet_pdma_attach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_attach(dev);
|
||||
}
|
||||
|
||||
int
|
||||
bcm56990_a0_cnet_pdma_detach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_detach(dev);
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*! \file bcm56990_b0_pdma_attach.c
|
||||
*
|
||||
* Initialize PDMA driver resources.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
int
|
||||
bcm56990_b0_cnet_pdma_attach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_attach(dev);
|
||||
}
|
||||
|
||||
int
|
||||
bcm56990_b0_cnet_pdma_detach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_detach(dev);
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*! \file bcm56996_a0_pdma_attach.c
|
||||
*
|
||||
* Initialize PDMA driver resources.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
int
|
||||
bcm56996_a0_cnet_pdma_attach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_attach(dev);
|
||||
}
|
||||
|
||||
int
|
||||
bcm56996_a0_cnet_pdma_detach(struct pdma_dev *dev)
|
||||
{
|
||||
return bcmcnet_cmicx_pdma_driver_detach(dev);
|
||||
}
|
||||
|
@ -0,0 +1,530 @@
|
||||
/*! \file bcmcnet_cmicd_pdma_hw.c
|
||||
*
|
||||
* Utility routines for handling BCMCNET hardware (CMICd).
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_rxtx.h>
|
||||
#include <bcmcnet/bcmcnet_cmicd.h>
|
||||
|
||||
/*!
|
||||
* Read 32-bit register
|
||||
*/
|
||||
static inline void
|
||||
cmicd_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data)
|
||||
{
|
||||
if (hw->dev->dev_read32) {
|
||||
hw->dev->dev_read32(hw->dev, addr, data);
|
||||
} else {
|
||||
DEV_READ32(&hw->dev->ctrl, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Write 32-bit register
|
||||
*/
|
||||
static inline void
|
||||
cmicd_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data)
|
||||
{
|
||||
if (hw->dev->dev_write32) {
|
||||
hw->dev->dev_write32(hw->dev, addr, data);
|
||||
} else {
|
||||
DEV_WRITE32(&hw->dev->ctrl, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a channel
|
||||
*/
|
||||
static inline void
|
||||
cmicd_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask)
|
||||
{
|
||||
uint32_t reg = CMICD_IRQ_STAT(cmc);
|
||||
|
||||
hw->dev->intr_unmask(hw->dev, cmc, chan, reg, mask);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a channel
|
||||
*/
|
||||
static inline void
|
||||
cmicd_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask)
|
||||
{
|
||||
uint32_t reg = CMICD_IRQ_STAT(cmc);
|
||||
|
||||
hw->dev->intr_mask(hw->dev, cmc, chan, reg, mask);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initialize HW
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_hw_init(struct pdma_hw *hw)
|
||||
{
|
||||
dev_mode_t mode = DEV_MODE_MAX;
|
||||
uint32_t val;
|
||||
|
||||
/* Temporarily upgrade work mode to get HW information in VNET mode. */
|
||||
if (hw->dev->mode == DEV_MODE_VNET) {
|
||||
mode = DEV_MODE_VNET;
|
||||
hw->dev->mode = DEV_MODE_UNET;
|
||||
}
|
||||
|
||||
/* Release credits to EP. Only do this once when HW is initialized. */
|
||||
hw->hdls.reg_rd32(hw, CMICD_EPINTF_RELEASE_CREDITS, &val);
|
||||
if (!val) {
|
||||
hw->hdls.reg_wr32(hw, CMICD_EPINTF_RELEASE_CREDITS, 1);
|
||||
}
|
||||
|
||||
hw->info.name = CMICD_DEV_NAME;
|
||||
hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val);
|
||||
hw->info.ver_no = val;
|
||||
hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val);
|
||||
hw->info.dev_id = val & 0xffff;
|
||||
hw->info.rev_id = val >> 16;
|
||||
hw->info.num_cmcs = CMICD_PDMA_CMC_MAX;
|
||||
hw->info.cmc_chans = CMICD_PDMA_CMC_CHAN;
|
||||
hw->info.num_chans = CMICD_PDMA_CMC_MAX * CMICD_PDMA_CMC_CHAN;
|
||||
hw->info.rx_dcb_size = CMICD_PDMA_DCB_SIZE;
|
||||
hw->info.tx_dcb_size = CMICD_PDMA_DCB_SIZE;
|
||||
hw->info.rx_ph_size = 0;
|
||||
hw->info.tx_ph_size = 0;
|
||||
|
||||
/* Restore work mode to VNET. */
|
||||
if (mode == DEV_MODE_VNET) {
|
||||
hw->dev->mode = DEV_MODE_VNET;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Configure HW
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_hw_config(struct pdma_hw *hw)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &hw->dev->ctrl;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
uint32_t val, que_ctrl;
|
||||
int grp, que;
|
||||
uint32_t qi;
|
||||
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi];
|
||||
grp = rxq->group_id;
|
||||
que = rxq->chan_id % CMICD_PDMA_CMC_CHAN;
|
||||
que_ctrl = ctrl->grp[grp].que_ctrl[que];
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que));
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que));
|
||||
val = 0;
|
||||
if (que_ctrl & PDMA_PKT_BYTE_SWAP) {
|
||||
val |= CMICD_PDMA_PKT_BIG_ENDIAN;
|
||||
}
|
||||
if (que_ctrl & PDMA_OTH_BYTE_SWAP) {
|
||||
val |= CMICD_PDMA_DESC_BIG_ENDIAN;
|
||||
}
|
||||
if (!(hw->dev->flags & PDMA_CHAIN_MODE)) {
|
||||
val |= CMICD_PDMA_CONTINUOUS;
|
||||
}
|
||||
val |= CMICD_PDMA_CNTLD_INTR;
|
||||
val &= ~CMICD_PDMA_DIR;
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val);
|
||||
}
|
||||
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi];
|
||||
grp = txq->group_id;
|
||||
que = txq->chan_id % CMICD_PDMA_CMC_CHAN;
|
||||
que_ctrl = ctrl->grp[grp].que_ctrl[que];
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que));
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que));
|
||||
val = 0;
|
||||
if (que_ctrl & PDMA_PKT_BYTE_SWAP) {
|
||||
val |= CMICD_PDMA_PKT_BIG_ENDIAN;
|
||||
}
|
||||
if (que_ctrl & PDMA_OTH_BYTE_SWAP) {
|
||||
val |= CMICD_PDMA_DESC_BIG_ENDIAN;
|
||||
}
|
||||
if (!(hw->dev->flags & PDMA_CHAIN_MODE)) {
|
||||
val |= CMICD_PDMA_CONTINUOUS;
|
||||
}
|
||||
val |= CMICD_PDMA_CNTLD_INTR | CMICD_PDMA_DIR;
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reset HW
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_hw_reset(struct pdma_hw *hw)
|
||||
{
|
||||
int gi, qi;
|
||||
|
||||
for (gi = 0; gi < hw->dev->num_groups; gi++) {
|
||||
if (!hw->dev->ctrl.grp[gi].attached) {
|
||||
continue;
|
||||
}
|
||||
for (qi = 0; qi < CMICD_PDMA_CMC_CHAN; qi++) {
|
||||
if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq ||
|
||||
1 << qi & hw->dev->ctrl.grp[gi].bm_txq) {
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(gi, qi), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_start(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val);
|
||||
val |= CMICD_PDMA_ENABLE;
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Stop a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_stop(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
int retry = CMICD_HW_RETRY_TIMES;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val);
|
||||
val |= CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT;
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
do {
|
||||
val = ~CMICD_PDMA_ACTIVE(que);
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val);
|
||||
} while ((val & CMICD_PDMA_ACTIVE(que)) && (--retry > 0));
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val);
|
||||
val &= ~(CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT);
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val);
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Setup a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC(grp, que), addr);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set halt point for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC_HALT(grp, que), addr);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Clear a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_clear(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get interrupt number for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que, start_num, mask_shift;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
mask_shift = 0;
|
||||
if (grp > 0) {
|
||||
mask_shift = CMICD_IRQ_MASK_SHIFT + grp * 32;
|
||||
}
|
||||
start_num = CMICD_IRQ_START_NUM + mask_shift;
|
||||
|
||||
return start_num + (que * CMICD_IRQ_NUM_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_enable(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
cmicd_pdma_intr_enable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que));
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_disable(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
cmicd_pdma_intr_disable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que));
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Query interrupt status for a channel
|
||||
*
|
||||
* In group mode (interrupt processing per CMC), need to query each channel's
|
||||
* interrupt status.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_query(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val);
|
||||
|
||||
return val & CMICD_IRQ_DESC_CNTLD(que);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt validity for a channel
|
||||
*
|
||||
* In group mode (interrupt processing per CMC), need to check each channel's
|
||||
* interrupt validity based on its interrupt mask.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_check(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICD_IRQ_DESC_CNTLD(que))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cmicd_pdma_chan_intr_query(hw, chan);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Coalesce interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
val = CMICD_PDMA_INTR_COAL_ENA |
|
||||
CMICD_PDMA_INTR_THRESH(count) |
|
||||
CMICD_PDMA_INTR_TIMER(timer);
|
||||
hw->hdls.reg_wr32(hw, CMICD_PDMA_INTR_COAL(grp, que), val);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dump registers for a channel
|
||||
*/
|
||||
static int
|
||||
cmicd_pdma_chan_reg_dump(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICD_PDMA_CMC_CHAN;
|
||||
que = chan % CMICD_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_CH%d_DMA_CTRL: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_DESC%d: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_CURR_DESC(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_CH%d_DMA_CURR_DESC: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC_HALT(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX0(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX1(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK0(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK0: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK1(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK1: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_INTR_COAL(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_RBUF_THRE(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_STAT: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_HI(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_STAT_HI: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_CLR(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_STAT_CLR: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_RX(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_RXPKT: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_TX(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_TXPKT: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_IRQ_STAT0: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_IRQ_PCI_MASK(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_PCIE_IRQ_MASK0: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val);
|
||||
CNET_PR("CMIC_DEV_REV_ID: 0x%08x\n", val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val);
|
||||
CNET_PR("CMIC_CMICM_REV_ID: 0x%08x\n", val);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initialize function pointers
|
||||
*/
|
||||
int
|
||||
bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw)
|
||||
{
|
||||
if (!hw) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
hw->hdls.reg_rd32 = cmicd_pdma_reg_read32;
|
||||
hw->hdls.reg_wr32 = cmicd_pdma_reg_write32;
|
||||
hw->hdls.hw_init = cmicd_pdma_hw_init;
|
||||
hw->hdls.hw_config = cmicd_pdma_hw_config;
|
||||
hw->hdls.hw_reset = cmicd_pdma_hw_reset;
|
||||
hw->hdls.chan_start = cmicd_pdma_chan_start;
|
||||
hw->hdls.chan_stop = cmicd_pdma_chan_stop;
|
||||
hw->hdls.chan_setup = cmicd_pdma_chan_setup;
|
||||
hw->hdls.chan_goto = cmicd_pdma_chan_goto;
|
||||
hw->hdls.chan_clear = cmicd_pdma_chan_clear;
|
||||
hw->hdls.chan_intr_num_get = cmicd_pdma_chan_intr_num_get;
|
||||
hw->hdls.chan_intr_enable = cmicd_pdma_chan_intr_enable;
|
||||
hw->hdls.chan_intr_disable = cmicd_pdma_chan_intr_disable;
|
||||
hw->hdls.chan_intr_query = cmicd_pdma_chan_intr_query;
|
||||
hw->hdls.chan_intr_check = cmicd_pdma_chan_intr_check;
|
||||
hw->hdls.chan_intr_coalesce = cmicd_pdma_chan_intr_coalesce;
|
||||
hw->hdls.chan_reg_dump = cmicd_pdma_chan_reg_dump;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,604 @@
|
||||
/*! \file bcmcnet_cmicx_pdma_hw.c
|
||||
*
|
||||
* Utility routines for handling BCMCNET hardware (CMICx).
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_rxtx.h>
|
||||
#include <bcmcnet/bcmcnet_cmicx.h>
|
||||
|
||||
/*!
|
||||
* Read 32-bit register
|
||||
*/
|
||||
static inline void
|
||||
cmicx_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data)
|
||||
{
|
||||
if (hw->dev->dev_read32) {
|
||||
hw->dev->dev_read32(hw->dev, addr, data);
|
||||
} else {
|
||||
DEV_READ32(&hw->dev->ctrl, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Write 32-bit register
|
||||
*/
|
||||
static inline void
|
||||
cmicx_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data)
|
||||
{
|
||||
if (hw->dev->dev_write32) {
|
||||
hw->dev->dev_write32(hw->dev, addr, data);
|
||||
} else {
|
||||
DEV_WRITE32(&hw->dev->ctrl, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a channel
|
||||
*/
|
||||
static inline void
|
||||
cmicx_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask)
|
||||
{
|
||||
uint32_t reg, irq_mask;
|
||||
|
||||
hw->dev->ctrl.grp[cmc].irq_mask |= mask;
|
||||
irq_mask = hw->dev->ctrl.grp[cmc].irq_mask;
|
||||
if (cmc == 0) {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT0;
|
||||
} else {
|
||||
if (chan < 4) {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT1;
|
||||
hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT;
|
||||
} else {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT2;
|
||||
hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
hw->dev->intr_unmask(hw->dev, cmc, chan, reg & 0xfff, 0);
|
||||
hw->dev->ctrl.grp[cmc].irq_mask = irq_mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a channel
|
||||
*/
|
||||
static inline void
|
||||
cmicx_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask)
|
||||
{
|
||||
uint32_t reg, irq_mask;
|
||||
|
||||
hw->dev->ctrl.grp[cmc].irq_mask &= ~mask;
|
||||
irq_mask = hw->dev->ctrl.grp[cmc].irq_mask;
|
||||
if (cmc == 0) {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT0;
|
||||
} else {
|
||||
if (chan < 4) {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT1;
|
||||
hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT;
|
||||
} else {
|
||||
reg = CMICX_PDMA_IRQ_RAW_STAT2;
|
||||
hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
hw->dev->intr_mask(hw->dev, cmc, chan, reg & 0xfff, 0);
|
||||
hw->dev->ctrl.grp[cmc].irq_mask = irq_mask;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Release Packet DMA credits to EP.
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_credits_release(struct pdma_hw *hw)
|
||||
{
|
||||
int credits;
|
||||
uint32_t val;
|
||||
|
||||
/*
|
||||
* Since only 6 bits of iproc_cmic_to_ep_credits[5:0] are being used,
|
||||
* so we have to set the max credits value twice in order to release
|
||||
* 64 credits to EP.
|
||||
* Only do this once when HW is initialized.
|
||||
*/
|
||||
hw->hdls.reg_rd32(hw, CMICX_EPINTF_RELEASE_CREDITS, &val);
|
||||
if (!val) {
|
||||
credits = 63;
|
||||
hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits);
|
||||
hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1);
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 0);
|
||||
credits = 1;
|
||||
hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits);
|
||||
hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initialize HW
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_hw_init(struct pdma_hw *hw)
|
||||
{
|
||||
dev_mode_t mode = DEV_MODE_MAX;
|
||||
uint32_t val;
|
||||
|
||||
/* Temporarily upgrade work mode to get HW information in VNET mode. */
|
||||
if (hw->dev->mode == DEV_MODE_VNET) {
|
||||
mode = DEV_MODE_VNET;
|
||||
hw->dev->mode = DEV_MODE_UNET;
|
||||
}
|
||||
|
||||
/* Release Packet DMA credits to EP. */
|
||||
cmicx_pdma_credits_release(hw);
|
||||
|
||||
hw->info.name = CMICX_DEV_NAME;
|
||||
hw->info.dev_id = hw->dev->dev_id;
|
||||
hw->info.num_cmcs = CMICX_PDMA_CMC_MAX;
|
||||
hw->info.cmc_chans = CMICX_PDMA_CMC_CHAN;
|
||||
hw->info.num_chans = CMICX_PDMA_CMC_MAX * CMICX_PDMA_CMC_CHAN;
|
||||
hw->info.rx_dcb_size = CMICX_PDMA_DCB_SIZE;
|
||||
hw->info.tx_dcb_size = CMICX_PDMA_DCB_SIZE;
|
||||
hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val);
|
||||
hw->info.rx_ph_size = (val & 0xf) * 8;
|
||||
hw->info.tx_ph_size = CMICX_TX_PKT_HDR_SIZE;
|
||||
|
||||
/* Restore work mode to VNET. */
|
||||
if (mode == DEV_MODE_VNET) {
|
||||
hw->dev->mode = DEV_MODE_VNET;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Configure HW
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_hw_config(struct pdma_hw *hw)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &hw->dev->ctrl;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
uint32_t val, que_ctrl;
|
||||
int grp, que;
|
||||
uint32_t qi;
|
||||
int ip_if_hdr_endian = 0;
|
||||
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi];
|
||||
grp = rxq->group_id;
|
||||
que = rxq->chan_id % CMICX_PDMA_CMC_CHAN;
|
||||
que_ctrl = ctrl->grp[grp].que_ctrl[que];
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que));
|
||||
val = 0;
|
||||
if (que_ctrl & PDMA_PKT_BYTE_SWAP) {
|
||||
val |= CMICX_PDMA_PKT_BIG_ENDIAN;
|
||||
}
|
||||
if (que_ctrl & PDMA_OTH_BYTE_SWAP) {
|
||||
val |= CMICX_PDMA_DESC_BIG_ENDIAN;
|
||||
}
|
||||
if (que_ctrl & PDMA_HDR_BYTE_SWAP) {
|
||||
val |= CMICX_PDMA_HDR_BIG_ENDIAN;
|
||||
}
|
||||
if (!(hw->dev->flags & PDMA_CHAIN_MODE)) {
|
||||
val |= CMICX_PDMA_CONTINUOUS;
|
||||
}
|
||||
if (hw->dev->flags & PDMA_DESC_PREFETCH) {
|
||||
val |= CMICX_PDMA_CONTINUOUS_DESC;
|
||||
}
|
||||
val |= CMICX_PDMA_INTR_ON_DESC;
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val);
|
||||
}
|
||||
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi];
|
||||
grp = txq->group_id;
|
||||
que = txq->chan_id % CMICX_PDMA_CMC_CHAN;
|
||||
que_ctrl = ctrl->grp[grp].que_ctrl[que];
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que));
|
||||
val = 0;
|
||||
if (que_ctrl & PDMA_PKT_BYTE_SWAP) {
|
||||
val |= CMICX_PDMA_PKT_BIG_ENDIAN;
|
||||
val |= CMICX_PDMA_HDR_BIG_ENDIAN;
|
||||
ip_if_hdr_endian = 1;
|
||||
}
|
||||
if (que_ctrl & PDMA_OTH_BYTE_SWAP) {
|
||||
val |= CMICX_PDMA_DESC_BIG_ENDIAN;
|
||||
}
|
||||
if (que_ctrl & PDMA_HDR_BYTE_SWAP) {
|
||||
ip_if_hdr_endian = 1;
|
||||
}
|
||||
if (!(hw->dev->flags & PDMA_CHAIN_MODE)) {
|
||||
val |= CMICX_PDMA_CONTINUOUS;
|
||||
}
|
||||
if (hw->dev->flags & PDMA_DESC_PREFETCH) {
|
||||
val |= CMICX_PDMA_CONTINUOUS_DESC;
|
||||
}
|
||||
val |= CMICX_PDMA_INTR_ON_DESC | CMICX_PDMA_DIR;
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val);
|
||||
}
|
||||
|
||||
if (ip_if_hdr_endian == 1) {
|
||||
hw->hdls.reg_rd32(hw, CMICX_TOP_CONFIG, &val);
|
||||
val |= 0x80;
|
||||
hw->hdls.reg_wr32(hw, CMICX_TOP_CONFIG, val);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reset HW
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_hw_reset(struct pdma_hw *hw)
|
||||
{
|
||||
int gi, qi;
|
||||
|
||||
for (gi = 0; gi < hw->dev->num_groups; gi++) {
|
||||
if (!hw->dev->ctrl.grp[gi].attached) {
|
||||
continue;
|
||||
}
|
||||
for (qi = 0; qi < CMICX_PDMA_CMC_CHAN; qi++) {
|
||||
if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq ||
|
||||
1 << qi & hw->dev->ctrl.grp[gi].bm_txq) {
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(gi, qi), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_start(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val);
|
||||
val |= CMICX_PDMA_ENABLE;
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Stop a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_stop(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
int retry = CMICX_HW_RETRY_TIMES;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val);
|
||||
val |= CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT;
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val);
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
do {
|
||||
val = ~CMICX_PDMA_IS_ACTIVE;
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val);
|
||||
} while ((val & CMICX_PDMA_IS_ACTIVE) && (--retry > 0));
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val);
|
||||
val &= ~(CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT);
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val);
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Setup a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_LO(grp, que), addr);
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HI(grp, que), DMA_TO_BUS_HI(addr >> 32));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set halt point for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), addr);
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), DMA_TO_BUS_HI(addr >> 32));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Clear a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_clear(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_CTRLD_INTR(que));
|
||||
|
||||
MEMORY_BARRIER;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get interrupt number for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que, start_num, mask_shift;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
mask_shift = 0;
|
||||
if (grp > 0) {
|
||||
mask_shift = CMICX_IRQ_MASK_SHIFT + grp * 32;
|
||||
}
|
||||
start_num = CMICX_IRQ_START_NUM + mask_shift;
|
||||
|
||||
return start_num + (que * CMICX_IRQ_NUM_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_enable(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
cmicx_pdma_intr_enable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que));
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_disable(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
cmicx_pdma_intr_disable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que));
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Query interrupt status for a channel
|
||||
*
|
||||
* In group mode (interrupt processing per CMC), need to query each channel's
|
||||
* interrupt status.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_query(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val);
|
||||
|
||||
return val & CMICX_PDMA_IRQ_CTRLD_INTR(que);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt validity for a channel
|
||||
*
|
||||
* In group mode (interrupt processing per CMC), need to check each channel's
|
||||
* interrupt validity based on its interrupt mask.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_check(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICX_PDMA_IRQ_CTRLD_INTR(que))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cmicx_pdma_chan_intr_query(hw, chan);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Coalesce interrupt for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
val = CMICX_PDMA_INTR_COAL_ENA |
|
||||
CMICX_PDMA_INTR_THRESH(count) |
|
||||
CMICX_PDMA_INTR_TIMER(timer);
|
||||
hw->hdls.reg_wr32(hw, CMICX_PDMA_INTR_COAL(grp, que), val);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dump registers for a channel
|
||||
*/
|
||||
static int
|
||||
cmicx_pdma_chan_reg_dump(struct pdma_hw *hw, int chan)
|
||||
{
|
||||
uint32_t val;
|
||||
int grp, que;
|
||||
|
||||
grp = chan / CMICX_PDMA_CMC_CHAN;
|
||||
que = chan % CMICX_PDMA_CMC_CHAN;
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_CTRL: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_LO(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_LO: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HI(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HI: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_LO(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_LO: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_HI(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_HI: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_LO: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_HI: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX0(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX1(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_INTR_COAL(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_RBUF_THRE(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_STAT: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_TX(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_TXPKT: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX_DROP(grp, que), &val);
|
||||
CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT_DROP: 0x%08x\n", grp, que, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_IRQ_STAT: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), &val);
|
||||
CNET_PR("CMIC_CMC%d_IRQ_STAT_CLR: 0x%08x\n", grp, val);
|
||||
|
||||
val = hw->dev->ctrl.grp[grp].irq_mask;
|
||||
CNET_PR("CMIC_CMC%d_IRQ_ENAB: 0x%08x\n", grp, val);
|
||||
|
||||
hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val);
|
||||
CNET_PR("CMIC_EP_TO_CPU_HEADER_SIZE: 0x%08x\n", val);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initialize function pointers
|
||||
*/
|
||||
int
|
||||
bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw)
|
||||
{
|
||||
if (!hw) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
hw->hdls.reg_rd32 = cmicx_pdma_reg_read32;
|
||||
hw->hdls.reg_wr32 = cmicx_pdma_reg_write32;
|
||||
hw->hdls.hw_init = cmicx_pdma_hw_init;
|
||||
hw->hdls.hw_config = cmicx_pdma_hw_config;
|
||||
hw->hdls.hw_reset = cmicx_pdma_hw_reset;
|
||||
hw->hdls.chan_start = cmicx_pdma_chan_start;
|
||||
hw->hdls.chan_stop = cmicx_pdma_chan_stop;
|
||||
hw->hdls.chan_setup = cmicx_pdma_chan_setup;
|
||||
hw->hdls.chan_goto = cmicx_pdma_chan_goto;
|
||||
hw->hdls.chan_clear = cmicx_pdma_chan_clear;
|
||||
hw->hdls.chan_intr_num_get = cmicx_pdma_chan_intr_num_get;
|
||||
hw->hdls.chan_intr_enable = cmicx_pdma_chan_intr_enable;
|
||||
hw->hdls.chan_intr_disable = cmicx_pdma_chan_intr_disable;
|
||||
hw->hdls.chan_intr_query = cmicx_pdma_chan_intr_query;
|
||||
hw->hdls.chan_intr_check = cmicx_pdma_chan_intr_check;
|
||||
hw->hdls.chan_intr_coalesce = cmicx_pdma_chan_intr_coalesce;
|
||||
hw->hdls.chan_reg_dump = cmicx_pdma_chan_reg_dump;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,369 @@
|
||||
/*! \file bcmcnet_cmicd.h
|
||||
*
|
||||
* CMICd registers and descriptors definitions.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_CMICD_H
|
||||
#define BCMCNET_CMICD_H
|
||||
|
||||
/*!
|
||||
* \name CMICD PDMA HW definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! CMICD CMC number */
|
||||
#define CMICD_PDMA_CMC_MAX 3
|
||||
/*! CMICD CMC PDMA channels */
|
||||
#define CMICD_PDMA_CMC_CHAN 4
|
||||
/*! CMICD PDMA DCB size */
|
||||
#define CMICD_PDMA_DCB_SIZE 64
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name CMICD PDMA register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
#define CMICD_PDMA_CTRLr 0x0140
|
||||
#define CMICD_PDMA_STATr 0x0150
|
||||
#define CMICD_PDMA_STAT_HIr 0x0130
|
||||
#define CMICD_PDMA_STAT_CLRr 0x01a4
|
||||
#define CMICD_PDMA_DESCr 0x0158
|
||||
#define CMICD_PDMA_CURR_DESCr 0x01a8
|
||||
#define CMICD_PDMA_DESC_HALTr 0x0120
|
||||
#define CMICD_PDMA_COS_RX0r 0x0168
|
||||
#define CMICD_PDMA_COS_RX1r 0x016c
|
||||
#define CMICD_PDMA_COS_MASK0r 0x019c
|
||||
#define CMICD_PDMA_COS_MASK1r 0x01a0
|
||||
#define CMICD_PDMA_INTR_COALr 0x0188
|
||||
#define CMICD_PDMA_RBUF_THREr 0x0110
|
||||
#define CMICD_PDMA_COUNT_RXr 0x0480
|
||||
#define CMICD_PDMA_COUNT_TXr 0x0484
|
||||
#define CMICD_PDMA_COUNT_ALL_RXr 0x04a0
|
||||
#define CMICD_PDMA_COUNT_ALL_TXr 0x04a4
|
||||
#define CMICD_IRQ_STATr 0x0400
|
||||
#define CMICD_IRQ_PCI_MASKr 0x0414
|
||||
#define CMICD_IRQ_UC0_MASKr 0x0428
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name CMICD PDMA register address
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Base address */
|
||||
#define CMICD_GRP_BASE(g) (0x00031000 + 0x1000 * g)
|
||||
/*! Control register address */
|
||||
#define CMICD_PDMA_CTRL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CTRLr + q * 4)
|
||||
/*! Status register address */
|
||||
#define CMICD_PDMA_STAT(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STATr)
|
||||
/*! Status higher register address */
|
||||
#define CMICD_PDMA_STAT_HI(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_HIr)
|
||||
/*! Status clear register address */
|
||||
#define CMICD_PDMA_STAT_CLR(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_CLRr)
|
||||
/*! Descriptor register address */
|
||||
#define CMICD_PDMA_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESCr + q * 4)
|
||||
/*! Current descriptor register address */
|
||||
#define CMICD_PDMA_CURR_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CURR_DESCr + q * 4)
|
||||
/*! Descriptor halt register address */
|
||||
#define CMICD_PDMA_DESC_HALT(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESC_HALTr + q * 4)
|
||||
/*! COS Rx0 register address */
|
||||
#define CMICD_PDMA_COS_RX0(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX0r + q * 8)
|
||||
/*! COS Rx1 register address */
|
||||
#define CMICD_PDMA_COS_RX1(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX1r + q * 8)
|
||||
/*! COS Mask0 register address */
|
||||
#define CMICD_PDMA_COS_MASK0(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK0r)
|
||||
/*! COS Mask1 register address */
|
||||
#define CMICD_PDMA_COS_MASK1(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK1r)
|
||||
/*! Interrupt coalesce register address */
|
||||
#define CMICD_PDMA_INTR_COAL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_INTR_COALr + q * 4)
|
||||
/*! Rx buffer threshhold register address */
|
||||
#define CMICD_PDMA_RBUF_THRE(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_RBUF_THREr + q * 4)
|
||||
/*! Rx counter register address */
|
||||
#define CMICD_PDMA_COUNT_RX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_RXr + q * 8)
|
||||
/*! Tx counter register address */
|
||||
#define CMICD_PDMA_COUNT_TX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_TXr + q * 8)
|
||||
/*! Rx global counter register address */
|
||||
#define CMICD_PDMA_COUNT_ALL_RX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_RXr)
|
||||
/*! Tx gloable counter register address */
|
||||
#define CMICD_PDMA_COUNT_ALL_TX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_TXr)
|
||||
/*! Interrupt status register address */
|
||||
#define CMICD_IRQ_STAT(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_STATr)
|
||||
/*! Interrupt PCI mask register address */
|
||||
#define CMICD_IRQ_PCI_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_PCI_MASKr)
|
||||
/*! Interrupt UC0 mask register address */
|
||||
#define CMICD_IRQ_UC0_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_UC0_MASKr)
|
||||
/*! Credits release release register address */
|
||||
#define CMICD_EPINTF_RELEASE_CREDITS 0x0001a000
|
||||
/*! Device revision register address */
|
||||
#define CMICD_DEV_REV_ID 0x00010224
|
||||
/*! CMIC revison register address */
|
||||
#define CMICD_CMICM_REV_ID 0x00010228
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Control register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Continuous DMA mode */
|
||||
#define CMICD_PDMA_CONTINUOUS 0x00000200
|
||||
/*! Controlled interrupt */
|
||||
#define CMICD_PDMA_CNTLD_INTR 0x00000100
|
||||
/*! Update status on reload */
|
||||
#define CMICD_PDMA_RLD_STAT_DIS 0x00000080
|
||||
/*! Dropped on chain end */
|
||||
#define CMICD_PDMA_DROP_ON_END 0x00000040
|
||||
/*! Descriptor big endianess */
|
||||
#define CMICD_PDMA_DESC_BIG_ENDIAN 0x00000020
|
||||
/*! Packet DMA big endianess */
|
||||
#define CMICD_PDMA_PKT_BIG_ENDIAN 0x00000010
|
||||
/*! Interrupt after descriptor */
|
||||
#define CMICD_PDMA_INTR_ON_DESC 0x00000008
|
||||
/*! Abort DMA */
|
||||
#define CMICD_PDMA_ABORT 0x00000004
|
||||
/*! Enable DMA */
|
||||
#define CMICD_PDMA_ENABLE 0x00000002
|
||||
/*! DMA direction */
|
||||
#define CMICD_PDMA_DIR 0x00000001
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Status register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Chain done */
|
||||
#define CMICD_PDMA_CHAIN_DONE(q) (0x00000001 << (q))
|
||||
/*! Descriptor done */
|
||||
#define CMICD_PDMA_DESC_DONE(q) (0x00000010 << (q))
|
||||
/*! Active */
|
||||
#define CMICD_PDMA_ACTIVE(q) (0x00000100 << (q))
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Status clear register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Clear completed interrupt */
|
||||
#define CMICD_PDMA_DESC_CMPLT(q) (0x00000001 << (q))
|
||||
/*! Clear controlled interrupt */
|
||||
#define CMICD_PDMA_DESC_CNTLD(q) (0x00000100 << (q))
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Interrupt_coalesce register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Interrupt coalesce enable */
|
||||
#define CMICD_PDMA_INTR_COAL_ENA (1 << 31)
|
||||
/*! Interrupt coalesce threshhold */
|
||||
#define CMICD_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16)
|
||||
/*! Interrupt coalesce timeout */
|
||||
#define CMICD_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff)
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Interrupt status&mask register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Interrupt mask */
|
||||
#define CMICD_PDMA_IRQ_MASK 0x78000000
|
||||
/*! Descriptor done */
|
||||
#define CMICD_IRQ_DESC_DONE(q) (0x00004000 >> (2 * (q)))
|
||||
/*! Chain done */
|
||||
#define CMICD_IRQ_CHAIN_DONE(q) (0x00008000 >> (2 * (q)))
|
||||
/*! Controlled interrupt */
|
||||
#define CMICD_IRQ_DESC_CNTLD(q) (0x08000000 << (q))
|
||||
/*! Interrupt start number */
|
||||
#define CMICD_IRQ_START_NUM 27
|
||||
/*! Interrupt number offset */
|
||||
#define CMICD_IRQ_NUM_OFFSET 1
|
||||
/*! Interrupt mask shift */
|
||||
#define CMICD_IRQ_MASK_SHIFT 0
|
||||
/*! Interrupt mask zeroing */
|
||||
#define CMICD_IRQ_ACT_CHAN(mask) (((mask) & CMICD_PDMA_IRQ_MASK) >> CMICD_IRQ_START_NUM)
|
||||
/*! \} */
|
||||
|
||||
/*! 32-bit register read */
|
||||
#define DEV_READ32(_c, _a, _p) \
|
||||
do { \
|
||||
if ((_c)->dev->mode != DEV_MODE_VNET) { \
|
||||
*(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*! 32-bit register write */
|
||||
#define DEV_WRITE32(_c, _a, _v) \
|
||||
do { \
|
||||
if ((_c)->dev->mode != DEV_MODE_VNET) { \
|
||||
((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*!
|
||||
* \brief Rx metadata in descriptor.
|
||||
*/
|
||||
struct rx_metadata {
|
||||
/*! Metadata */
|
||||
volatile uint32_t data[13];
|
||||
|
||||
/*! Status */
|
||||
volatile uint32_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*!
|
||||
* \brief Rx descriptor.
|
||||
*/
|
||||
struct cmicd_rx_desc {
|
||||
/*! Packet address */
|
||||
volatile uint32_t addr;
|
||||
|
||||
/*! Packet control */
|
||||
volatile uint32_t ctrl;
|
||||
|
||||
/*! Metadata fields */
|
||||
struct rx_metadata md;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*! Reserve Rx meta data size in packet buffer */
|
||||
#define CMICD_RX_META_RESV 64
|
||||
|
||||
/*!
|
||||
* \brief Tx metadata in descriptor.
|
||||
*/
|
||||
struct tx_metadata {
|
||||
/*! Metadata */
|
||||
volatile uint32_t data[4];
|
||||
|
||||
/*! Reserved */
|
||||
volatile uint32_t rsvd[9];
|
||||
|
||||
/*! Status */
|
||||
volatile uint32_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*!
|
||||
* \brief Tx descriptor.
|
||||
*/
|
||||
struct cmicd_tx_desc {
|
||||
/*! Packet address */
|
||||
volatile uint32_t addr;
|
||||
|
||||
/*! Packet control */
|
||||
volatile uint32_t ctrl;
|
||||
|
||||
/*! Metadata fields */
|
||||
struct tx_metadata md;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*! Reserve Tx meta data size in packet buffer */
|
||||
#define CMICD_TX_META_RESV 16
|
||||
|
||||
/*!
|
||||
* Flags related to descriptors.
|
||||
*/
|
||||
/*! Controlled interrupt */
|
||||
#define CMICD_DESC_CTRL_CNTLD_INTR (1 << 24)
|
||||
/*! Completed interrupt */
|
||||
#define CMICD_DESC_CTRL_CMPLT_INTR (1 << 23)
|
||||
/*! Reload DCB */
|
||||
#define CMICD_DESC_CTRL_RELOAD (1 << 18)
|
||||
/*! Scatter DCB */
|
||||
#define CMICD_DESC_CTRL_SCATTER (1 << 17)
|
||||
/*! Chained DCB */
|
||||
#define CMICD_DESC_CTRL_CHAIN (1 << 16)
|
||||
/*! Control flags */
|
||||
#define CMICD_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16)
|
||||
/*! Purge packet */
|
||||
#define CMICD_DESC_TX_PURGE_PKT (1 << 6)
|
||||
/*! Pause packet */
|
||||
#define CMICD_DESC_TX_PAUSE_PKT (1 << 5)
|
||||
/*! Higig packet */
|
||||
#define CMICD_DESC_TX_HIGIG_PKT (1 << 3)
|
||||
/*! Packet length */
|
||||
#define CMICD_DESC_CTRL_LEN(len) ((len) & 0xffff)
|
||||
/*! Done */
|
||||
#define CMICD_DESC_STAT_RTX_DONE (1 << 31)
|
||||
/*! Head error */
|
||||
#define CMICD_DESC_STAT_HEAD_ERR (1 << 20)
|
||||
/*! Data error */
|
||||
#define CMICD_DESC_STAT_DATA_ERR (1 << 19)
|
||||
/*! Cell error */
|
||||
#define CMICD_DESC_STAT_CELL_ERR (1 << 18)
|
||||
/*! Error mask */
|
||||
#define CMICD_DESC_STAT_ERR_MASK (CMICD_DESC_STAT_HEAD_ERR | \
|
||||
CMICD_DESC_STAT_DATA_ERR | \
|
||||
CMICD_DESC_STAT_CELL_ERR)
|
||||
/*! Packet start */
|
||||
#define CMICD_DESC_STAT_PKT_START (1 << 17)
|
||||
/*! Packet end */
|
||||
#define CMICD_DESC_STAT_PKT_END (1 << 16)
|
||||
/*! Get done state */
|
||||
#define CMICD_DESC_STAT_DONE(stat) ((stat) & CMICD_DESC_STAT_RTX_DONE)
|
||||
/*! Get flags */
|
||||
#define CMICD_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003)
|
||||
/*! Get packet length */
|
||||
#define CMICD_DESC_STAT_LEN(stat) ((stat) & 0xffff)
|
||||
|
||||
/*! HW access retry times */
|
||||
#define CMICD_HW_RETRY_TIMES 100000
|
||||
|
||||
/*!
|
||||
* \brief Initialize HW handles.
|
||||
*
|
||||
* \param [in] hw HW structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Initialize descriptor operations.
|
||||
*
|
||||
* \param [in] hw HW structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicd_pdma_desc_ops_init(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Attach device driver.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicd_pdma_driver_attach(struct pdma_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Detach device driver.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicd_pdma_driver_detach(struct pdma_dev *dev);
|
||||
|
||||
#endif /* BCMCNET_CMICD_H */
|
||||
|
@ -0,0 +1,379 @@
|
||||
/*! \file bcmcnet_cmicx.h
|
||||
*
|
||||
* CMICx registers and descriptors definitions.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_CMICX_H
|
||||
#define BCMCNET_CMICX_H
|
||||
|
||||
/*!
|
||||
* \name CMICX PDMA HW definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! CMICX CMC number */
|
||||
#define CMICX_PDMA_CMC_MAX 2
|
||||
/*! CMICX CMC PDMA channels */
|
||||
#define CMICX_PDMA_CMC_CHAN 8
|
||||
/*! CMICX PDMA DCB size */
|
||||
#define CMICX_PDMA_DCB_SIZE 16
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name CMICX PCIe device address definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! CMICX PCIE offset */
|
||||
#define CMICX_PCIE_SO_OFFSET 0x10000000
|
||||
/*! Higher DMA address to bus address */
|
||||
#define DMA_TO_BUS_HI(dma) ((dma) | CMICX_PCIE_SO_OFFSET)
|
||||
/*! Higher bus address to DMA address */
|
||||
#define BUS_TO_DMA_HI(bus) ((bus) & ~CMICX_PCIE_SO_OFFSET)
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name CMICX PDMA register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
#define CMICX_PDMA_CTRLr 0x2100
|
||||
#define CMICX_PDMA_STATr 0x2114
|
||||
#define CMICX_PDMA_DESC_LOr 0x2104
|
||||
#define CMICX_PDMA_DESC_HIr 0x2108
|
||||
#define CMICX_PDMA_CURR_DESC_LOr 0x2124
|
||||
#define CMICX_PDMA_CURR_DESC_HIr 0x2128
|
||||
#define CMICX_PDMA_DESC_HALT_LOr 0x210c
|
||||
#define CMICX_PDMA_DESC_HALT_HIr 0x2110
|
||||
#define CMICX_PDMA_COS_CTRL_RX0r 0x2118
|
||||
#define CMICX_PDMA_COS_CTRL_RX1r 0x211c
|
||||
#define CMICX_PDMA_INTR_COALr 0x2120
|
||||
#define CMICX_PDMA_RBUF_THREr 0x212c
|
||||
#define CMICX_PDMA_DEBUG_CTRLr 0x2130
|
||||
#define CMICX_PDMA_DEBUG_SM_STATr 0x2134
|
||||
#define CMICX_PDMA_DEBUG_STATr 0x2138
|
||||
#define CMICX_PDMA_COUNT_RXr 0x213c
|
||||
#define CMICX_PDMA_COUNT_TXr 0x2140
|
||||
#define CMICX_PDMA_COUNT_RX_DROPr 0x2144
|
||||
#define CMICX_PDMA_DESC_CNT_REQr 0x2148
|
||||
#define CMICX_PDMA_DESC_CNT_RXr 0x214c
|
||||
#define CMICX_PDMA_DESC_CNT_STATr 0x2150
|
||||
#define CMICX_PDMA_IRQ_STATr 0x106c
|
||||
#define CMICX_PDMA_IRQ_STAT_CLRr 0x1074
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name CMICX PDMA register address
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Base address */
|
||||
#define CMICX_GRP_BASE(g) (0x00000000 + 0x3000 * g)
|
||||
/*! Control register address */
|
||||
#define CMICX_PDMA_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CTRLr + q * 0x80)
|
||||
/*! Status register address */
|
||||
#define CMICX_PDMA_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_STATr + q * 0x80)
|
||||
/*! Descriptor Address Lower register address */
|
||||
#define CMICX_PDMA_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_LOr + q * 0x80)
|
||||
/*! Descriptor Address Higher register address */
|
||||
#define CMICX_PDMA_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HIr + q * 0x80)
|
||||
/*! Current Descriptor Address Lower register address */
|
||||
#define CMICX_PDMA_CURR_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_LOr + q * 0x80)
|
||||
/*! Current Descriptor Address Higher register address */
|
||||
#define CMICX_PDMA_CURR_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_HIr + q * 0x80)
|
||||
/*! Descriptor Halt Address Lower register address */
|
||||
#define CMICX_PDMA_DESC_HALT_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_LOr + q * 0x80)
|
||||
/*! Descriptor Halt Address Higher register address */
|
||||
#define CMICX_PDMA_DESC_HALT_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_HIr + q * 0x80)
|
||||
/*! COS Control Rx0 register address */
|
||||
#define CMICX_PDMA_COS_CTRL_RX0(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX0r + q * 0x80)
|
||||
/*! COS Control Rx1 register address */
|
||||
#define CMICX_PDMA_COS_CTRL_RX1(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX1r + q * 0x80)
|
||||
/*! Interrupt Coalesce register address */
|
||||
#define CMICX_PDMA_INTR_COAL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_INTR_COALr + q * 0x80)
|
||||
/*! Rx Buffer Threshhold register address */
|
||||
#define CMICX_PDMA_RBUF_THRE(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_RBUF_THREr + q * 0x80)
|
||||
/*! Debug Control register address */
|
||||
#define CMICX_PDMA_DEBUG_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_CTRLr + q * 0x80)
|
||||
/*! Debug Status register address */
|
||||
#define CMICX_PDMA_DEBUG_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_STATr + q * 0x80)
|
||||
/*! Debug State Machine Status register address */
|
||||
#define CMICX_PDMA_DEBUG_SM_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_SM_STATr + q * 0x80)
|
||||
/*! Rx Packet Count register address */
|
||||
#define CMICX_PDMA_COUNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RXr + q * 0x80)
|
||||
/*! Tx Packet Count register address */
|
||||
#define CMICX_PDMA_COUNT_TX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_TXr + q * 0x80)
|
||||
/*! Dropped Rx Packet Count register address */
|
||||
#define CMICX_PDMA_COUNT_RX_DROP(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RX_DROPr + q * 0x80)
|
||||
/*! Requested Descriptor Count register address */
|
||||
#define CMICX_PDMA_DESC_CNT_REQ(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_REQr + q * 0x80)
|
||||
/*! Received Descriptor Count register address */
|
||||
#define CMICX_PDMA_DESC_CNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_RXr + q * 0x80)
|
||||
/*! Updated Descriptor Count register address */
|
||||
#define CMICX_PDMA_DESC_CNT_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_STATr + q * 0x80)
|
||||
/*! Interrupt Status register address */
|
||||
#define CMICX_PDMA_IRQ_STAT(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STATr)
|
||||
/*! Interrupt Status Clear register address */
|
||||
#define CMICX_PDMA_IRQ_STAT_CLR(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STAT_CLRr)
|
||||
/*! Interrupt Enable register address0 */
|
||||
#define CMICX_PDMA_IRQ_ENAB0 0x18013100
|
||||
/*! Interrupt Enable register address1 */
|
||||
#define CMICX_PDMA_IRQ_ENAB1 0x18013104
|
||||
/*! Interrupt Enable register address2 */
|
||||
#define CMICX_PDMA_IRQ_ENAB2 0x18013108
|
||||
/*! Interrupt raw status register address0 */
|
||||
#define CMICX_PDMA_IRQ_RAW_STAT0 0x18013150
|
||||
/*! Interrupt raw status register address1 */
|
||||
#define CMICX_PDMA_IRQ_RAW_STAT1 0x18013154
|
||||
/*! Interrupt raw status register address2 */
|
||||
#define CMICX_PDMA_IRQ_RAW_STAT2 0x18013158
|
||||
/*! EP_TO_CPU Header Size register address */
|
||||
#define CMICX_EP_TO_CPU_HEADER_SIZE 0x00000004
|
||||
/*! Top config register address */
|
||||
#define CMICX_TOP_CONFIG 0x00000008
|
||||
/*! Credits release register address */
|
||||
#define CMICX_EPINTF_RELEASE_CREDITS 0x0000006c
|
||||
/*! Max credits register address */
|
||||
#define CMICX_EPINTF_MAX_CREDITS 0x00000070
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Control register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Disable abort on error */
|
||||
#define CMICX_PDMA_NO_ABORT_ON_ERR 0x00002000
|
||||
/*! EP_TO_CPU header big endianess */
|
||||
#define CMICX_PDMA_HDR_BIG_ENDIAN 0x00001000
|
||||
/*! Continuous descriptor mode */
|
||||
#define CMICX_PDMA_CONTINUOUS_DESC 0x00000200
|
||||
/*! Continuous DMA mode */
|
||||
#define CMICX_PDMA_CONTINUOUS 0x00000100
|
||||
/*! Interrupt after descriptor */
|
||||
#define CMICX_PDMA_INTR_ON_DESC 0x00000080
|
||||
/*! Update status on reload */
|
||||
#define CMICX_PDMA_RLD_STAT_DIS 0x00000040
|
||||
/*! Dropped on chain end */
|
||||
#define CMICX_PDMA_DROP_ON_END 0x00000020
|
||||
/*! Descriptor big endianess */
|
||||
#define CMICX_PDMA_DESC_BIG_ENDIAN 0x00000010
|
||||
/*! Packet DMA big endianess */
|
||||
#define CMICX_PDMA_PKT_BIG_ENDIAN 0x00000008
|
||||
/*! Abort DMA */
|
||||
#define CMICX_PDMA_ABORT 0x00000004
|
||||
/*! Enable DMA */
|
||||
#define CMICX_PDMA_ENABLE 0x00000002
|
||||
/*! DMA direction */
|
||||
#define CMICX_PDMA_DIR 0x00000001
|
||||
/*! EP_TO_CPU header alignment bytes */
|
||||
#define CMICX_PDMA_HDR_ALMNT(bytes) (((bytes) & 0x3) << 10)
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Status register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Channel in halt */
|
||||
#define CMICX_PDMA_IN_HALT 0x00000040
|
||||
/*! Channel active */
|
||||
#define CMICX_PDMA_IS_ACTIVE 0x00000002
|
||||
/*! Chain done */
|
||||
#define CMICX_PDMA_CHAIN_DONE 0x00000001
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Interrupt_coalesce register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Interrupt coalesce enable */
|
||||
#define CMICX_PDMA_INTR_COAL_ENA (1 << 31)
|
||||
/*! Interrupt coalesce threshhold */
|
||||
#define CMICX_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16)
|
||||
/*! Interrupt coalesce timeout */
|
||||
#define CMICX_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff)
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Interrupt status&clear register definitions
|
||||
*/
|
||||
/*! \{ */
|
||||
/*! Descriptor done */
|
||||
#define CMICX_PDMA_IRQ_DESC_DONE(q) (0x00000001 << ((q) * 4))
|
||||
/*! Chain done */
|
||||
#define CMICX_PDMA_IRQ_CHAIN_DONE(q) (0x00000002 << ((q) * 4))
|
||||
/*! Coalescing interrupt */
|
||||
#define CMICX_PDMA_IRQ_COALESCE_INTR(q) (0x00000004 << ((q) * 4))
|
||||
/*! Controlled interrupt */
|
||||
#define CMICX_PDMA_IRQ_CTRLD_INTR(q) (0x00000008 << ((q) * 4))
|
||||
/*! Interrupt mask */
|
||||
#define CMICX_PDMA_IRQ_MASK(q) (0xf << ((q) * 4))
|
||||
/*! Interrupt start number */
|
||||
#define CMICX_IRQ_START_NUM (128 + 3)
|
||||
/*! Interrupt number offset */
|
||||
#define CMICX_IRQ_NUM_OFFSET 4
|
||||
/*! Interrupt mask shift */
|
||||
#define CMICX_IRQ_MASK_SHIFT 16
|
||||
/*! \} */
|
||||
|
||||
/*! 32-bit register read */
|
||||
#define DEV_READ32(_c, _a, _p) \
|
||||
do { \
|
||||
if ((_c)->dev->mode != DEV_MODE_VNET) { \
|
||||
*(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*! 32-bit register write */
|
||||
#define DEV_WRITE32(_c, _a, _v) \
|
||||
do { \
|
||||
if ((_c)->dev->mode != DEV_MODE_VNET) { \
|
||||
((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*!
|
||||
* \brief Rx descriptor.
|
||||
*/
|
||||
struct cmicx_rx_desc {
|
||||
/*! Packet address lower */
|
||||
volatile uint32_t addr_lo;
|
||||
|
||||
/*! Packet address higher */
|
||||
volatile uint32_t addr_hi;
|
||||
|
||||
/*! Packet control */
|
||||
volatile uint32_t ctrl;
|
||||
|
||||
/*! Packet status */
|
||||
volatile uint32_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*!
|
||||
* \brief Tx descriptor.
|
||||
*/
|
||||
struct cmicx_tx_desc {
|
||||
/*! Packet address lower */
|
||||
volatile uint32_t addr_lo;
|
||||
|
||||
/*! Packet address higher */
|
||||
volatile uint32_t addr_hi;
|
||||
|
||||
/*! Packet control */
|
||||
volatile uint32_t ctrl;
|
||||
|
||||
/*! Packet status */
|
||||
volatile uint32_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*!
|
||||
* Flags related to descriptors.
|
||||
*/
|
||||
/*! Disable descriptor status write */
|
||||
#define CMICX_DESC_CTRL_STAT_WR_DIS (1 << 29)
|
||||
/*! Descriptors remaining */
|
||||
#define CMICX_DESC_CTRL_REMAIN(cnt) (((cnt) & 0xf) << 25)
|
||||
/*! Max remaining descriptors */
|
||||
#define CMICX_DESC_REMAIN_MAX 8
|
||||
/*! Controlled interrupt */
|
||||
#define CMICX_DESC_CTRL_CNTLD_INTR (1 << 24)
|
||||
/*! Completed interrupt */
|
||||
#define CMICX_DESC_CTRL_CMPLT_INTR (1 << 23)
|
||||
/*! Reload DCB */
|
||||
#define CMICX_DESC_CTRL_RELOAD (1 << 18)
|
||||
/*! Scatter DCB */
|
||||
#define CMICX_DESC_CTRL_SCATTER (1 << 17)
|
||||
/*! Chained DCB */
|
||||
#define CMICX_DESC_CTRL_CHAIN (1 << 16)
|
||||
/*! Control flags */
|
||||
#define CMICX_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16)
|
||||
/*! Purge packet */
|
||||
#define CMICX_DESC_TX_PURGE_PKT (1 << 6)
|
||||
/*! Higig packet */
|
||||
#define CMICX_DESC_TX_HIGIG_PKT (1 << 3)
|
||||
/*! Packet length */
|
||||
#define CMICX_DESC_CTRL_LEN(len) ((len) & 0xffff)
|
||||
/*! Done */
|
||||
#define CMICX_DESC_STAT_RTX_DONE (1 << 31)
|
||||
/*! Ecc error */
|
||||
#define CMICX_DESC_STAT_DATA_ERR (1 << 19)
|
||||
/*! Cell error */
|
||||
#define CMICX_DESC_STAT_CELL_ERR (1 << 18)
|
||||
/*! Error mask */
|
||||
#define CMICX_DESC_STAT_ERR_MASK (CMICX_DESC_STAT_DATA_ERR | \
|
||||
CMICX_DESC_STAT_CELL_ERR)
|
||||
/*! Packet start */
|
||||
#define CMICX_DESC_STAT_PKT_START (1 << 17)
|
||||
/*! Packet end */
|
||||
#define CMICX_DESC_STAT_PKT_END (1 << 16)
|
||||
/*! Get done state */
|
||||
#define CMICX_DESC_STAT_DONE(stat) ((stat) & CMICX_DESC_STAT_RTX_DONE)
|
||||
/*! Get flags */
|
||||
#define CMICX_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003)
|
||||
/*! Get packet length */
|
||||
#define CMICX_DESC_STAT_LEN(stat) ((stat) & 0xffff)
|
||||
|
||||
/*! Tx packet header size */
|
||||
#define CMICX_TX_PKT_HDR_SIZE 16
|
||||
|
||||
/*! HW access retry times */
|
||||
#define CMICX_HW_RETRY_TIMES 100000
|
||||
|
||||
/*!
|
||||
* \brief Initialize HW handles.
|
||||
*
|
||||
* \param [in] hw HW structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Initialize descriptor operations.
|
||||
*
|
||||
* \param [in] hw HW structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicx_pdma_desc_ops_init(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Attach device driver.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicx_pdma_driver_attach(struct pdma_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Detach device driver.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_cmicx_pdma_driver_detach(struct pdma_dev *dev);
|
||||
|
||||
#endif /* BCMCNET_CMICX_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,544 @@
|
||||
/*! \file bcmcnet_dev.h
|
||||
*
|
||||
* Generic data structure and macro definitions for BCMCNET device.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_DEV_H
|
||||
#define BCMCNET_DEV_H
|
||||
|
||||
#include <bcmcnet/bcmcnet_rxtx.h>
|
||||
|
||||
/*!
|
||||
* \brief HW information.
|
||||
*/
|
||||
struct hw_info {
|
||||
/*! HW name */
|
||||
char *name;
|
||||
|
||||
/*! HW version */
|
||||
int ver_no;
|
||||
|
||||
/*! Device ID */
|
||||
uint32_t dev_id;
|
||||
|
||||
/*! Revision ID */
|
||||
uint32_t rev_id;
|
||||
|
||||
/*! Number of CMCs */
|
||||
uint32_t num_cmcs;
|
||||
|
||||
/*! Number of CMC channels */
|
||||
uint32_t cmc_chans;
|
||||
|
||||
/*! Number of channels */
|
||||
uint32_t num_chans;
|
||||
|
||||
/*! Rx DCB size */
|
||||
uint32_t rx_dcb_size;
|
||||
|
||||
/*! Tx DCB size */
|
||||
uint32_t tx_dcb_size;
|
||||
|
||||
/*! Rx packet header size */
|
||||
uint32_t rx_ph_size;
|
||||
|
||||
/*! Tx packet header size */
|
||||
uint32_t tx_ph_size;
|
||||
|
||||
/*! HW structure point */
|
||||
struct pdma_hw *hw;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Read 32-bit register.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] addr Register address.
|
||||
* \param [in] data Pointer to read data.
|
||||
*/
|
||||
typedef void (*reg_rd32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t *data);
|
||||
|
||||
/*!
|
||||
* \brief Write 32-bit register.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] addr Register address.
|
||||
* \param [in] data Data to write.
|
||||
*/
|
||||
typedef void (*reg_wr32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t data);
|
||||
|
||||
/*!
|
||||
* \brief Pre-initialize hardware.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*pre_init_f)(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Initialize hardware.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*hw_init_f)(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Configure hardware.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*hw_config_f)(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Reset hardware.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*hw_reset_f)(struct pdma_hw *hw);
|
||||
|
||||
/*!
|
||||
* \brief Start channel.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_start_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Stop channel.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_stop_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Set up channel.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
* \param [in] addr Start DMA address of descriptors.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_setup_f)(struct pdma_hw *hw, int chan, uint64_t addr);
|
||||
|
||||
/*!
|
||||
* \brief Go to ohter descriptor.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
* \param [in] addr Destination DMA address of descriptors.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_goto_f)(struct pdma_hw *hw, int chan, uint64_t addr);
|
||||
|
||||
/*!
|
||||
* \brief Clear channel.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_clear_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Get interrupt number.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval Returned interrupt number, errors if negative value.
|
||||
*/
|
||||
typedef int (*chan_intr_num_get_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Enable interrupt.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_intr_enable_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Disable interrupt.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_intr_disable_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Query interrupt.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_intr_query_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Check interrupt.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_intr_check_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief Coalesce interrupt.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
* \param [in] count Count value to trigger interrupt.
|
||||
* \param [in] timer Timer value to triggre interrupt.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_intr_coalesce_f)(struct pdma_hw *hw, int chan, int count, int timer);
|
||||
|
||||
/*!
|
||||
* \brief Dump registers.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] chan Channel number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*chan_reg_dump_f)(struct pdma_hw *hw, int chan);
|
||||
|
||||
/*!
|
||||
* \brief HW handlers.
|
||||
*/
|
||||
struct hw_handlers {
|
||||
/*! 32 bits register read */
|
||||
reg_rd32_f reg_rd32;
|
||||
|
||||
/*! 32 bits register write */
|
||||
reg_wr32_f reg_wr32;
|
||||
|
||||
/*! HW pre-initialize */
|
||||
pre_init_f pre_init;
|
||||
|
||||
/*! HW initialize */
|
||||
hw_init_f hw_init;
|
||||
|
||||
/*! HW configure */
|
||||
hw_config_f hw_config;
|
||||
|
||||
/*! HW reset */
|
||||
hw_reset_f hw_reset;
|
||||
|
||||
/*! Channel start */
|
||||
chan_start_f chan_start;
|
||||
|
||||
/*! Channel stop */
|
||||
chan_stop_f chan_stop;
|
||||
|
||||
/*! Channel setup */
|
||||
chan_setup_f chan_setup;
|
||||
|
||||
/*! Channel goto */
|
||||
chan_goto_f chan_goto;
|
||||
|
||||
/*! Channel clear */
|
||||
chan_clear_f chan_clear;
|
||||
|
||||
/*! Channel interrupt number get */
|
||||
chan_intr_num_get_f chan_intr_num_get;
|
||||
|
||||
/*! Channel interrupt enable */
|
||||
chan_intr_enable_f chan_intr_enable;
|
||||
|
||||
/*! Channel interrupt disable */
|
||||
chan_intr_disable_f chan_intr_disable;
|
||||
|
||||
/*! Channel interrupt query */
|
||||
chan_intr_query_f chan_intr_query;
|
||||
|
||||
/*! Channel interrupt check */
|
||||
chan_intr_check_f chan_intr_check;
|
||||
|
||||
/*! Channel interrupt coalesce */
|
||||
chan_intr_coalesce_f chan_intr_coalesce;
|
||||
|
||||
/*! Channel registers dump */
|
||||
chan_reg_dump_f chan_reg_dump;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Initialize Rx descriptor.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_MEMORY Allocation failed.
|
||||
*/
|
||||
typedef int (*rx_desc_init_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Clean up Rx descriptor.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*rx_desc_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Clean up Rx ring.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] budget Budget for each operation.
|
||||
*
|
||||
* \retval Number of descriptors finished.
|
||||
*/
|
||||
typedef int (*rx_ring_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget);
|
||||
|
||||
/*!
|
||||
* \brief Dump Rx ring.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*rx_ring_dump_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Suspend Rx queue.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*rx_suspend_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Resume Rx queue.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*rx_resume_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Initialize Tx descriptor.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] txq Pointer to Tx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_MEMORY Allocation failed.
|
||||
*/
|
||||
typedef int (*tx_desc_init_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq);
|
||||
|
||||
/*!
|
||||
* \brief Clean up Tx descriptor.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] txq Pointer to Tx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*tx_desc_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq);
|
||||
|
||||
/*!
|
||||
* \brief Clean up Tx ring.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] txq Pointer to Tx queue struture.
|
||||
* \param [in] budget Budget for each operation.
|
||||
*
|
||||
* \retval Number of descriptors finished.
|
||||
*/
|
||||
typedef int (*tx_ring_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget);
|
||||
|
||||
/*!
|
||||
* \brief Dump Tx ring.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] txq Pointer to Tx queue struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
typedef int (*tx_ring_dump_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq);
|
||||
|
||||
/*!
|
||||
* \brief Transmit packet.
|
||||
*
|
||||
* \param [in] hw Pointer to hardware structure.
|
||||
* \param [in] txq Pointer to Tx queue struture.
|
||||
* \param [in] buf Pointer to packet buffer struture.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
typedef int (*pkt_xmit_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf);
|
||||
|
||||
/*!
|
||||
* \brief Descriptor operations.
|
||||
*/
|
||||
struct desc_operations {
|
||||
/*! Rx descriptor initialize */
|
||||
rx_desc_init_f rx_desc_init;
|
||||
|
||||
/*! Rx descriptor cleanup */
|
||||
rx_desc_clean_f rx_desc_clean;
|
||||
|
||||
/*! Rx ring cleanup */
|
||||
rx_ring_clean_f rx_ring_clean;
|
||||
|
||||
/*! Rx ring dump */
|
||||
rx_ring_dump_f rx_ring_dump;
|
||||
|
||||
/*! Rx suspend */
|
||||
rx_suspend_f rx_suspend;
|
||||
|
||||
/*! Rx resume */
|
||||
rx_resume_f rx_resume;
|
||||
|
||||
/*! Tx descriptor initialize */
|
||||
tx_desc_init_f tx_desc_init;
|
||||
|
||||
/*! Tx descriptor cleanup */
|
||||
tx_desc_clean_f tx_desc_clean;
|
||||
|
||||
/*! Tx ring cleanup */
|
||||
tx_ring_clean_f tx_ring_clean;
|
||||
|
||||
/*! Tx ring dump */
|
||||
tx_ring_dump_f tx_ring_dump;
|
||||
|
||||
/*! Tx transmit */
|
||||
pkt_xmit_f pkt_xmit;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief HW structure.
|
||||
*/
|
||||
struct pdma_hw {
|
||||
/*! Device number */
|
||||
int unit;
|
||||
|
||||
/*! Device structure point */
|
||||
struct pdma_dev *dev;
|
||||
|
||||
/*! HW information */
|
||||
struct hw_info info;
|
||||
|
||||
/*! HW handlers */
|
||||
struct hw_handlers hdls;
|
||||
|
||||
/*! HW operations */
|
||||
struct desc_operations dops;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Open device.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_open(struct pdma_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Coalesce Rx interrupt.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
* \param [in] count Interrupt threshhold.
|
||||
* \param [in] timer Timer value.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer);
|
||||
|
||||
/*!
|
||||
* \brief Coalesce Tx interrupt.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
* \param [in] count Interrupt threshhold.
|
||||
* \param [in] timer Timer value.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer);
|
||||
|
||||
/*!
|
||||
* \brief Dump Rx queue registers.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_reg_dump(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Dump Tx queue registers.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_reg_dump(struct pdma_dev *dev, int queue);
|
||||
|
||||
#endif /* BCMCNET_DEV_H */
|
||||
|
@ -0,0 +1,305 @@
|
||||
/*! \file bcmcnet_internal.h
|
||||
*
|
||||
* BCMCNET internal data structure and macro definitions.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_INTERNAL_H
|
||||
#define BCMCNET_INTERNAL_H
|
||||
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
|
||||
/*! CMICD name */
|
||||
#define CMICD_DEV_NAME "cmicd"
|
||||
|
||||
/*! CMICX name */
|
||||
#define CMICX_DEV_NAME "cmicx"
|
||||
|
||||
/*!
|
||||
* \brief Allocate descriptor ring buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] dma DMA address of ring buffer.
|
||||
*
|
||||
* \retval Pointer to DMA buffer or NULL if an error occurred.
|
||||
*/
|
||||
typedef void *(*ring_buf_alloc_f)(struct pdma_dev *dev, uint32_t, dma_addr_t *dma);
|
||||
|
||||
/*!
|
||||
* \brief Free descriptor ring buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] size Size of DMA buffer.
|
||||
* \param [in] mem Pointer to DMA buffer.
|
||||
* \param [in] dma DMA address of ring buffer.
|
||||
*/
|
||||
typedef void (*ring_buf_free_f)(struct pdma_dev *dev, uint32_t size, void *mem,
|
||||
dma_addr_t dma);
|
||||
|
||||
/*!
|
||||
* \brief Allocate Rx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_MEMORY Allocation failed.
|
||||
*/
|
||||
typedef int (*rx_buf_alloc_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf);
|
||||
|
||||
/*!
|
||||
* \brief Get Rx packet buffer DMA address.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
* \param [in] dma DMA address of packet buffer.
|
||||
*/
|
||||
typedef void (*rx_buf_dma_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, dma_addr_t *dma);
|
||||
|
||||
/*!
|
||||
* \brief Check Rx packet buffer validity.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
*
|
||||
* \retval Ture Buffer is available or FALSE.
|
||||
*/
|
||||
typedef int (*rx_buf_avail_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf);
|
||||
|
||||
/*!
|
||||
* \brief Get Rx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
* \param [in] len Packet length.
|
||||
*
|
||||
* \retval Pointer to packet header structure or NULL if failed.
|
||||
*/
|
||||
typedef struct pkt_hdr *(*rx_buf_get_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, int len);
|
||||
|
||||
/*!
|
||||
* \brief Put Rx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
* \param [in] len Packet length.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_MEMORY Allocation failed.
|
||||
*/
|
||||
typedef int (*rx_buf_put_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, int len);
|
||||
|
||||
/*!
|
||||
* \brief Free Rx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
*/
|
||||
typedef void (*rx_buf_free_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf);
|
||||
|
||||
/*!
|
||||
* \brief Get Rx packet buffer mode.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] rxq Pointer to Rx queue struture.
|
||||
*
|
||||
* \retval Buffer mode.
|
||||
*/
|
||||
typedef enum buf_mode (*rx_buf_mode_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq);
|
||||
|
||||
/*!
|
||||
* \brief Get Tx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] txq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
* \param [in] buf Packet buffer.
|
||||
*
|
||||
* \retval Pointer to packet header structure or NULL if failed.
|
||||
*/
|
||||
typedef struct pkt_hdr *(*tx_buf_get_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf, void *buf);
|
||||
|
||||
/*!
|
||||
* \brief Get Tx packet buffer DMA address.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] txq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
* \param [in] dma DMA address of packet buffer.
|
||||
*/
|
||||
typedef void (*tx_buf_dma_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf, dma_addr_t *dma);
|
||||
|
||||
/*!
|
||||
* \brief Free Tx packet buffer.
|
||||
*
|
||||
* \param [in] dev Pointer to Packet DMA device.
|
||||
* \param [in] txq Pointer to Rx queue struture.
|
||||
* \param [in] pbuf Pointer to packet buffer structure.
|
||||
*/
|
||||
typedef void (*tx_buf_free_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf);
|
||||
|
||||
/*!
|
||||
* \brief Buffer manager.
|
||||
*/
|
||||
struct pdma_buf_mngr {
|
||||
/*! Allocate descriptor ring buffer */
|
||||
ring_buf_alloc_f ring_buf_alloc;
|
||||
|
||||
/*! Free descriptor ring buffer */
|
||||
ring_buf_free_f ring_buf_free;
|
||||
|
||||
/*! Allocate Rx packet buffer */
|
||||
rx_buf_alloc_f rx_buf_alloc;
|
||||
|
||||
/*! Get Rx packet buffer DMA address */
|
||||
rx_buf_dma_f rx_buf_dma;
|
||||
|
||||
/*! Check Rx packet buffer validity */
|
||||
rx_buf_avail_f rx_buf_avail;
|
||||
|
||||
/*! Get Rx packet buffer */
|
||||
rx_buf_get_f rx_buf_get;
|
||||
|
||||
/*! Put Rx packet buffer */
|
||||
rx_buf_put_f rx_buf_put;
|
||||
|
||||
/*! Free Rx packet buffer */
|
||||
rx_buf_free_f rx_buf_free;
|
||||
|
||||
/*! Get Rx packet buffer mode */
|
||||
rx_buf_mode_f rx_buf_mode;
|
||||
|
||||
/*! Get Tx packet buffer */
|
||||
tx_buf_get_f tx_buf_get;
|
||||
|
||||
/*! Get Tx packet buffer DMA address */
|
||||
tx_buf_dma_f tx_buf_dma;
|
||||
|
||||
/*! Free Tx packet buffer */
|
||||
tx_buf_free_f tx_buf_free;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Wait for the kernel networking subsystem.
|
||||
*
|
||||
* \param [in] unit Device number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_FAIL Operation failed.
|
||||
*/
|
||||
typedef int (*bcmcnet_vnet_wait_f)(int unit);
|
||||
|
||||
/*!
|
||||
* \brief Wake up the kernel networking subsystem.
|
||||
*
|
||||
* \param [in] unit Device number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_FAIL Operation failed.
|
||||
*/
|
||||
typedef int (*bcmcnet_hnet_wake_f)(int unit);
|
||||
|
||||
/*!
|
||||
* \brief Dock to the kernel networking subsystem.
|
||||
*
|
||||
* \param [in] unit Device number.
|
||||
* \param [in] vsync Sync data.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_FAIL Operation failed.
|
||||
*/
|
||||
typedef int (*bcmcnet_vnet_dock_f)(int unit, vnet_sync_t *vsync);
|
||||
|
||||
/*!
|
||||
* \brief Undock from the kernel networking subsystem.
|
||||
*
|
||||
* \param [in] unit Device number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_FAIL Operation failed.
|
||||
*/
|
||||
typedef int (*bcmcnet_vnet_undock_f)(int unit);
|
||||
|
||||
/*!
|
||||
* \brief VNET operations.
|
||||
*/
|
||||
typedef struct bcmcnet_vnet_ops_s {
|
||||
/*!
|
||||
* VNET wait for HNET.
|
||||
* VNET calls this to wait for any notification from HNET.
|
||||
*/
|
||||
bcmcnet_vnet_wait_f vnet_wait;
|
||||
|
||||
/*!
|
||||
* VNET wake up HNET.
|
||||
* VNET calls this to notify HNET that Tx/Rx is ready.
|
||||
*/
|
||||
bcmcnet_hnet_wake_f hnet_wake;
|
||||
|
||||
/*!
|
||||
* VNET dock to HNET.
|
||||
* This is called to notify HNET that VNET is ready to work and synchronize
|
||||
* vrings information to HNET.
|
||||
*/
|
||||
bcmcnet_vnet_dock_f vnet_dock;
|
||||
|
||||
/*!
|
||||
* VNET undock from HNET.
|
||||
* This is called to notify HNET that VNET is ready to leave.
|
||||
*/
|
||||
bcmcnet_vnet_undock_f vnet_undock;
|
||||
} bcmcnet_vnet_ops_t;
|
||||
|
||||
/*!
|
||||
* \brief Initialize buffer manager.
|
||||
*
|
||||
* \param [in] dev Device structure pointer.
|
||||
*/
|
||||
extern void
|
||||
bcmcnet_buf_mngr_init(struct pdma_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Register VNET operations.
|
||||
*
|
||||
* \param [in] unit Device number.
|
||||
* \param [in] vnet_ops VNET operations.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_PARAM Invalid parameters.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_vnet_ops_register(int unit, bcmcnet_vnet_ops_t *vnet_ops);
|
||||
|
||||
#endif /* BCMCNET_INTERNAL_H */
|
||||
|
@ -0,0 +1,512 @@
|
||||
/*! \file bcmcnet_rxtx.h
|
||||
*
|
||||
* Generic data structure and macro definitions for BCMCNET Rx/Tx.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_RXTX_H
|
||||
#define BCMCNET_RXTX_H
|
||||
|
||||
/*! Default descriptor number in each ring */
|
||||
#define NUM_RING_DESC 64
|
||||
|
||||
/*! Maximum number of packets to be handled in one poll call */
|
||||
#define NUM_RXTX_BUDGET 64
|
||||
|
||||
/*!
|
||||
* \brief Rx buffer mode definitions.
|
||||
*/
|
||||
enum buf_mode {
|
||||
/*! Private DMA buffer in user space */
|
||||
PDMA_BUF_MODE_PRIV,
|
||||
|
||||
/*! SKB in kernel */
|
||||
PDMA_BUF_MODE_SKB,
|
||||
|
||||
/*! Paged buffer in kernel */
|
||||
PDMA_BUF_MODE_PAGE,
|
||||
|
||||
/*! Kernel buffer mapped to user space */
|
||||
PDMA_BUF_MODE_MAPPED,
|
||||
|
||||
/*! MAX mode */
|
||||
PDMA_BUF_MODE_MAX
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Rx queue statistics.
|
||||
*/
|
||||
struct rx_stats {
|
||||
/*! Number of received packets */
|
||||
uint64_t packets;
|
||||
|
||||
/*! Number of received bytes */
|
||||
uint64_t bytes;
|
||||
|
||||
/*! Number of dropped packets */
|
||||
uint64_t dropped;
|
||||
|
||||
/*! Number of errors */
|
||||
uint64_t errors;
|
||||
|
||||
/*! Number of head errors */
|
||||
uint64_t head_errors;
|
||||
|
||||
/*! Number of data errors */
|
||||
uint64_t data_errors;
|
||||
|
||||
/*! Number of cell errors */
|
||||
uint64_t cell_errors;
|
||||
|
||||
/*! Number of failed allocation */
|
||||
uint64_t nomems;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Rx queue structure
|
||||
*/
|
||||
struct pdma_rx_queue {
|
||||
/*! Group index to which this queue belongs */
|
||||
uint32_t group_id;
|
||||
|
||||
/*! Global channel index */
|
||||
uint32_t chan_id;
|
||||
|
||||
/*! Queue index */
|
||||
uint32_t queue_id;
|
||||
|
||||
/*! Pointer to the device control structure */
|
||||
struct dev_ctrl *ctrl;
|
||||
|
||||
/*! Rx packet buffer pointers */
|
||||
struct pdma_rx_buf *pbuf;
|
||||
|
||||
/*! Rx ring address */
|
||||
void *ring;
|
||||
|
||||
/*! Rx ring DMA address */
|
||||
dma_addr_t ring_addr;
|
||||
|
||||
/*! Rx ring DMA halt address */
|
||||
dma_addr_t halt_addr;
|
||||
|
||||
/*! Rx buffer size */
|
||||
uint32_t buf_size;
|
||||
|
||||
/*! Total number of descriptors */
|
||||
uint32_t nb_desc;
|
||||
|
||||
/*! Next free ring entry */
|
||||
uint32_t curr;
|
||||
|
||||
/*! Halt ring entry */
|
||||
uint32_t halt;
|
||||
|
||||
/*! Max free descriptors to hold */
|
||||
uint32_t free_thresh;
|
||||
|
||||
/*! Rx interrupt coalesce value */
|
||||
uint32_t ic_val;
|
||||
|
||||
/*! Rx interrupt coalescing */
|
||||
int intr_coalescing;
|
||||
|
||||
/*! Queue statistics */
|
||||
struct rx_stats stats;
|
||||
|
||||
/*! Rx queue spin lock */
|
||||
sal_spinlock_t lock;
|
||||
|
||||
/*! Queue state */
|
||||
int state;
|
||||
/*! Queue is used */
|
||||
#define PDMA_RX_QUEUE_USED (1 << 0)
|
||||
/*! Queue is setup */
|
||||
#define PDMA_RX_QUEUE_SETUP (1 << 1)
|
||||
/*! Queue is active */
|
||||
#define PDMA_RX_QUEUE_ACTIVE (1 << 2)
|
||||
/*! Queue is busy */
|
||||
#define PDMA_RX_QUEUE_BUSY (1 << 3)
|
||||
/*! Queue is suspended */
|
||||
#define PDMA_RX_QUEUE_XOFF (1 << 4)
|
||||
/*! Queue is batch refilled */
|
||||
#define PDMA_RX_BATCH_REFILL (1 << 5)
|
||||
|
||||
/*! DMA buffer mode */
|
||||
enum buf_mode mode;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Tx queue statistics.
|
||||
*/
|
||||
struct tx_stats {
|
||||
/*! Number of sent packets */
|
||||
uint64_t packets;
|
||||
|
||||
/*! Number of sent bytes */
|
||||
uint64_t bytes;
|
||||
|
||||
/*! Number of dropped packets */
|
||||
uint64_t dropped;
|
||||
|
||||
/*! Number of errors */
|
||||
uint64_t errors;
|
||||
|
||||
/*! Number of suspends */
|
||||
uint64_t xoffs;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Tx queue structure.
|
||||
*/
|
||||
struct pdma_tx_queue {
|
||||
/*! Group index to which this queue belongs */
|
||||
uint32_t group_id;
|
||||
|
||||
/*! Global channel index */
|
||||
uint32_t chan_id;
|
||||
|
||||
/*! Queue index */
|
||||
uint32_t queue_id;
|
||||
|
||||
/*! pointer to the device control structure */
|
||||
struct dev_ctrl *ctrl;
|
||||
|
||||
/*! Tx packet buffer pointers */
|
||||
struct pdma_tx_buf *pbuf;
|
||||
|
||||
/*! Tx ring address */
|
||||
void *ring;
|
||||
|
||||
/*! Tx ring DMA address */
|
||||
dma_addr_t ring_addr;
|
||||
|
||||
/*! Tx ring DMA halt address */
|
||||
dma_addr_t halt_addr;
|
||||
|
||||
/*! Total number of descriptors */
|
||||
uint32_t nb_desc;
|
||||
|
||||
/*! Next free ring entry */
|
||||
uint32_t curr;
|
||||
|
||||
/*! First entry to be transmitted */
|
||||
uint32_t dirt;
|
||||
|
||||
/*! Halt ring entry */
|
||||
uint32_t halt;
|
||||
|
||||
/*! Max free descriptors to hold in non-intr mode */
|
||||
uint32_t free_thresh;
|
||||
|
||||
/*! Tx interrupt coalesce value */
|
||||
uint32_t ic_val;
|
||||
|
||||
/*! Tx interrupt coalescing */
|
||||
int intr_coalescing;
|
||||
|
||||
/*! Queue statistics */
|
||||
struct tx_stats stats;
|
||||
|
||||
/*! Tx queue spin lock */
|
||||
sal_spinlock_t lock;
|
||||
|
||||
/*! Tx mutex spin lock */
|
||||
sal_spinlock_t mutex;
|
||||
|
||||
/*! Tx mutex and flow control semaphore */
|
||||
sal_sem_t sem;
|
||||
|
||||
/*! Queue state */
|
||||
int state;
|
||||
/*! Queue is used */
|
||||
#define PDMA_TX_QUEUE_USED (1 << 0)
|
||||
/*! Queue is setup */
|
||||
#define PDMA_TX_QUEUE_SETUP (1 << 1)
|
||||
/*! Queue is active */
|
||||
#define PDMA_TX_QUEUE_ACTIVE (1 << 2)
|
||||
/*! Queue is setup */
|
||||
#define PDMA_TX_QUEUE_BUSY (1 << 3)
|
||||
/*! Queue is suspended */
|
||||
#define PDMA_TX_QUEUE_XOFF (1 << 4)
|
||||
/*! Queue is poll mode */
|
||||
#define PDMA_TX_QUEUE_POLL (1 << 5)
|
||||
|
||||
/*! DMA buffer mode */
|
||||
enum buf_mode mode;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Setup Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Release Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Restore Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Setup virtual Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Release virtual Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Setup Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Release Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Restore Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Setup virtual Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Release virtual Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Suspend Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Resume Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Suspend Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Resume Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Wakeup Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Start Tx queue transmission.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
* \param [in] buf Tx packet buffer.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf);
|
||||
|
||||
/*!
|
||||
* \brief Poll Rx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
* \param [in] budget Poll budget.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget);
|
||||
|
||||
/*!
|
||||
* \brief Poll Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
* \param [in] budget Poll budget.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget);
|
||||
|
||||
/*!
|
||||
* \brief Poll queue group.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] group Group number.
|
||||
* \param [in] budget Poll budget.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget);
|
||||
|
||||
/*!
|
||||
* \brief Dump Rx ring.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Rx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue);
|
||||
|
||||
/*!
|
||||
* \brief Dump Tx ring.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue);
|
||||
|
||||
#endif /* BCMCNET_RXTX_H */
|
||||
|
@ -0,0 +1,263 @@
|
||||
/*! \file bcmcnet_types.h
|
||||
*
|
||||
* BCMCNET public data structure and macro definitions.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef BCMCNET_TYPES_H
|
||||
#define BCMCNET_TYPES_H
|
||||
|
||||
#include <bcmcnet/bcmcnet_dep.h>
|
||||
|
||||
/*! Maximum length of device name */
|
||||
#define DEV_NAME_LEN_MAX 16
|
||||
|
||||
/*! Maximum number of groups supported each device */
|
||||
#define NUM_GRP_MAX 4
|
||||
|
||||
/*! Maximum number of queues supported each group */
|
||||
#define NUM_Q_PER_GRP 8
|
||||
|
||||
/*! Maximum number of queues supported each device */
|
||||
#define NUM_QUE_MAX (NUM_GRP_MAX * NUM_Q_PER_GRP)
|
||||
|
||||
/*! Maximum length of jumbo frame */
|
||||
#define JUMBO_FRAME_LEN_MAX 0xffff
|
||||
|
||||
/*! Maximum Rx buffer size */
|
||||
#define RX_BUF_SIZE_MAX JUMBO_FRAME_LEN_MAX
|
||||
|
||||
/*! Minimum Rx buffer size */
|
||||
#define RX_BUF_SIZE_MIN 68
|
||||
|
||||
/*! Default Rx buffer size */
|
||||
#define RX_BUF_SIZE_DFLT 9216
|
||||
|
||||
/*!
|
||||
* \brief Transmission direction.
|
||||
*/
|
||||
enum pdma_dir {
|
||||
PDMA_Q_RX = 0,
|
||||
PDMA_Q_TX
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Device information.
|
||||
*/
|
||||
typedef struct bcmcnet_dev_info {
|
||||
/*! Device name */
|
||||
char dev_name[DEV_NAME_LEN_MAX];
|
||||
|
||||
/*! Device ID */
|
||||
uint32_t dev_id;
|
||||
|
||||
/*! Device type */
|
||||
uint32_t dev_type;
|
||||
|
||||
/*! Maximum number of groups */
|
||||
uint32_t max_groups;
|
||||
|
||||
/*! Maximum number of queues */
|
||||
uint32_t max_queues;
|
||||
|
||||
/*! Bitmap of groups at work */
|
||||
uint32_t bm_groups;
|
||||
|
||||
/*! Bitmap of Rx queues at work */
|
||||
uint32_t bm_rx_queues;
|
||||
|
||||
/*! Bitmap of Tx queues at work */
|
||||
uint32_t bm_tx_queues;
|
||||
|
||||
/*! Number of groups at work */
|
||||
uint32_t nb_groups;
|
||||
|
||||
/*! Number of Rx queues at work */
|
||||
uint32_t nb_rx_queues;
|
||||
|
||||
/*! Number of Tx queues at work */
|
||||
uint32_t nb_tx_queues;
|
||||
|
||||
/*! Rx descriptor size */
|
||||
uint32_t rx_desc_size;
|
||||
|
||||
/*! Tx descriptor size */
|
||||
uint32_t tx_desc_size;
|
||||
|
||||
/*! Rx packet header size */
|
||||
uint32_t rx_ph_size;
|
||||
|
||||
/*! Tx packet header size */
|
||||
uint32_t tx_ph_size;
|
||||
|
||||
/*! Rx buffer size */
|
||||
uint32_t rx_buf_dflt;
|
||||
|
||||
/*! Number of descriptors for a queue */
|
||||
uint32_t nb_desc_dflt;
|
||||
|
||||
/*! Rx buffer size per queue */
|
||||
uint32_t rx_buf_size[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of Rx descriptors per queue */
|
||||
uint32_t nb_rx_desc[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of Tx descriptors per queue */
|
||||
uint32_t nb_tx_desc[NUM_QUE_MAX];
|
||||
} bcmcnet_dev_info_t;
|
||||
|
||||
/*!
|
||||
* \brief Device statistics.
|
||||
*/
|
||||
typedef struct bcmcnet_dev_stats {
|
||||
/*! Number of successfully received packets */
|
||||
uint64_t rx_packets;
|
||||
|
||||
/*! Number of successfully received bytes */
|
||||
uint64_t rx_bytes;
|
||||
|
||||
/*! Number of dropped packets */
|
||||
uint64_t rx_dropped;
|
||||
|
||||
/*! Number of erroneous received packets */
|
||||
uint64_t rx_errors;
|
||||
|
||||
/*! Number of error head packets */
|
||||
uint64_t rx_head_errors;
|
||||
|
||||
/*! Number of error data packets */
|
||||
uint64_t rx_data_errors;
|
||||
|
||||
/*! Number of error cell packets */
|
||||
uint64_t rx_cell_errors;
|
||||
|
||||
/*! Number of RX pktbuf allocation failures */
|
||||
uint64_t rx_nomems;
|
||||
|
||||
/*! Number of successfully transmitted packets */
|
||||
uint64_t tx_packets;
|
||||
|
||||
/*! Number of successfully transmitted bytes */
|
||||
uint64_t tx_bytes;
|
||||
|
||||
/*! Number of dropped packets */
|
||||
uint64_t tx_dropped;
|
||||
|
||||
/*! Number of failed transmitted packets */
|
||||
uint64_t tx_errors;
|
||||
|
||||
/*! Number of suspended transmission */
|
||||
uint64_t tx_xoffs;
|
||||
|
||||
/*! Number of interrupts */
|
||||
uint64_t intrs;
|
||||
|
||||
/*! Number of successfully received packets per queue */
|
||||
uint64_t rxq_packets[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of successfully received bytes per queue */
|
||||
uint64_t rxq_bytes[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of dropped packets per queue */
|
||||
uint64_t rxq_dropped[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of erroneous received packets per queue */
|
||||
uint64_t rxq_errors[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of error head packets per queue */
|
||||
uint64_t rxq_head_errors[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of error data packets per queue */
|
||||
uint64_t rxq_data_errors[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of error cell packets per queue */
|
||||
uint64_t rxq_cell_errors[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of RX pktbuf allocation failures per queue */
|
||||
uint64_t rxq_nomems[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of successfully transmitted bytes per queue */
|
||||
uint64_t txq_packets[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of successfully transmitted bytes per queue */
|
||||
uint64_t txq_bytes[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of dropped packets per queue */
|
||||
uint64_t txq_dropped[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of failed transmitted packets per queue */
|
||||
uint64_t txq_errors[NUM_QUE_MAX];
|
||||
|
||||
/*! Number of suspended transmission per queue */
|
||||
uint64_t txq_xoffs[NUM_QUE_MAX];
|
||||
} bcmcnet_dev_stats_t;
|
||||
|
||||
/*!
|
||||
* \brief Device modes.
|
||||
*/
|
||||
typedef enum dev_mode_e {
|
||||
/*!
|
||||
* User network mode.
|
||||
* The standalone CNET works in user space.
|
||||
*/
|
||||
DEV_MODE_UNET = 0,
|
||||
|
||||
/*!
|
||||
* Kernel network mode.
|
||||
* Combined with KNET module, CNET works in kernel space.
|
||||
*/
|
||||
DEV_MODE_KNET,
|
||||
|
||||
/*!
|
||||
* Virtual network mode.
|
||||
* CNET works in user space as a virtual network.
|
||||
* The hypervisor must be deployed in KNET module.
|
||||
*/
|
||||
DEV_MODE_VNET,
|
||||
|
||||
/*!
|
||||
* Hyper network mode.
|
||||
* Combined with KNET module, CNET works in kernel space as a hypervisor.
|
||||
* The virtual network is not neccessary in this mode.
|
||||
*/
|
||||
DEV_MODE_HNET,
|
||||
|
||||
/*! Maximum number of mode */
|
||||
DEV_MODE_MAX
|
||||
} dev_mode_t;
|
||||
|
||||
/*!
|
||||
* \brief VNET sync data.
|
||||
*/
|
||||
typedef struct vnet_sync_s {
|
||||
/*! Rx ring address */
|
||||
uint64_t rx_ring_addr[NUM_QUE_MAX];
|
||||
|
||||
/*! Rx ring size */
|
||||
uint32_t rx_ring_size[NUM_QUE_MAX];
|
||||
|
||||
/*! Tx ring address */
|
||||
uint64_t tx_ring_addr[NUM_QUE_MAX];
|
||||
|
||||
/*! Tx ring size */
|
||||
uint32_t tx_ring_size[NUM_QUE_MAX];
|
||||
} vnet_sync_t;
|
||||
|
||||
#endif /* BCMCNET_TYPES_H */
|
||||
|
@ -0,0 +1,701 @@
|
||||
/*! \file bcmcnet_core.c
|
||||
*
|
||||
* Utility routines for BCMCNET driver.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
|
||||
/*!
|
||||
* Initialize a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_init(struct pdma_dev *dev)
|
||||
{
|
||||
int rv;
|
||||
|
||||
/* Open the device */
|
||||
rv = bcmcnet_pdma_open(dev);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
dev->attached = 1;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Clean up a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_cleanup(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->attached) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
dev->ops->dev_close(dev);
|
||||
dev->ops = NULL;
|
||||
|
||||
dev->attached = 0;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_start(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
int rv;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
if (dev->started) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
rv = dev->ops->dev_config(dev, ctrl->bm_rxq, ctrl->bm_txq);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Start all the Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
rv = dev->ops->rx_queue_setup(dev, qi);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
dev->ops->rx_queue_intr_enable(dev, qi);
|
||||
dev->ops->rx_queue_start(dev, qi);
|
||||
}
|
||||
|
||||
/* Start all the Tx queues */
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
dev->ops->tx_queue_setup(dev, qi);
|
||||
dev->ops->tx_queue_intr_enable(dev, qi);
|
||||
dev->ops->tx_queue_start(dev, qi);
|
||||
dev->ops->tx_queue_wakeup(dev, qi);
|
||||
}
|
||||
|
||||
bcmcnet_pdma_dev_info_get(dev);
|
||||
|
||||
dev->started = 1;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Stop a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_stop(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
if (!dev->started) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/* Stop all the Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
dev->ops->rx_queue_intr_disable(dev, qi);
|
||||
dev->ops->rx_queue_stop(dev, qi);
|
||||
dev->ops->rx_queue_release(dev, qi);
|
||||
}
|
||||
|
||||
/* Stop all the Tx queues */
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
dev->ops->tx_queue_intr_disable(dev, qi);
|
||||
dev->ops->tx_queue_stop(dev, qi);
|
||||
dev->ops->tx_queue_wakeup(dev, qi);
|
||||
dev->ops->tx_queue_release(dev, qi);
|
||||
}
|
||||
|
||||
dev->started = 0;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Suspend a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_suspend(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return dev->ops->dev_suspend(dev);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resume a device
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_resume(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return dev->ops->dev_resume(dev);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Suspend Rx
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_rx_suspend(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/* Suspend all the Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
dev->ops->rx_queue_suspend(dev, qi);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resume Rx
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_rx_resume(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/* Resume all the Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
dev->ops->rx_queue_resume(dev, qi);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dock to HNET
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_dock(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
int rv;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/* Set up all the virtual Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
rv = dev->ops->rx_vqueue_setup(dev, qi);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up all the virtual Tx queues */
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
rv = dev->ops->tx_vqueue_setup(dev, qi);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Undock from HNET
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_undock(struct pdma_dev *dev)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
uint32_t qi;
|
||||
|
||||
if (!dev->attached) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/* Release all the virtual Rx queues */
|
||||
for (qi = 0; qi < ctrl->nb_rxq; qi++) {
|
||||
dev->ops->rx_vqueue_release(dev, qi);
|
||||
}
|
||||
|
||||
/* Release all the virtual Tx queues */
|
||||
for (qi = 0; qi < ctrl->nb_txq; qi++) {
|
||||
dev->ops->tx_vqueue_release(dev, qi);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get device information
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_info_get(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->dev_info_get) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
dev->ops->dev_info_get(dev);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get device statistics
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_stats_get(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->dev_stats_get) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
dev->ops->dev_stats_get(dev);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reset device statistics
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_stats_reset(struct pdma_dev *dev)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->dev_stats_reset) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
dev->ops->dev_stats_reset(dev);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Convert a queue index to channel index
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_queue_to_chan(struct pdma_dev *dev, int queue, int dir, int *chan)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
|
||||
if (dir == PDMA_Q_RX) {
|
||||
if ((uint32_t)queue >= ctrl->nb_rxq || chan == NULL) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
} else {
|
||||
if ((uint32_t)queue >= ctrl->nb_txq || chan == NULL) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->ops || !dev->ops->dev_lq_to_pq) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->dev_lq_to_pq(dev, queue, dir, chan);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Convert a channel index to queue index
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_dev_chan_to_queue(struct pdma_dev *dev, int chan, int *queue, int *dir)
|
||||
{
|
||||
if (chan < 0 || chan >= dev->num_queues || queue == NULL || dir == NULL) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
if (!dev->ops || !dev->ops->dev_pq_to_lq) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->dev_pq_to_lq(dev, chan, queue, dir);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_rx_queue_intr_enable(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->rx_queue_intr_enable) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->rx_queue_intr_enable(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_rx_queue_intr_disable(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->rx_queue_intr_disable) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->rx_queue_intr_disable(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Acknowledge interrupt for a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_rx_queue_intr_ack(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->rx_queue_intr_ack) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->rx_queue_intr_ack(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt for a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_rx_queue_intr_check(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->rx_queue_intr_check) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->rx_queue_intr_check(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_tx_queue_intr_enable(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->tx_queue_intr_enable) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->tx_queue_intr_enable(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_tx_queue_intr_disable(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->tx_queue_intr_disable) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->tx_queue_intr_disable(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Acknowledge interrupt for a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_tx_queue_intr_ack(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->tx_queue_intr_ack) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->tx_queue_intr_ack(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt for a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_tx_queue_intr_check(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->tx_queue_intr_check) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->tx_queue_intr_check(dev, queue);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_queue_intr_enable(struct pdma_dev *dev, struct intr_handle *hdl)
|
||||
{
|
||||
if (hdl->dir == PDMA_Q_RX) {
|
||||
return bcmcnet_rx_queue_intr_enable(dev, hdl->queue);
|
||||
} else {
|
||||
return bcmcnet_tx_queue_intr_enable(dev, hdl->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_queue_intr_disable(struct pdma_dev *dev, struct intr_handle *hdl)
|
||||
{
|
||||
if (hdl->dir == PDMA_Q_RX) {
|
||||
return bcmcnet_rx_queue_intr_disable(dev, hdl->queue);
|
||||
} else {
|
||||
return bcmcnet_tx_queue_intr_disable(dev, hdl->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Acknowledge interrupt for a queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_queue_intr_ack(struct pdma_dev *dev, struct intr_handle *hdl)
|
||||
{
|
||||
if (hdl->dir == PDMA_Q_RX) {
|
||||
return bcmcnet_rx_queue_intr_ack(dev, hdl->queue);
|
||||
} else {
|
||||
return bcmcnet_tx_queue_intr_ack(dev, hdl->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt for a queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_queue_intr_check(struct pdma_dev *dev, struct intr_handle *hdl)
|
||||
{
|
||||
if (hdl->dir == PDMA_Q_RX) {
|
||||
return bcmcnet_rx_queue_intr_check(dev, hdl->queue);
|
||||
} else {
|
||||
return bcmcnet_tx_queue_intr_check(dev, hdl->queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt for a queue group
|
||||
*/
|
||||
int
|
||||
bcmcnet_group_intr_enable(struct pdma_dev *dev, int group)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct queue_group *grp = &ctrl->grp[group];
|
||||
int queue, dir;
|
||||
int i;
|
||||
|
||||
if (!dev->ops) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->rx_queue_intr_enable(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_txq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->tx_queue_intr_enable(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Disable interrupt for a queue group
|
||||
*/
|
||||
int
|
||||
bcmcnet_group_intr_disable(struct pdma_dev *dev, int group)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct queue_group *grp = &ctrl->grp[group];
|
||||
int queue, dir;
|
||||
int i;
|
||||
|
||||
if (!dev->ops) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->rx_queue_intr_disable(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_txq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->tx_queue_intr_disable(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Acknowledge interrupt for a queue group
|
||||
*/
|
||||
int
|
||||
bcmcnet_group_intr_ack(struct pdma_dev *dev, int group)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct queue_group *grp = &ctrl->grp[group];
|
||||
int queue, dir;
|
||||
int i;
|
||||
|
||||
if (!dev->ops) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->rx_queue_intr_ack(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_txq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
dev->ops->tx_queue_intr_ack(dev, queue);
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check interrupt for a queue group
|
||||
*/
|
||||
int
|
||||
bcmcnet_group_intr_check(struct pdma_dev *dev, int group)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct queue_group *grp = &ctrl->grp[group];
|
||||
int queue, dir;
|
||||
int i;
|
||||
|
||||
if (!dev->ops) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
if (dev->ops->rx_queue_intr_check(dev, queue)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_txq) {
|
||||
dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir);
|
||||
if (dev->ops->tx_queue_intr_check(dev, queue)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_rx_queue_poll(struct pdma_dev *dev, int queue, int budget)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->rx_queue_poll) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->rx_queue_poll(dev, queue, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_tx_queue_poll(struct pdma_dev *dev, int queue, int budget)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->tx_queue_poll) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->tx_queue_poll(dev, queue, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_queue_poll(struct pdma_dev *dev, struct intr_handle *hdl, int budget)
|
||||
{
|
||||
if (hdl->dir == PDMA_Q_RX) {
|
||||
return bcmcnet_rx_queue_poll(dev, hdl->queue, budget);
|
||||
} else {
|
||||
return bcmcnet_tx_queue_poll(dev, hdl->queue, budget);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a queue group
|
||||
*/
|
||||
int
|
||||
bcmcnet_group_poll(struct pdma_dev *dev, int group, int budget)
|
||||
{
|
||||
if (!dev->ops || !dev->ops->group_poll) {
|
||||
return SHR_E_INTERNAL;
|
||||
}
|
||||
|
||||
return dev->ops->group_poll(dev, group, budget);
|
||||
}
|
||||
|
1059
platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c
Normal file
1059
platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,708 @@
|
||||
/*! \file bcmcnet_rxtx.c
|
||||
*
|
||||
* Utility routines for BCMCNET Rx/Tx.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_rxtx.h>
|
||||
#include <bcmcnet/bcmcnet_buff.h>
|
||||
|
||||
/*!
|
||||
* Free a Rx ring
|
||||
*/
|
||||
static void
|
||||
bcn_rx_ring_free(struct pdma_rx_queue *rxq)
|
||||
{
|
||||
struct dev_ctrl *ctrl = rxq->ctrl;
|
||||
struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr;
|
||||
|
||||
if (rxq->lock) {
|
||||
sal_spinlock_destroy(rxq->lock);
|
||||
rxq->lock = NULL;
|
||||
}
|
||||
|
||||
if (rxq->ring) {
|
||||
bm->ring_buf_free(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1),
|
||||
rxq->ring, rxq->ring_addr);
|
||||
rxq->ring = NULL;
|
||||
}
|
||||
|
||||
if (rxq->pbuf) {
|
||||
sal_free(rxq->pbuf);
|
||||
rxq->pbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate a Rx ring
|
||||
*/
|
||||
static int
|
||||
bcn_rx_ring_alloc(struct pdma_rx_queue *rxq)
|
||||
{
|
||||
struct dev_ctrl *ctrl = rxq->ctrl;
|
||||
struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr;
|
||||
|
||||
/* Setup pktbuf ring */
|
||||
rxq->pbuf = sal_alloc(sizeof(*rxq->pbuf) * rxq->nb_desc, "bcmcnetRxBufRing");
|
||||
if (!rxq->pbuf) {
|
||||
goto cleanup;
|
||||
}
|
||||
sal_memset(rxq->pbuf, 0, sizeof(*rxq->pbuf) * rxq->nb_desc);
|
||||
|
||||
/* Allocate memory for descriptors */
|
||||
rxq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1),
|
||||
&rxq->ring_addr);
|
||||
if (!rxq->ring) {
|
||||
goto cleanup;
|
||||
}
|
||||
sal_memset(rxq->ring, 0, ctrl->rx_desc_size * (rxq->nb_desc + 1));
|
||||
|
||||
rxq->lock = sal_spinlock_create("bcmcnetRxQueueLock");
|
||||
if (!rxq->lock) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
|
||||
cleanup:
|
||||
bcn_rx_ring_free(rxq);
|
||||
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free a Tx ring
|
||||
*/
|
||||
static void
|
||||
bcn_tx_ring_free(struct pdma_tx_queue *txq)
|
||||
{
|
||||
struct dev_ctrl *ctrl = txq->ctrl;
|
||||
struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr;
|
||||
|
||||
if (txq->sem) {
|
||||
sal_sem_destroy(txq->sem);
|
||||
txq->sem = NULL;
|
||||
}
|
||||
|
||||
if (txq->mutex) {
|
||||
sal_spinlock_destroy(txq->mutex);
|
||||
txq->mutex = NULL;
|
||||
}
|
||||
|
||||
if (txq->lock) {
|
||||
sal_spinlock_destroy(txq->lock);
|
||||
txq->lock = NULL;
|
||||
}
|
||||
|
||||
if (txq->ring) {
|
||||
bm->ring_buf_free(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1),
|
||||
txq->ring, txq->ring_addr);
|
||||
txq->ring = NULL;
|
||||
}
|
||||
|
||||
if (txq->pbuf) {
|
||||
sal_free(txq->pbuf);
|
||||
txq->pbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate a Tx ring
|
||||
*/
|
||||
static int
|
||||
bcn_tx_ring_alloc(struct pdma_tx_queue *txq)
|
||||
{
|
||||
struct dev_ctrl *ctrl = txq->ctrl;
|
||||
struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr;
|
||||
|
||||
/* Setup pktbuf ring */
|
||||
txq->pbuf = sal_alloc(sizeof(*txq->pbuf) * txq->nb_desc, "bcmcnetTxBufRing");
|
||||
if (!txq->pbuf) {
|
||||
goto cleanup;
|
||||
}
|
||||
sal_memset(txq->pbuf, 0, sizeof(*txq->pbuf) * txq->nb_desc);
|
||||
|
||||
/* Allocate memory for descriptors */
|
||||
txq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1),
|
||||
&txq->ring_addr);
|
||||
if (!txq->ring) {
|
||||
goto cleanup;
|
||||
}
|
||||
sal_memset(txq->ring, 0, ctrl->tx_desc_size * (txq->nb_desc + 1));
|
||||
|
||||
txq->lock = sal_spinlock_create("bcmcnetTxQueueLock");
|
||||
if (!txq->lock) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
txq->mutex = sal_spinlock_create("bcmcnetTxMutexLock");
|
||||
if (!txq->mutex) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
txq->sem = sal_sem_create("bcmcnetTxMutexSem", SAL_SEM_BINARY, 0);
|
||||
if (!txq->sem) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
|
||||
cleanup:
|
||||
bcn_tx_ring_free(txq);
|
||||
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Rx polling
|
||||
*/
|
||||
static int
|
||||
bcn_rx_poll(struct pdma_rx_queue *rxq, int budget)
|
||||
{
|
||||
struct dev_ctrl *ctrl = rxq->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
|
||||
return hw->dops.rx_ring_clean(hw, rxq, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Tx polling
|
||||
*/
|
||||
static int
|
||||
bcn_tx_poll(struct pdma_tx_queue *txq, int budget)
|
||||
{
|
||||
struct dev_ctrl *ctrl = txq->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
|
||||
return hw->dops.tx_ring_clean(hw, txq, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Setup a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
int rv;
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (rxq->state & PDMA_RX_QUEUE_SETUP) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
rv = bcn_rx_ring_alloc(rxq);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = hw->dops.rx_desc_init(hw, rxq);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (dev->mode == DEV_MODE_VNET) {
|
||||
ctrl->vsync.rx_ring_addr[queue] = rxq->ring_addr;
|
||||
ctrl->vsync.rx_ring_size[queue] = rxq->nb_desc;
|
||||
}
|
||||
|
||||
rxq->state |= PDMA_RX_QUEUE_SETUP;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Release a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (rxq->state & PDMA_RX_QUEUE_SETUP) {
|
||||
hw->dops.rx_desc_clean(hw, rxq);
|
||||
bcn_rx_ring_free(rxq);
|
||||
rxq->state &= ~PDMA_RX_QUEUE_SETUP;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Restore a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (rxq->state & PDMA_RX_QUEUE_SETUP) {
|
||||
hw->dops.rx_desc_init(hw, rxq);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set up a virtual Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_rx_queue *vrxq = NULL;
|
||||
|
||||
vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue];
|
||||
if (vrxq->state & PDMA_RX_QUEUE_SETUP) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
if (dev->ctrl.vsync.rx_ring_addr[queue]) {
|
||||
vrxq->curr = 0;
|
||||
vrxq->nb_desc = dev->ctrl.vsync.rx_ring_size[queue];
|
||||
vrxq->ring_addr = dev->ctrl.vsync.rx_ring_addr[queue];
|
||||
vrxq->ring = dev->sys_p2v(dev, vrxq->ring_addr);
|
||||
vrxq->state |= PDMA_RX_QUEUE_SETUP;
|
||||
} else {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Release a virtual Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_rx_queue *vrxq = NULL;
|
||||
|
||||
vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue];
|
||||
if (vrxq->state & PDMA_RX_QUEUE_SETUP) {
|
||||
vrxq->state &= ~PDMA_RX_QUEUE_SETUP;
|
||||
vrxq->ring = NULL;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Setup a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
int rv;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (txq->state & PDMA_TX_QUEUE_SETUP) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
rv = bcn_tx_ring_alloc(txq);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = hw->dops.tx_desc_init(hw, txq);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (dev->mode == DEV_MODE_VNET) {
|
||||
ctrl->vsync.tx_ring_addr[queue] = txq->ring_addr;
|
||||
ctrl->vsync.tx_ring_size[queue] = txq->nb_desc;
|
||||
}
|
||||
|
||||
txq->state |= PDMA_TX_QUEUE_SETUP;
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Release a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (txq->state & PDMA_TX_QUEUE_SETUP) {
|
||||
hw->dops.tx_desc_clean(hw, txq);
|
||||
bcn_tx_ring_free(txq);
|
||||
txq->state &= ~PDMA_TX_QUEUE_SETUP;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Restore a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (txq->state & PDMA_TX_QUEUE_SETUP) {
|
||||
hw->dops.tx_desc_init(hw, txq);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set up a virtual Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *vtxq = NULL;
|
||||
|
||||
vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue];
|
||||
if (vtxq->state & PDMA_TX_QUEUE_SETUP) {
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
if (dev->ctrl.vsync.tx_ring_addr[queue]) {
|
||||
vtxq->curr = 0;
|
||||
vtxq->dirt = 0;
|
||||
vtxq->nb_desc = dev->ctrl.vsync.tx_ring_size[queue];
|
||||
vtxq->ring_addr = dev->ctrl.vsync.tx_ring_addr[queue];
|
||||
vtxq->ring = dev->sys_p2v(dev, vtxq->ring_addr);
|
||||
vtxq->state |= PDMA_TX_QUEUE_SETUP;
|
||||
} else {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Release a virtual Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *vtxq = NULL;
|
||||
|
||||
vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue];
|
||||
if (vtxq->state & PDMA_TX_QUEUE_SETUP) {
|
||||
vtxq->state &= ~PDMA_TX_QUEUE_SETUP;
|
||||
vtxq->ring = NULL;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Suspend a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return hw->dops.rx_suspend(hw, rxq);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resume a Rx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return hw->dops.rx_resume(hw, rxq);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Suspend a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
if (txq->sem) {
|
||||
sal_sem_take(txq->sem, SAL_SEM_FOREVER);
|
||||
}
|
||||
if (dev->tx_suspend) {
|
||||
dev->tx_suspend(dev, txq->queue_id);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resume a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
if (txq->sem) {
|
||||
sal_sem_give(txq->sem);
|
||||
}
|
||||
if (dev->tx_resume) {
|
||||
dev->tx_resume(dev, txq->queue_id);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Wake up a Tx queue
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (txq->sem) {
|
||||
sal_sem_give(txq->sem);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Transmit a outputing packet
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
return hw->dops.pkt_xmit(hw, txq, buf);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a Rx queues
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_rx_queue *rxq = ctrl->rx_queue[queue];
|
||||
|
||||
return bcn_rx_poll(rxq, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll a Tx queues
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_tx_queue *txq = ctrl->tx_queue[queue];
|
||||
|
||||
return bcn_tx_poll(txq, budget);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Poll for Rx/Tx queues in a group
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
struct queue_group *grp = &ctrl->grp[group];
|
||||
int done = 0, done_que, budget_que;
|
||||
int i;
|
||||
|
||||
/* Acknowledge the interrupts */
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
rxq = grp->rx_queue[i];
|
||||
if (rxq->state & PDMA_RX_QUEUE_ACTIVE) {
|
||||
if (hw->hdls.chan_intr_query(hw, rxq->chan_id)) {
|
||||
hw->hdls.chan_clear(hw, rxq->chan_id);
|
||||
grp->poll_queues |= 1 << i;
|
||||
} else if (rxq->state & PDMA_RX_QUEUE_BUSY) {
|
||||
rxq->state &= ~PDMA_RX_QUEUE_BUSY;
|
||||
grp->poll_queues |= 1 << i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
txq = grp->tx_queue[i];
|
||||
if (txq->state & PDMA_TX_QUEUE_ACTIVE) {
|
||||
if (hw->hdls.chan_intr_query(hw, txq->chan_id)) {
|
||||
hw->hdls.chan_clear(hw, txq->chan_id);
|
||||
grp->poll_queues |= 1 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate per queue budget */
|
||||
if (!grp->poll_queues) {
|
||||
grp->poll_queues = grp->bm_rxq | grp->bm_txq;
|
||||
budget_que = budget / grp->nb_rxq;
|
||||
} else {
|
||||
budget_que = 0;
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq & grp->poll_queues) {
|
||||
budget_que++;
|
||||
}
|
||||
}
|
||||
if (budget_que) {
|
||||
budget_que = budget / budget_que;
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll Rx queues */
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
if (1 << i & grp->bm_rxq & grp->poll_queues) {
|
||||
rxq = grp->rx_queue[i];
|
||||
done_que = bcn_rx_poll(rxq, budget_que);
|
||||
if (done_que < budget_que) {
|
||||
grp->poll_queues &= ~(1 << i);
|
||||
}
|
||||
done += done_que;
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll Tx queues */
|
||||
for (i = 0; i < dev->grp_queues; i++) {
|
||||
txq = grp->tx_queue[i];
|
||||
if (1 << i & grp->bm_txq & grp->poll_queues && !txq->free_thresh) {
|
||||
if (bcn_tx_poll(txq, budget) < budget) {
|
||||
grp->poll_queues &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grp->poll_queues ? budget : done;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dump a Rx ring
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = ctrl->hw;
|
||||
struct pdma_rx_queue *rxq = NULL;
|
||||
|
||||
if ((uint32_t)queue >= ctrl->nb_rxq) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue];
|
||||
if (rxq->state & PDMA_RX_QUEUE_ACTIVE) {
|
||||
hw->dops.rx_ring_dump(hw, rxq);
|
||||
}
|
||||
if (dev->mode == DEV_MODE_HNET) {
|
||||
rxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue];
|
||||
hw->dops.rx_ring_dump(hw, rxq);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Dump a Tx ring
|
||||
*/
|
||||
int
|
||||
bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue)
|
||||
{
|
||||
struct dev_ctrl *ctrl = &dev->ctrl;
|
||||
struct pdma_hw *hw = ctrl->hw;
|
||||
struct pdma_tx_queue *txq = NULL;
|
||||
|
||||
if ((uint32_t)queue >= ctrl->nb_txq) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue];
|
||||
if (txq->state & PDMA_TX_QUEUE_ACTIVE) {
|
||||
hw->dops.tx_ring_dump(hw, txq);
|
||||
}
|
||||
if (dev->mode == DEV_MODE_HNET) {
|
||||
txq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue];
|
||||
hw->dops.tx_ring_dump(hw, txq);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* DO NOT EDIT THIS FILE!
|
||||
* This file is auto-generated.
|
||||
* Edits to this file will be lost when it is regenerated.
|
||||
* Tool: INTERNAL/drd/instpkgs.pl
|
||||
*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the complete list of supported devices.
|
||||
* No other device lists should be used anywhere in the SDK.
|
||||
*/
|
||||
|
||||
#ifndef BCMDRD_DEVIDS_H
|
||||
#define BCMDRD_DEVIDS_H
|
||||
|
||||
#include <bcmdrd_config.h>
|
||||
|
||||
/*
|
||||
* All Supported Devices and Revisions
|
||||
*/
|
||||
|
||||
#define BROADCOM_VENDOR_ID 0x14e4
|
||||
#define BROADCOM_PHYID_MSB 0x0143
|
||||
|
||||
/* BCM56780 */
|
||||
#define BCM56780_VENDOR_ID 0x14e4
|
||||
#define BCM56780_DEVICE_ID 0xb780
|
||||
#define BCM56780_REV_A0 0x01
|
||||
|
||||
/* BCM56782 */
|
||||
#define BCM56782_VENDOR_ID 0x14e4
|
||||
#define BCM56782_DEVICE_ID 0xb782
|
||||
#define BCM56782_REV_A0 0x01
|
||||
|
||||
/* BCM56784 */
|
||||
#define BCM56784_VENDOR_ID 0x14e4
|
||||
#define BCM56784_DEVICE_ID 0xb784
|
||||
#define BCM56784_REV_A0 0x01
|
||||
|
||||
/* BCM56786 */
|
||||
#define BCM56786_VENDOR_ID 0x14e4
|
||||
#define BCM56786_DEVICE_ID 0xb786
|
||||
#define BCM56786_REV_A0 0x01
|
||||
|
||||
/* BCM56788 */
|
||||
#define BCM56788_VENDOR_ID 0x14e4
|
||||
#define BCM56788_DEVICE_ID 0xb788
|
||||
#define BCM56788_REV_A0 0x01
|
||||
|
||||
/* BCM56789 */
|
||||
#define BCM56789_VENDOR_ID 0x14e4
|
||||
#define BCM56789_DEVICE_ID 0xb789
|
||||
#define BCM56789_REV_A0 0x01
|
||||
|
||||
/* BCM56880 */
|
||||
#define BCM56880_VENDOR_ID 0x14e4
|
||||
#define BCM56880_DEVICE_ID 0xb880
|
||||
#define BCM56880_REV_A0 0x01
|
||||
#define BCM56880_REV_B0 0x11
|
||||
|
||||
/* BCM56881 */
|
||||
#define BCM56881_VENDOR_ID 0x14e4
|
||||
#define BCM56881_DEVICE_ID 0xb881
|
||||
#define BCM56881_REV_A0 0x01
|
||||
#define BCM56881_REV_B0 0x11
|
||||
|
||||
/* BCM56883 */
|
||||
#define BCM56883_VENDOR_ID 0x14e4
|
||||
#define BCM56883_DEVICE_ID 0xb883
|
||||
#define BCM56883_REV_A0 0x01
|
||||
#define BCM56883_REV_B0 0x11
|
||||
|
||||
/* BCM56889 */
|
||||
#define BCM56889_VENDOR_ID 0x14e4
|
||||
#define BCM56889_DEVICE_ID 0xb889
|
||||
#define BCM56889_REV_A0 0x01
|
||||
#define BCM56889_REV_B0 0x11
|
||||
|
||||
/* BCM56990 */
|
||||
#define BCM56990_VENDOR_ID 0x14e4
|
||||
#define BCM56990_DEVICE_ID 0xb990
|
||||
#define BCM56990_REV_A0 0x01
|
||||
#define BCM56990_REV_B0 0x11
|
||||
|
||||
/* BCM56992 */
|
||||
#define BCM56992_VENDOR_ID 0x14e4
|
||||
#define BCM56992_DEVICE_ID 0xb992
|
||||
#define BCM56992_REV_B0 0x11
|
||||
|
||||
/* BCM56996 */
|
||||
#define BCM56996_VENDOR_ID 0x14e4
|
||||
#define BCM56996_DEVICE_ID 0xb996
|
||||
#define BCM56996_REV_A0 0x01
|
||||
|
||||
/* BCM56997 */
|
||||
#define BCM56997_VENDOR_ID 0x14e4
|
||||
#define BCM56997_DEVICE_ID 0xb997
|
||||
#define BCM56997_REV_A0 0x01
|
||||
|
||||
/*
|
||||
* End of Supported Devices and Revisions
|
||||
*/
|
||||
|
||||
#endif /* BCMDRD_DEVIDS_H */
|
||||
|
||||
#ifdef BCMDRD_DEVLIST_ENTRY
|
||||
/*
|
||||
* BCMDRD_DEVLIST_ENTRY macros.
|
||||
*
|
||||
* Before including this file, define BCMDRD_DEVLIST_ENTRY
|
||||
* as a macro to operate on the following parameters:
|
||||
*
|
||||
* #define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1)
|
||||
*
|
||||
* _nm: Chip Name
|
||||
* _vn: Chip Vendor ID
|
||||
* _dv: Chip Device ID
|
||||
* _rv: Chip Revision
|
||||
* _md: Chip Model
|
||||
* _pi: Probe Information
|
||||
* _bd: SW Base Driver
|
||||
* _bc: SW Base Configuration
|
||||
* _fn: SW Full Name
|
||||
* _cn: Code Name
|
||||
* _pf: Product Family
|
||||
* _pd: Product Description
|
||||
* _r0: Reserved
|
||||
* _r1: Reserved
|
||||
*
|
||||
* Note that this macro will be undefined at the end of this file.
|
||||
*/
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56780, BCM56780_VENDOR_ID, BCM56780_DEVICE_ID, BCM56780_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56780_a0, bcm56780_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"8 Tb/s 160x50G-PAM4 Programmable Switch", 0, 0)
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56782, BCM56782_VENDOR_ID, BCM56782_DEVICE_ID, BCM56782_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56782_a0, bcm56782_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56784, BCM56784_VENDOR_ID, BCM56784_DEVICE_ID, BCM56784_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56784_a0, bcm56784_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56786, BCM56786_VENDOR_ID, BCM56786_DEVICE_ID, BCM56786_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56786_a0, bcm56786_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch w/MACsec", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56788, BCM56788_VENDOR_ID, BCM56788_DEVICE_ID, BCM56788_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56788_a0, bcm56788_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec w/MTop", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56789, BCM56789_VENDOR_ID, BCM56789_DEVICE_ID, BCM56789_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56780_a0, bcm56789_a0, bcm56789_a0, \
|
||||
"Trident4-X9", "BCM56780", \
|
||||
"8 Tb/s 160x50G-PAM4 Programmable Switch w/MTop", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56880_a0, bcm56880_a0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56880_a0, bcm56880_b0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56881_a0, bcm56881_a0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56881_a0, bcm56881_b0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56883_a0, bcm56883_a0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56883_a0, bcm56883_b0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56889_a0, bcm56889_a0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56880_a0, bcm56889_a0, bcm56889_b0, \
|
||||
"Trident4", "BCM56880", \
|
||||
"12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56990_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56990_a0, bcm56990_a0, bcm56990_a0, \
|
||||
"Tomahawk4", "BCM56990", \
|
||||
"25.6 Tbps Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56990_b0, bcm56990_b0, bcm56990_b0, \
|
||||
"Tomahawk4", "BCM56990", \
|
||||
"25.6 Tbps Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56992, BCM56992_VENDOR_ID, BCM56992_DEVICE_ID, BCM56992_REV_B0, \
|
||||
0, 0, \
|
||||
bcm56990_b0, bcm56992_b0, bcm56992_b0, \
|
||||
"Tomahawk4", "BCM56990", \
|
||||
"25.6 Tbps Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56996, BCM56996_VENDOR_ID, BCM56996_DEVICE_ID, BCM56996_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56996_a0, bcm56996_a0, bcm56996_a0, \
|
||||
"Tomahawk4G", "BCM56996", \
|
||||
"25.6 Tbps Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE)
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
BCMDRD_DEVLIST_ENTRY(BCM56997, BCM56997_VENDOR_ID, BCM56997_DEVICE_ID, BCM56997_REV_A0, \
|
||||
0, 0, \
|
||||
bcm56996_a0, bcm56997_a0, bcm56997_a0, \
|
||||
"Tomahawk4G", "BCM56996", \
|
||||
"12.8 Tbps Multilayer Switch", 0, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* End BCMDRD_DEVLIST_ENTRY Macros */
|
||||
|
||||
#ifdef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
#undef BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
#endif
|
||||
#ifdef BCMDRD_DEVLIST_OVERRIDE
|
||||
#undef BCMDRD_DEVLIST_OVERRIDE
|
||||
#endif
|
||||
#undef BCMDRD_DEVLIST_ENTRY
|
||||
#endif /* BCMDRD_DEVLIST_ENTRY */
|
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*
|
||||
* DO NOT EDIT THIS FILE!
|
||||
* This file will be auto-generated in the near future.
|
||||
*
|
||||
* This config file defines all compilation-time specifications for
|
||||
* the BCMDRD.
|
||||
*
|
||||
* Reasonable defaults are provided for all configuration options
|
||||
* where appropriate.
|
||||
*
|
||||
* You need not edit this file directly to change your configuration,
|
||||
* nor is modifying this file advised -- so doing will require
|
||||
* manually merging whenever the BCMDRD is upgraded.
|
||||
*
|
||||
* You should provide your own configuration options or overrides
|
||||
* through a combination of:
|
||||
*
|
||||
* 1. The compiler command line, such as -D{OPTION}={VALUE}
|
||||
*
|
||||
* 2. Create your own custom configuration file:
|
||||
* a) Create a file called 'bcmdrd_custom_config.h'
|
||||
* b) Define all custom settings, using this file as
|
||||
* the reference
|
||||
* c) Add -DBCMDRD_INCLUDE_CUSTOM_CONFIG to your
|
||||
* compilation
|
||||
* d) Make sure the compilation include path includes
|
||||
* 'bcmdrd_custom_config.h'
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BCMDRD_CONFIG_H
|
||||
#define BCMDRD_CONFIG_H
|
||||
|
||||
|
||||
/*
|
||||
* Include system config file if specified:
|
||||
*/
|
||||
#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG
|
||||
#include <bcmdrd_custom_config.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* OPTIONAL configuration and feature values.
|
||||
* Defaults are provided for all non-specified values.
|
||||
*/
|
||||
|
||||
/* Maximum number of chips supported */
|
||||
#ifndef BCMDRD_CONFIG_MAX_UNITS
|
||||
#define BCMDRD_CONFIG_MAX_UNITS 8
|
||||
#endif
|
||||
|
||||
/* Maximum number of ports per chip supported */
|
||||
#ifndef BCMDRD_CONFIG_MAX_PORTS
|
||||
#define BCMDRD_CONFIG_MAX_PORTS 576
|
||||
#endif
|
||||
|
||||
/* Maximum number of SCHAN polls */
|
||||
#ifndef BCMDRD_CONFIG_SCHAN_MAX_POLLS
|
||||
#define BCMDRD_CONFIG_SCHAN_MAX_POLLS 100000
|
||||
#endif
|
||||
|
||||
/* Maximum number of MIIM polls */
|
||||
#ifndef BCMDRD_CONFIG_MIIM_MAX_POLLS
|
||||
#define BCMDRD_CONFIG_MIIM_MAX_POLLS 100000
|
||||
#endif
|
||||
|
||||
/* Direct access to memory-mapped registers */
|
||||
#ifndef BCMDRD_CONFIG_MEMMAP_DIRECT
|
||||
#define BCMDRD_CONFIG_MEMMAP_DIRECT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include chip symbol tables for the debug shell.
|
||||
*
|
||||
* No symbolic debugging (register/memory names) will be available
|
||||
* without this defined.
|
||||
*
|
||||
* You should enable at least these symbols if you can afford the
|
||||
* space.
|
||||
*
|
||||
* This define is required to get any symbols at all.
|
||||
*
|
||||
* If you only wish to include symbols for a subset of chips in the
|
||||
* system (probably for code space reasons), you can define the
|
||||
* following for each chip whose symbols you wish to EXCLUDE:
|
||||
*
|
||||
* BCMDRD_CONFIG_EXCLUDE_CHIP_SYMBOLS_<CHIP>
|
||||
*
|
||||
*/
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS
|
||||
#define BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include register and memory field information for the debug shell.
|
||||
*
|
||||
* This provides encoding, decoding, and displaying individual field
|
||||
* values for each register and memory.
|
||||
*
|
||||
* Requires more code space than just the chip symbols alone.
|
||||
*
|
||||
* The per-chip exclusion define
|
||||
* (BCMDRD_CONFIG_EXCLUDE_FIELD_INFO_<CHIP>) also applies.
|
||||
*/
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_FIELD_INFO
|
||||
#define BCMDRD_CONFIG_INCLUDE_FIELD_INFO 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include alternative symbol names for registers and memories.
|
||||
*
|
||||
* Mainly for internal Broadcom use, so you can safely leave this
|
||||
* option off.
|
||||
*/
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES
|
||||
#define BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES 1
|
||||
#endif
|
||||
|
||||
#endif /* BCMDRD_CONFIG_H */
|
||||
|
||||
#ifdef CONFIG_OPTION
|
||||
#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG
|
||||
CONFIG_OPTION(BCMDRD_INCLUDE_CUSTOM_CONFIG)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_MAX_UNITS
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_MAX_UNITS)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_MAX_PORTS
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_MAX_PORTS)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_SCHAN_MAX_POLLS
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_SCHAN_MAX_POLLS)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_MIIM_MAX_POLLS
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_MIIM_MAX_POLLS)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_MEMMAP_DIRECT
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_MEMMAP_DIRECT)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_FIELD_INFO
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_FIELD_INFO)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES)
|
||||
#endif
|
||||
#endif /* CONFIG_OPTION */
|
||||
#include "bcmdrd_config_chips.h"
|
@ -0,0 +1,545 @@
|
||||
/*
|
||||
* DO NOT EDIT THIS FILE!
|
||||
* This file is auto-generated.
|
||||
* Edits to this file will be lost when it is regenerated.
|
||||
* Tool: INTERNAL/drd/instpkgs.pl
|
||||
*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Chip inclusion and exclusion support within the BCMDRD can be
|
||||
* specified as a combination of the following defines:
|
||||
*
|
||||
* (1) #define BCMDRD_CONFIG_INCLUDE_<CHIPNAME> [1|0]
|
||||
* -- Include or exclude all revisions of the given device
|
||||
* Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780 1
|
||||
*
|
||||
* (2) #define BCMDRD_CONFIG_INCLUDE_<CHIPNAME>_<REV>X [1|0]
|
||||
* -- Include or exclude all versions of the given revision
|
||||
* Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax 0
|
||||
* #define BCMDRD_CONFIG_INCLUde_BCM56780_Bx 1
|
||||
*
|
||||
* (3) #define BCMDRD_CONFIG_INCLUDE_<EXACT_CHIP> [1|0]
|
||||
* -- Include or exclude an exact device
|
||||
* Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
* #define BCMDRD_CONFIG_INCLUDE_BCM56780_A1 0
|
||||
*
|
||||
*
|
||||
* The value of BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT is used for any
|
||||
* chips which are left unspecified. Set this value to 1 or 0 to
|
||||
* include or exclude all chips by default.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BCMDRD_CONFIG_CHIPS_H
|
||||
#define BCMDRD_CONFIG_CHIPS_H
|
||||
|
||||
/* This determines whether a chip is included or excluded by default */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#define BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Default configuration and dependencies for all chips
|
||||
*/
|
||||
|
||||
/*
|
||||
* BCM56780
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax BCMDRD_CONFIG_INCLUDE_BCM56780
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_BCM56780_Ax
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56782
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56782 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56782_Ax BCMDRD_CONFIG_INCLUDE_BCM56782
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56782_A0 BCMDRD_CONFIG_INCLUDE_BCM56782_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56784
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56784 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56784_Ax BCMDRD_CONFIG_INCLUDE_BCM56784
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56784_A0 BCMDRD_CONFIG_INCLUDE_BCM56784_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56786
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56786 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56786_Ax BCMDRD_CONFIG_INCLUDE_BCM56786
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56786_A0 BCMDRD_CONFIG_INCLUDE_BCM56786_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56788
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56788 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56788_Ax BCMDRD_CONFIG_INCLUDE_BCM56788
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56788_A0 BCMDRD_CONFIG_INCLUDE_BCM56788_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56789
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56789 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56789_Ax BCMDRD_CONFIG_INCLUDE_BCM56789
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56789_A0 BCMDRD_CONFIG_INCLUDE_BCM56789_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56880
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_Ax BCMDRD_CONFIG_INCLUDE_BCM56880
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_BCM56880_Ax
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_Bx BCMDRD_CONFIG_INCLUDE_BCM56880
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_B0 BCMDRD_CONFIG_INCLUDE_BCM56880_Bx
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56881
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56881 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56881_Ax BCMDRD_CONFIG_INCLUDE_BCM56881
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56881_A0 BCMDRD_CONFIG_INCLUDE_BCM56881_Ax
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56881_Bx BCMDRD_CONFIG_INCLUDE_BCM56881
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56881_B0 BCMDRD_CONFIG_INCLUDE_BCM56881_Bx
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56883
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56883 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56883_Ax BCMDRD_CONFIG_INCLUDE_BCM56883
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56883_A0 BCMDRD_CONFIG_INCLUDE_BCM56883_Ax
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56883_Bx BCMDRD_CONFIG_INCLUDE_BCM56883
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56883_B0 BCMDRD_CONFIG_INCLUDE_BCM56883_Bx
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56889
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56889 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56889_Ax BCMDRD_CONFIG_INCLUDE_BCM56889
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56889_A0 BCMDRD_CONFIG_INCLUDE_BCM56889_Ax
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56889_Bx BCMDRD_CONFIG_INCLUDE_BCM56889
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56889_B0 BCMDRD_CONFIG_INCLUDE_BCM56889_Bx
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56990
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_Ax BCMDRD_CONFIG_INCLUDE_BCM56990
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_A0 BCMDRD_CONFIG_INCLUDE_BCM56990_Ax
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_Bx BCMDRD_CONFIG_INCLUDE_BCM56990
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_BCM56990_Bx
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56992
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56992 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_Bx
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56992_Bx BCMDRD_CONFIG_INCLUDE_BCM56992
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56992_B0 BCMDRD_CONFIG_INCLUDE_BCM56992_Bx
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56990_B0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56996
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996_Ax BCMDRD_CONFIG_INCLUDE_BCM56996
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_BCM56996_Ax
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* BCM56997
|
||||
*/
|
||||
|
||||
/* Sets the default include state if it was not given */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56997 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
/* Resolve revision dependencies */
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_Ax
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56997_Ax BCMDRD_CONFIG_INCLUDE_BCM56997
|
||||
#endif
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56997_A0 BCMDRD_CONFIG_INCLUDE_BCM56997_Ax
|
||||
#endif
|
||||
/* Resolve all interchip dependencies */
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1
|
||||
#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT
|
||||
#endif
|
||||
#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 != 1
|
||||
#undef BCMDRD_CONFIG_INCLUDE_BCM56996_A0
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 1
|
||||
#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* BCMDRD_CONFIG_CHIPS_H */
|
||||
|
||||
/*
|
||||
* CONFIG_OPTION Macros. Can be used to determine the build configuration.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_OPTION
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0)
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED)
|
||||
#endif
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_B0)
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED)
|
||||
#endif
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_B0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_B0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_B0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0)
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED)
|
||||
#endif
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED)
|
||||
#endif
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_Bx)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_B0)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0)
|
||||
#ifdef BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED)
|
||||
#endif
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_Ax)
|
||||
CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_A0)
|
||||
#undef CONFIG_OPTION
|
||||
#endif /* #ifdef CONFIG_OPTION */
|
39
platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild
Normal file
39
platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- Kbuild -*-
|
||||
#
|
||||
# Linux kernel BDE module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
obj-m := linux_ngbde.o
|
||||
|
||||
ccflags-y := $(LKM_CFLAGS) \
|
||||
-I$(SDK)/linux/include \
|
||||
-I$(SDK)/linux/bde \
|
||||
-I$(SDK)/bcmdrd/include
|
||||
|
||||
linux_ngbde-y := ngbde_main.o \
|
||||
ngbde_kapi.o \
|
||||
ngbde_ioctl.o \
|
||||
ngbde_procfs.o \
|
||||
ngbde_pio.o \
|
||||
ngbde_iio.o \
|
||||
ngbde_dma.o \
|
||||
ngbde_intr.o \
|
||||
ngbde_pgmem.o \
|
||||
ngbde_pci_probe.o \
|
||||
ngbde_iproc_probe.o \
|
||||
ngbde_swdev.o
|
33
platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile
Normal file
33
platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- Makefile -*-
|
||||
#
|
||||
# Linux kernel BDE module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
include Kbuild
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
MOD_NAME = linux_ngbde
|
||||
|
||||
include $(SDK)/make/lkm.mk
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: distclean
|
||||
|
||||
distclean:
|
836
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h
Normal file
836
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h
Normal file
@ -0,0 +1,836 @@
|
||||
/*! \file ngbde.h
|
||||
*
|
||||
* Shared definitions and APIs for NGBDE kernel module.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGBDE_H
|
||||
#define NGBDE_H
|
||||
|
||||
#include <lkm/lkm.h>
|
||||
#include <lkm/ngbde_kapi.h>
|
||||
|
||||
/*! Module name. */
|
||||
#define MOD_NAME "linux_ngbde"
|
||||
|
||||
/*! Major number for associated charcter device file. */
|
||||
#define MOD_MAJOR 120
|
||||
|
||||
/*! Read memory-mapped device register without byte-swap. */
|
||||
#define NGBDE_IOREAD32(_a) __raw_readl(_a)
|
||||
|
||||
/*! Write memory-mapped device register without byte-swap. */
|
||||
#define NGBDE_IOWRITE32(_v, _a) __raw_writel(_v, _a)
|
||||
|
||||
/*! Maximum number of I/O windows supported per device. */
|
||||
#define NGBDE_NUM_IOWIN_MAX 3
|
||||
|
||||
/*! Maximum number of DMA memory pools supported per device. */
|
||||
#define NGBDE_NUM_DMAPOOL_MAX 2
|
||||
|
||||
/*! Maximum number of IRQ status registers per interrupt source. */
|
||||
#define NGBDE_NUM_IRQ_REGS_MAX 16
|
||||
|
||||
/*! Maximum number of IRQ lines (MSI vectors) per device. */
|
||||
#define NGBDE_NUM_IRQS_MAX 1
|
||||
|
||||
/*!
|
||||
* Maximum number of interrupt controller registers which may be
|
||||
* written from both a user mode driver and a kernel mode driver.
|
||||
*
|
||||
* This feature is used when the kernel mode driver owns a subset of
|
||||
* bits within a register, which is also used by the user mode driver.
|
||||
*
|
||||
* Both drivers must access such registers through a lock-protected
|
||||
* access function.
|
||||
*/
|
||||
#define NGBDE_NUM_INTR_SHR_REGS_MAX 1
|
||||
|
||||
/*! I/O memory window definition. */
|
||||
struct ngbde_memwin_s {
|
||||
|
||||
/*! Physical address of I/O window. */
|
||||
phys_addr_t addr;
|
||||
|
||||
/*! Size of I/O window (in bytes). */
|
||||
phys_addr_t size;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Shared register value.
|
||||
*
|
||||
* This structure contains the current value of a register where user
|
||||
* mode and kernel mode owns different bits within the same
|
||||
* register. In this case access must be carefully controlled to avoid
|
||||
* that one context overwrites the bits owned by the other context.
|
||||
*
|
||||
* The structure also contains the offset of the shared register in
|
||||
* order to identify the register (in case there is more than one
|
||||
* shared register).
|
||||
*/
|
||||
typedef struct ngbde_shr_reg_s {
|
||||
|
||||
/*! Offset of the shared register. */
|
||||
uint32_t reg_offs;
|
||||
|
||||
/*! Current value of the shared register. */
|
||||
uint32_t cur_val;
|
||||
|
||||
} ngbde_shr_reg_t;
|
||||
|
||||
/*!
|
||||
* \brief Shared interrupt mask register control.
|
||||
*
|
||||
* This defines which bits of an interrupt mask register are owned by
|
||||
* user mode context, and which are owned by kernel context.
|
||||
*
|
||||
* The structure contains the corresponding interrupt status register
|
||||
* in order to allow identification of the interrupt mask register
|
||||
* irrespective of the host CPU being used.
|
||||
*
|
||||
* For example, if the host CPU is connected via PCI, then we use one
|
||||
* mask register, but if the host CPU is an embedded ARM CPU, then we
|
||||
* use a different mask register (for the same interrupt status
|
||||
* register). By using the status register to identify the shared mask
|
||||
* register, the kernel mode driver does not need to know which host
|
||||
* CPU it is running off.
|
||||
*/
|
||||
typedef struct ngbde_irq_reg_s {
|
||||
|
||||
/*! Interrupt status register corresponding to the mask register. */
|
||||
uint32_t status_reg;
|
||||
|
||||
/*! Shared interrupt mask register. */
|
||||
uint32_t mask_reg;
|
||||
|
||||
/*! Mask identifying the register bits owned by the kernel mode driver. */
|
||||
uint32_t kmask;
|
||||
|
||||
} ngbde_irq_reg_t;
|
||||
|
||||
/*!
|
||||
* \name Interrupt ACK register access flags.
|
||||
* \anchor NGBDE_INTR_ACK_F_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! ACK registers resides in PCI bridge I/O window. */
|
||||
#define NGBDE_INTR_ACK_F_PAXB (1 << 0)
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \brief Interrupt ACK register control.
|
||||
*
|
||||
* The structure contains the corresponding register offset
|
||||
* and value in order to acknowledge interrupt in kernel driver.
|
||||
*
|
||||
* For example, if the host CPU is connected via PCI, then we use one
|
||||
* ACK register, but if the host CPU is an embedded ARM CPU, then we
|
||||
* use a different ACK register.
|
||||
*/
|
||||
typedef struct ngbde_intr_ack_reg_s {
|
||||
|
||||
/*! Ack register offset. */
|
||||
uint32_t ack_reg;
|
||||
|
||||
/*! Ack value. */
|
||||
uint32_t ack_val;
|
||||
|
||||
/*! Flags to indicate ack_reg resides in PCI bridge window. */
|
||||
uint32_t flags;
|
||||
|
||||
} ngbde_intr_ack_reg_t;
|
||||
|
||||
/*!
|
||||
* \brief BDE interrupt handler.
|
||||
*
|
||||
* The BDE will use a function of this type to register an interrupt
|
||||
* handler with the Linux kernel.
|
||||
*
|
||||
* \param [in] data Interrupt handler context.
|
||||
*
|
||||
* \retval 0 Interrupt not recognized.
|
||||
* \retval 1 Interrupt recognized and handled.
|
||||
*/
|
||||
typedef int (*ngbde_isr_f)(void *data);
|
||||
|
||||
/*!
|
||||
* \brief Kernel interrupt control.
|
||||
*
|
||||
* This structure controls the sharing of interrupt processing between
|
||||
* a user mode thread and a kernel mode interrupt handler.
|
||||
*/
|
||||
typedef struct ngbde_intr_ctrl_s {
|
||||
|
||||
/*! Handle for device I/O (for writing interrupt registers). */
|
||||
uint8_t *iomem;
|
||||
|
||||
/*! Kernel device number (similar to user mode unit number). */
|
||||
int kdev;
|
||||
|
||||
/*! Indicates that our interrupt handler is connected to the kernel. */
|
||||
int irq_active;
|
||||
|
||||
/*! Interrupt number (IRQ# or MSI vector). */
|
||||
int irq_vect;
|
||||
|
||||
/*! Number of interrupt status/mask register pairs. */
|
||||
int num_regs;
|
||||
|
||||
/*! Interrupt status/mask register pairs for this device. */
|
||||
ngbde_irq_reg_t regs[NGBDE_NUM_IRQ_REGS_MAX];
|
||||
|
||||
/*! Interrupt ACK register/value for this device. */
|
||||
ngbde_intr_ack_reg_t intr_ack;
|
||||
|
||||
/*! Wait queue for user mode interrupt thread. */
|
||||
wait_queue_head_t user_thread_wq;
|
||||
|
||||
/*! Flag to wake up user mode interrupt thread. */
|
||||
atomic_t run_user_thread;
|
||||
|
||||
/*! Primary interrupt handler. */
|
||||
ngbde_isr_f isr_func;
|
||||
|
||||
/*! Context for primary interrupt handler. */
|
||||
void *isr_data;
|
||||
|
||||
} ngbde_intr_ctrl_t;
|
||||
|
||||
/*! Convenience macro for 1 kilobyte. */
|
||||
#define ONE_KB 1024
|
||||
|
||||
/*! Convenience macro for 1 megabyte. */
|
||||
#define ONE_MB (1024*1024)
|
||||
|
||||
/*!
|
||||
* \name DMA allocation types.
|
||||
* \anchor NGBDE_DMA_T_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*!
|
||||
* Do not allocate any DMA memory.
|
||||
*/
|
||||
#define NGBDE_DMA_T_NONE 0
|
||||
|
||||
/*!
|
||||
* Try different allocation methods until DMA memory is successfully
|
||||
* allocated.
|
||||
*/
|
||||
#define NGBDE_DMA_T_AUTO 1
|
||||
|
||||
/*! Use kernel DMA API (dma_alloc_coherent). */
|
||||
#define NGBDE_DMA_T_KAPI 2
|
||||
|
||||
/*! Use page allocator and map to physical address manually. */
|
||||
#define NGBDE_DMA_T_PGMEM 3
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*! DMA memory allocation control structure. */
|
||||
typedef struct ngbde_dmactrl_s {
|
||||
|
||||
/*! Requested size of DMA memory block (in bytes). */
|
||||
size_t size;
|
||||
|
||||
/*! Kernel flags for memory allocation. */
|
||||
gfp_t flags;
|
||||
|
||||
/*! Preferred DMA memory type (NGBDE_DMA_T_xxx). */
|
||||
int pref_type;
|
||||
|
||||
/*! Kernel device for DMA memory management. */
|
||||
struct device *dev;
|
||||
|
||||
} ngbde_dmactrl_t;
|
||||
|
||||
/*! DMA memory descriptor. */
|
||||
typedef struct ngbde_dmamem_s {
|
||||
|
||||
/*! Logical address of DMA memory block. */
|
||||
void *vaddr;
|
||||
|
||||
/*! Physical address of DMA memory block. */
|
||||
dma_addr_t paddr;
|
||||
|
||||
/*! Bus address of DMA memory block. */
|
||||
dma_addr_t baddr;
|
||||
|
||||
/*! Actual size of DMA memory block (in bytes). */
|
||||
size_t size;
|
||||
|
||||
/*! Actual DMA memory type (NGBDE_DMA_T_xxx). */
|
||||
int type;
|
||||
|
||||
/*! Kernel device for DMA memory management. */
|
||||
struct device *dev;
|
||||
|
||||
} ngbde_dmamem_t;
|
||||
|
||||
/*! DMA memory pool. */
|
||||
typedef struct ngbde_dmapool_s {
|
||||
|
||||
/*! DMA control parameters. */
|
||||
struct ngbde_dmactrl_s dmactrl;
|
||||
|
||||
/*! DMA memory resources. */
|
||||
struct ngbde_dmamem_s dmamem;
|
||||
|
||||
} ngbde_dmapool_t;
|
||||
|
||||
/*! Switch device descriptor. */
|
||||
struct ngbde_dev_s {
|
||||
|
||||
/*! Vendor ID (typically PCI vendor ID). */
|
||||
uint16_t vendor_id;
|
||||
|
||||
/*! Device ID (typically PCI device ID). */
|
||||
uint16_t device_id;
|
||||
|
||||
/*! Device revision (typically PCI revision). */
|
||||
uint16_t revision;
|
||||
|
||||
/*! Additional device identification when primary ID is not unique. */
|
||||
uint16_t model;
|
||||
|
||||
/*! Bus number (typically PCI bus number). */
|
||||
int bus_no;
|
||||
|
||||
/*! Slot number (typically PCI slot number). */
|
||||
int slot_no;
|
||||
|
||||
/*! Interrupt line associated with this device. */
|
||||
int irq_line;
|
||||
|
||||
/*! Use MSI interrupts with this device. */
|
||||
int use_msi;
|
||||
|
||||
/*! Non-zero if device was removed. */
|
||||
int inactive;
|
||||
|
||||
/*! Physical I/O window for kernel driver device access. */
|
||||
struct ngbde_memwin_s pio_win;
|
||||
|
||||
/*! Memory mapped I/O window for kernel driver device access. */
|
||||
uint8_t *pio_mem;
|
||||
|
||||
/*! Physical I/O window for interrupt controller access. */
|
||||
struct ngbde_memwin_s iio_win;
|
||||
|
||||
/*! Memory mapped I/O window for interrupt controller access. */
|
||||
uint8_t *iio_mem;
|
||||
|
||||
/*! Physical I/O window for device PCI bridge access. */
|
||||
struct ngbde_memwin_s paxb_win;
|
||||
|
||||
/*! Memory mapped I/O window for device PCI bridge access. */
|
||||
uint8_t *paxb_mem;
|
||||
|
||||
/*! Current value of shared register (typically an IRQ mask register). */
|
||||
struct ngbde_shr_reg_s intr_shr_reg[NGBDE_NUM_INTR_SHR_REGS_MAX];
|
||||
|
||||
/*! Lock for shared register synchronization. */
|
||||
spinlock_t lock;
|
||||
|
||||
/*! Interrupt control information. */
|
||||
struct ngbde_intr_ctrl_s intr_ctrl[NGBDE_NUM_IRQS_MAX];
|
||||
|
||||
/*! Linux PCI handle. */
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
/*! Kernel device for DMA memory management. */
|
||||
struct device *dma_dev;
|
||||
|
||||
/*! Physical device I/O. */
|
||||
struct ngbde_memwin_s iowin[NGBDE_NUM_IOWIN_MAX];
|
||||
|
||||
/*! DMA memory pools. */
|
||||
struct ngbde_dmapool_s dmapool[NGBDE_NUM_DMAPOOL_MAX];
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Linux IOCTL handler.
|
||||
*
|
||||
* This function handles communication between user mode and kernel
|
||||
* mode.
|
||||
*
|
||||
* \param [in] file Device file handle.
|
||||
* \param [in] cmd IOCTL command.
|
||||
* \param [in] arg IOCTL command argument.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
*/
|
||||
extern long
|
||||
ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
|
||||
/*!
|
||||
* \brief Initialize procfs for BDE driver.
|
||||
*
|
||||
* Create procfs read interface for dumping probe information.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_procfs_init(void);
|
||||
|
||||
/*!
|
||||
* \brief Clean up procfs for BDE driver.
|
||||
*
|
||||
* Clean up resources allocated by \ref ngbde_procfs_init.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_procfs_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Allocate DMA memory pools for all probed devices.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_dma_init(void);
|
||||
|
||||
/*!
|
||||
* \brief Free DMA memory pools for all probed devices.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_dma_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Connect to hardware interrupt handler.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_connect(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Disconnect from hardware interrupt handler.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_disconnect(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Disconnect from all hardware interrupt handlers.
|
||||
*/
|
||||
void
|
||||
ngbde_intr_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Wait for hardware interrupt.
|
||||
*
|
||||
* A user mode thread will call this function and sleep until a
|
||||
* hardware interrupt occurs.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_wait(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Wake up sleeping interrupt thread.
|
||||
*
|
||||
* Wake up interrupt thread even if no interrupt has occurred.
|
||||
*
|
||||
* Intended for graceful shut-down procedure.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_stop(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Clear list of interrupt status/mask registers.
|
||||
*
|
||||
* This function is typically called before new interrupt register
|
||||
* information is added.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_regs_clr(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Add interrupt status/mask register to monitor.
|
||||
*
|
||||
* This function adds a new interrupt status/mask register set to the
|
||||
* list of registers monitored by the user-mode interrupt handler.
|
||||
*
|
||||
* The register list is used to determine whether a user-mode
|
||||
* interrupt has occurred.
|
||||
*
|
||||
* See also \ref ngbde_intr_regs_clr.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
* \param [in] ireg Interrupt status/mask register information.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_reg_add(int kdev, unsigned int irq_num,
|
||||
struct ngbde_irq_reg_s *ireg);
|
||||
|
||||
/*!
|
||||
* \brief Add interrupt ack register to monitor.
|
||||
*
|
||||
* This function adds a interrupt register and mask value
|
||||
* to acknowledge corresponding irq_num.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
* \param [in] ackreg Interrupt ack register information.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num,
|
||||
struct ngbde_intr_ack_reg_s *ackreg);
|
||||
|
||||
/*!
|
||||
* \brief Write shared interrupt mask register.
|
||||
*
|
||||
* This function is used by an interrupt handler when a shared
|
||||
* interrupt mask register needs to be updated.
|
||||
*
|
||||
* Since the register is shared between multiple interrupt handlers,
|
||||
* access must be protected by a lock.
|
||||
*
|
||||
* The register information provided via \ref ngbde_intr_reg_add is
|
||||
* used to detemine which bits of the mask register belong to the user
|
||||
* mode driver.
|
||||
*
|
||||
* Note that the mask register to access is referenced by the
|
||||
* corresponding status register. This is because the mask register
|
||||
* may be different depending on the host CPU interface being used
|
||||
* (e.g. PCI vs. AXI). On the other hand, the status register is the
|
||||
* same irrespective of the host CPU interface.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
* \param [in] kapi Must be set to 1 if called from kernel API.
|
||||
* \param [in] status_reg Corresponding interrupt status register offset.
|
||||
* \param [in] mask_val New value to write to mask register.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi,
|
||||
uint32_t status_reg, uint32_t mask_val);
|
||||
|
||||
/*!
|
||||
* \brief Probe for PCI-attached Broadcom switch devices.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_pci_probe(void);
|
||||
|
||||
/*!
|
||||
* \brief Clean up resources for PCI-attached Broadcom switch devices.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_pci_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Add new switch device to BDE database.
|
||||
*
|
||||
* Add device information for probed or fixed switch device.
|
||||
*
|
||||
* \param [in] nd Switch device information.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_swdev_add(struct ngbde_dev_s *nd);
|
||||
|
||||
/*!
|
||||
* \brief Get device information for a BDE switch device.
|
||||
*
|
||||
* \param [in] kdev Switch device number.
|
||||
*
|
||||
* \return Pointer to switch device structure or NULL on error.
|
||||
*/
|
||||
struct ngbde_dev_s *
|
||||
ngbde_swdev_get(int kdev);
|
||||
|
||||
/*!
|
||||
* \brief Get list of all probed switch devices.
|
||||
*
|
||||
* Return a pointer to the array of registered switch devices.
|
||||
*
|
||||
* \param [out] nd Pointer to array of switch devices.
|
||||
* \param [in] num_nd number of valid entries in switch device array.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
*/
|
||||
extern int
|
||||
ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd);
|
||||
|
||||
/*!
|
||||
* \brief Allocate memory using page allocator
|
||||
*
|
||||
* For any sizes less than MEM_CHUNK_SIZE, we ask the page allocator
|
||||
* for the entire memory block, otherwise we try to assemble a
|
||||
* contiguous cmblock ourselves.
|
||||
*
|
||||
* Upon successful allocation, the memory block will be added to the
|
||||
* global list of allocated memory blocks.
|
||||
*
|
||||
* \param [in] size Number of bytes to allocate.
|
||||
* \param [in] flags Kernel flags (GFP_xxx) for memory allocation.
|
||||
*
|
||||
* \return Pointer to allocated memory or NULL if failure.
|
||||
*/
|
||||
void *
|
||||
ngbde_pgmem_alloc(size_t size, gfp_t flags);
|
||||
|
||||
/*!
|
||||
* \brief Free memory block allocated by ngbde_pgmem_alloc.
|
||||
*
|
||||
* \param [in] ptr Pointer returned by ngbde_pgmem_alloc.
|
||||
*
|
||||
* \return 0 if succesfully freed, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_pgmem_free(void *ptr);
|
||||
|
||||
/*!
|
||||
* \brief Free all memory blocks allocated by ngbde_pgmem_alloc.
|
||||
*
|
||||
* This function will walk the global list of allocated memory blocks
|
||||
* and free all associated resources.
|
||||
*
|
||||
* Intended for a full clean up before the module is unloaded.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_pgmem_free_all(void);
|
||||
|
||||
/*!
|
||||
* \brief Map I/O memory in kernel driver.
|
||||
*
|
||||
* This function is used to provide device I/O access to a kernel mode
|
||||
* driver.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] addr Physical address to map.
|
||||
* \param [in] size Size of I/O window to map.
|
||||
*
|
||||
* \return Pointer to mapped I/O memory, or NULL on error.
|
||||
*/
|
||||
extern void *
|
||||
ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size);
|
||||
|
||||
/*!
|
||||
* \brief Unmap I/O memory in kernel driver.
|
||||
*
|
||||
* Unmap I/O memory previously mapped via \ref ngbde_pio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_pio_unmap(void *devh);
|
||||
|
||||
/*!
|
||||
* \brief Unmap all I/O windows.
|
||||
*/
|
||||
extern void
|
||||
ngbde_pio_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Write a memory-mapped register from kernel driver.
|
||||
*
|
||||
* Write a 32-bit register using I/O memory previously mapped via \ref
|
||||
* ngbde_pio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] offs Register address offset.
|
||||
* \param [in] val Value to write to register.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val);
|
||||
|
||||
/*!
|
||||
* \brief Read a memory-mapped register from kernel driver.
|
||||
*
|
||||
* Read a 32-bit register using I/O memory previously mapped via \ref
|
||||
* ngbde_pio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] offs Register address offset.
|
||||
*
|
||||
* \return Value read from register.
|
||||
*/
|
||||
extern uint32_t
|
||||
ngbde_pio_read32(void *devh, uint32_t offs);
|
||||
|
||||
/*!
|
||||
* \brief Map interrupt controller I/O memory.
|
||||
*
|
||||
* On some devices the interrupt controller is a device separate from
|
||||
* the main switch device. This function is used to provide interrupt
|
||||
* controller I/O access to a kernel mode driver.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] addr Physical address to map.
|
||||
* \param [in] size Size of I/O window to map.
|
||||
*
|
||||
* \return Pointer to mapped I/O memory, or NULL on error.
|
||||
*/
|
||||
extern void *
|
||||
ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size);
|
||||
|
||||
/*!
|
||||
* \brief Unmap interrupt controller I/O memory.
|
||||
*
|
||||
* Unmap I/O memory previously mapped via \ref ngbde_iio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_iio_unmap(void *devh);
|
||||
|
||||
/*!
|
||||
* \brief Unmap all interrupt controller I/O windows.
|
||||
*/
|
||||
extern void
|
||||
ngbde_iio_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Write a memory-mapped interrupt controller register.
|
||||
*
|
||||
* Write a 32-bit register using I/O memory previously mapped via \ref
|
||||
* ngbde_iio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] offs Register address offset.
|
||||
* \param [in] val Value to write to register.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val);
|
||||
|
||||
/*!
|
||||
* \brief Read a memory-mapped interrupt controller register.
|
||||
*
|
||||
* Read a 32-bit register using I/O memory previously mapped via \ref
|
||||
* ngbde_iio_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] offs Register address offset.
|
||||
*
|
||||
* \return Value read from register.
|
||||
*/
|
||||
extern uint32_t
|
||||
ngbde_iio_read32(void *devh, uint32_t offs);
|
||||
|
||||
/*!
|
||||
* \brief Map PCI bridge I/O memory.
|
||||
*
|
||||
* On some devices the interrupt controller is a device separate from
|
||||
* the main switch device. This function is used to provide interrupt
|
||||
* controller I/O access to a kernel mode driver.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
* \param [in] addr Physical address to map.
|
||||
* \param [in] size Size of I/O window to map.
|
||||
*
|
||||
* \return Pointer to mapped I/O memory, or NULL on error.
|
||||
*/
|
||||
extern void *
|
||||
ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size);
|
||||
|
||||
/*!
|
||||
* \brief Unmap PCI bridge I/O memory.
|
||||
*
|
||||
* Unmap I/O memory previously mapped via \ref ngbde_paxb_map.
|
||||
*
|
||||
* \param [in] devh Device handle (\ref ngbde_dev_s).
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_paxb_unmap(void *devh);
|
||||
|
||||
/*!
|
||||
* \brief Unmap all PCI bridge I/O windows.
|
||||
*/
|
||||
extern void
|
||||
ngbde_paxb_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Probe for Broadcom switch devices on IPROC internal bus.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_iproc_probe(void);
|
||||
|
||||
/*!
|
||||
* \brief Clean up resources for Broadcom switch devices on IPROC internal bus.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngbde_iproc_cleanup(void);
|
||||
|
||||
#endif /* NGBDE_H */
|
340
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c
Normal file
340
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*! \file ngbde_dma.c
|
||||
*
|
||||
* This module handles allocation of DMA memory pools.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
/*! \cond */
|
||||
static int dma_debug = 0;
|
||||
module_param(dma_debug, int, 0);
|
||||
MODULE_PARM_DESC(dma_debug,
|
||||
"DMA debug output enable (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
/*! Default size of of DMA memory pools (in MB). */
|
||||
#define DMAPOOL_SIZE_DEFAULT 16
|
||||
|
||||
/*! Default number of DMA memory pools per device. */
|
||||
#define NUM_DMAPOOL_DEFAULT 1
|
||||
|
||||
/*! \cond */
|
||||
static int dma_size = DMAPOOL_SIZE_DEFAULT;
|
||||
module_param(dma_size, int, 0);
|
||||
MODULE_PARM_DESC(dma_size,
|
||||
"Size of of DMA memory pools in MB (default 16 MB).");
|
||||
/*! \endcond */
|
||||
|
||||
/*! \cond */
|
||||
static char *dma_alloc;
|
||||
module_param(dma_alloc, charp, 0);
|
||||
MODULE_PARM_DESC(dma_alloc,
|
||||
"DMA allocation method auto|kapi|pgmem (default auto)");
|
||||
/*! \endcond */
|
||||
|
||||
/*! \cond */
|
||||
static int dma_pools = NUM_DMAPOOL_DEFAULT;
|
||||
module_param(dma_pools, int, 0);
|
||||
MODULE_PARM_DESC(dma_pools,
|
||||
"Number of DMA memory pools to pre-allocate per device (default 1).");
|
||||
/*! \endcond */
|
||||
|
||||
/*!
|
||||
* \brief Allocate DMA memory via kernel API.
|
||||
*
|
||||
* \param [in] dmactrl DMA allocation control.
|
||||
* \param [out] dmamem DMA allocation result.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
static void
|
||||
ngbde_dmamem_kapi_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem)
|
||||
{
|
||||
void *vaddr;
|
||||
dma_addr_t baddr;
|
||||
|
||||
vaddr = dma_alloc_coherent(dmactrl->dev, dmactrl->size, &baddr,
|
||||
dmactrl->flags);
|
||||
if (vaddr) {
|
||||
/* Store allocation information in dmamem structure */
|
||||
dmamem->vaddr = vaddr;
|
||||
dmamem->paddr = virt_to_phys(vaddr);
|
||||
dmamem->dev = dmactrl->dev;
|
||||
dmamem->size = dmactrl->size;
|
||||
dmamem->type = NGBDE_DMA_T_KAPI;
|
||||
dmamem->baddr = baddr;
|
||||
|
||||
/* Write small signature for debug purposes */
|
||||
strcpy((char *)vaddr, "DMA_KAPI");
|
||||
|
||||
if (dma_debug) {
|
||||
printk("DMA: Allocated %d KB of KAPI memory at 0x%08lx\n",
|
||||
(int)(dmamem->size / ONE_KB),
|
||||
(unsigned long)dmamem->paddr);
|
||||
}
|
||||
} else {
|
||||
if (dma_debug) {
|
||||
printk("DMA: Failed to allocate KAPI memory\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Allocate DMA memory via page allocator.
|
||||
*
|
||||
* \param [in] dmactrl DMA allocation control.
|
||||
* \param [out] dmamem DMA allocation result.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
static void
|
||||
ngbde_dmamem_pgmem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
vaddr = ngbde_pgmem_alloc(dmactrl->size, dmactrl->flags);
|
||||
if (vaddr) {
|
||||
/* Store allocation information in dmamem structure */
|
||||
dmamem->vaddr = vaddr;
|
||||
dmamem->paddr = virt_to_phys(vaddr);
|
||||
dmamem->dev = dmactrl->dev;
|
||||
dmamem->size = dmactrl->size;
|
||||
dmamem->type = NGBDE_DMA_T_PGMEM;
|
||||
dmamem->baddr = dma_map_single(dmamem->dev, dmamem->vaddr,
|
||||
dmamem->size, DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(dmactrl->dev, dmamem->baddr)) {
|
||||
dmamem->baddr = 0;
|
||||
if (dma_debug) {
|
||||
printk("DMA: Failed to map PGMEM memory\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Write small signature for debug purposes */
|
||||
strcpy((char *)vaddr, "DMA_PGMEM");
|
||||
|
||||
if (dma_debug) {
|
||||
printk("DMA: Allocated %d KB of PGMEM memory at 0x%08lx\n",
|
||||
(int)(dmamem->size / ONE_KB),
|
||||
(unsigned long)dmamem->paddr);
|
||||
}
|
||||
} else {
|
||||
if (dma_debug) {
|
||||
printk("DMA: Failed to allocate PGMEM memory\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Allocate DMA memory.
|
||||
*
|
||||
* Depending on the DMA allocation control parameters, we select one
|
||||
* of several DMA memory allocation methods.
|
||||
*
|
||||
* \param [in] dmactrl DMA allocation control.
|
||||
* \param [out] dmamem DMA allocation result.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
static int
|
||||
ngbde_dmamem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem)
|
||||
{
|
||||
int kapi = 0;
|
||||
|
||||
if (dmamem->vaddr) {
|
||||
/* Already allocated */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMA
|
||||
/* Always allow KAPI when CMA is available */
|
||||
kapi = 1;
|
||||
#else
|
||||
if (dmactrl->size <= (1 << (MAX_ORDER - 1 + PAGE_SHIFT))) {
|
||||
kapi = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocation via kernel DMA API (if allowed) */
|
||||
if (kapi) {
|
||||
switch (dmactrl->pref_type) {
|
||||
case NGBDE_DMA_T_AUTO:
|
||||
case NGBDE_DMA_T_KAPI:
|
||||
ngbde_dmamem_kapi_alloc(dmactrl, dmamem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocation via private page allocator */
|
||||
if (dmamem->vaddr == NULL) {
|
||||
switch (dmactrl->pref_type) {
|
||||
case NGBDE_DMA_T_AUTO:
|
||||
case NGBDE_DMA_T_PGMEM:
|
||||
ngbde_dmamem_pgmem_alloc(dmactrl, dmamem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmamem->vaddr == NULL) {
|
||||
printk(KERN_WARNING "%s: Failed to allocate DMA memory\n",
|
||||
MOD_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Free DMA memory.
|
||||
*
|
||||
* Free DMA memory allocated via \ref ngbde_dmamem_alloc.
|
||||
*
|
||||
* \param [in] dmamem DMA allocation result from \ref ngbde_dmamem_alloc.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
static int
|
||||
ngbde_dmamem_free(ngbde_dmamem_t *dmamem)
|
||||
{
|
||||
switch (dmamem->type) {
|
||||
case NGBDE_DMA_T_KAPI:
|
||||
if (dma_debug) {
|
||||
printk("DMA: Freeing %d KB of KAPI memory\n",
|
||||
(int)(dmamem->size / ONE_KB));
|
||||
}
|
||||
dma_free_coherent(dmamem->dev, dmamem->size,
|
||||
dmamem->vaddr, dmamem->paddr);
|
||||
memset(dmamem, 0, sizeof(*dmamem));
|
||||
break;
|
||||
case NGBDE_DMA_T_PGMEM:
|
||||
if (dma_debug) {
|
||||
printk("DMA: Freeing %d KB of PGMEM memory\n",
|
||||
(int)(dmamem->size / ONE_KB));
|
||||
}
|
||||
if (dmamem->baddr) {
|
||||
if (dma_debug) {
|
||||
printk("DMA: Unmapping PGMEM memory at 0x%08lx\n",
|
||||
(unsigned long)dmamem->baddr);
|
||||
}
|
||||
dma_unmap_single(dmamem->dev, dmamem->baddr,
|
||||
dmamem->size, DMA_BIDIRECTIONAL);
|
||||
}
|
||||
ngbde_pgmem_free(dmamem->vaddr);
|
||||
memset(dmamem, 0, sizeof(*dmamem));
|
||||
break;
|
||||
case NGBDE_DMA_T_NONE:
|
||||
/* Nothing to free */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: Unable to free unknown DMA memory type\n",
|
||||
MOD_NAME);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Free all DMA memory pools for all devices.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
void
|
||||
ngbde_dma_cleanup(void)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
unsigned int pool;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) {
|
||||
if (swdev[idx].inactive) {
|
||||
ngbde_dmamem_free(&swdev[idx].dmapool[pool].dmamem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Allocate DMA memory pools for all devices.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
int
|
||||
ngbde_dma_init(void)
|
||||
{
|
||||
int rv;
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
int dma_type = NGBDE_DMA_T_AUTO;
|
||||
struct ngbde_dmapool_s *dmapool;
|
||||
unsigned int pool;
|
||||
|
||||
/* Default DMA memory size per device */
|
||||
if (dma_size < 0) {
|
||||
dma_size = DMAPOOL_SIZE_DEFAULT;
|
||||
}
|
||||
|
||||
/* Check for forced DMA allocation method */
|
||||
if (dma_alloc) {
|
||||
if (strcmp(dma_alloc, "kapi") == 0) {
|
||||
dma_type = NGBDE_DMA_T_KAPI;
|
||||
} else if (strcmp(dma_alloc, "pgmem") == 0) {
|
||||
dma_type = NGBDE_DMA_T_PGMEM;
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: Unknown DMA type: %s\n",
|
||||
MOD_NAME, dma_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Number of DMA memory pools per device */
|
||||
if ((unsigned int)dma_pools >= NGBDE_NUM_DMAPOOL_MAX) {
|
||||
dma_pools = NUM_DMAPOOL_DEFAULT;
|
||||
}
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
|
||||
/* Set DMA allocation parameters */
|
||||
for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) {
|
||||
dmapool = &swdev[idx].dmapool[pool];
|
||||
dmapool->dmactrl.dev = swdev[idx].dma_dev;
|
||||
dmapool->dmactrl.size = dma_size * ONE_MB;
|
||||
dmapool->dmactrl.pref_type = dma_type;
|
||||
dmapool->dmactrl.flags = GFP_KERNEL | GFP_DMA32;
|
||||
}
|
||||
|
||||
/* Allocate DMA pools */
|
||||
for (pool = 0; pool < dma_pools; pool++) {
|
||||
dmapool = &swdev[idx].dmapool[pool];
|
||||
rv = ngbde_dmamem_alloc(&dmapool->dmactrl, &dmapool->dmamem);
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: Unable to allocate DMA pool %d %d\n",
|
||||
MOD_NAME, idx, pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
143
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c
Normal file
143
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*! \file ngbde_iio.c
|
||||
*
|
||||
* API for managing and accessing memory-mapped I/O for interrupt
|
||||
* controller registers.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
void *
|
||||
ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->iio_mem) {
|
||||
if (addr == sd->iio_win.addr && size == sd->iio_win.size) {
|
||||
/* Already mapped */
|
||||
return sd->iio_mem;
|
||||
}
|
||||
ngbde_iio_unmap(devh);
|
||||
}
|
||||
|
||||
sd->iio_mem = ioremap_nocache(addr, size);
|
||||
|
||||
if (sd->iio_mem) {
|
||||
/* Save mapped resources */
|
||||
sd->iio_win.addr = addr;
|
||||
sd->iio_win.size = size;
|
||||
}
|
||||
|
||||
return sd->iio_mem;
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_iio_unmap(void *devh)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->iio_mem) {
|
||||
iounmap(sd->iio_mem);
|
||||
sd->iio_mem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_iio_cleanup(void)
|
||||
{
|
||||
struct ngbde_dev_s *swdev, *sd;
|
||||
unsigned int num_swdev, idx;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
sd = ngbde_swdev_get(idx);
|
||||
ngbde_iio_unmap(sd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->iio_mem) {
|
||||
NGBDE_IOWRITE32(val, sd->iio_mem + offs);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ngbde_iio_read32(void *devh, uint32_t offs)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->iio_mem) {
|
||||
return NGBDE_IOREAD32(sd->iio_mem + offs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->paxb_mem) {
|
||||
if (addr == sd->paxb_win.addr && size == sd->paxb_win.size) {
|
||||
/* Already mapped */
|
||||
return sd->paxb_mem;
|
||||
}
|
||||
iounmap(sd->paxb_mem);
|
||||
}
|
||||
|
||||
sd->paxb_mem = ioremap_nocache(addr, size);
|
||||
|
||||
if (sd->paxb_mem) {
|
||||
/* Save mapped resources */
|
||||
sd->paxb_win.addr = addr;
|
||||
sd->paxb_win.size = size;
|
||||
}
|
||||
|
||||
return sd->paxb_mem;
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_paxb_unmap(void *devh)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->paxb_mem) {
|
||||
iounmap(sd->paxb_mem);
|
||||
sd->paxb_mem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_paxb_cleanup(void)
|
||||
{
|
||||
struct ngbde_dev_s *swdev, *sd;
|
||||
unsigned int num_swdev, idx;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
sd = ngbde_swdev_get(idx);
|
||||
ngbde_paxb_unmap(sd);
|
||||
}
|
||||
}
|
550
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c
Normal file
550
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c
Normal file
@ -0,0 +1,550 @@
|
||||
/*! \file ngbde_intr.c
|
||||
*
|
||||
* API for controlling a thread-based user-mode interrupt handler.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
/*! \cond */
|
||||
static int intr_debug = 0;
|
||||
module_param(intr_debug, int, 0);
|
||||
MODULE_PARM_DESC(intr_debug,
|
||||
"Interrupt debug output enable (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
static int
|
||||
ngbde_intr_shared_write32(struct ngbde_dev_s *sd, struct ngbde_intr_ctrl_s *ic,
|
||||
uint32_t reg_offs, uint32_t reg_val, uint32_t shr_mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct ngbde_shr_reg_s *sr;
|
||||
int idx;
|
||||
|
||||
sr = NULL;
|
||||
for (idx = 0; idx < NGBDE_NUM_INTR_SHR_REGS_MAX; idx++) {
|
||||
if (sd->intr_shr_reg[idx].reg_offs == 0) {
|
||||
/* If not found, then we add a new entry */
|
||||
sd->intr_shr_reg[idx].reg_offs = reg_offs;
|
||||
}
|
||||
if (sd->intr_shr_reg[idx].reg_offs == reg_offs) {
|
||||
sr = &sd->intr_shr_reg[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sd->lock, flags);
|
||||
|
||||
sr->cur_val &= ~shr_mask;
|
||||
sr->cur_val |= (reg_val & shr_mask);
|
||||
|
||||
NGBDE_IOWRITE32(sr->cur_val, ic->iomem + reg_offs);
|
||||
|
||||
spin_unlock_irqrestore(&sd->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Interrupt handler for user mode thread.
|
||||
*
|
||||
* This function will determine whether a user-mode interrupt has
|
||||
* occurred by reading the configured interrupt status and mask
|
||||
* registers.
|
||||
*
|
||||
* If an interrupt has occurred, any waiting user-mode thread is woken
|
||||
* up.
|
||||
*
|
||||
* \param [in] ic Interrupt control information.
|
||||
*
|
||||
* \retval 1 One or more user mode interrupts occurred.
|
||||
* \retval 0 No user mode interrupts occurred.
|
||||
*/
|
||||
static int
|
||||
ngbde_user_isr(ngbde_intr_ctrl_t *ic)
|
||||
{
|
||||
int idx;
|
||||
int active_interrupts = 0;
|
||||
uint32_t stat = 0, mask = 0;
|
||||
uint32_t kmask;
|
||||
|
||||
/* Check if any enabled interrupts are active */
|
||||
for (idx = 0; idx < ic->num_regs; idx++) {
|
||||
ngbde_irq_reg_t *ir = &ic->regs[idx];
|
||||
|
||||
/* Get mask of all kernel interrupt sources for this register address */
|
||||
kmask = ir->kmask;
|
||||
|
||||
stat = NGBDE_IOREAD32(&ic->iomem[ir->status_reg]);
|
||||
mask = NGBDE_IOREAD32(&ic->iomem[ir->mask_reg]);
|
||||
|
||||
if (stat & mask & ~kmask) {
|
||||
active_interrupts = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No active interrupts to service */
|
||||
if (!active_interrupts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Disable (mask off) all interrupts */
|
||||
for (idx = 0; idx < ic->num_regs; idx++) {
|
||||
ngbde_irq_reg_t *ir = &ic->regs[idx];
|
||||
|
||||
/* Get mask of all kernel interrupt sources for this register address */
|
||||
kmask = ir->kmask;
|
||||
|
||||
if (kmask == 0xffffffff) {
|
||||
/* Kernel driver owns all interrupts in this register */
|
||||
continue;
|
||||
} else if (kmask) {
|
||||
/* Synchronized write */
|
||||
struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev);
|
||||
if (ngbde_intr_shared_write32(sd, ic, ir->mask_reg, 0, ~kmask) < 0) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Failed to write shared register for device %d\n",
|
||||
MOD_NAME, ic->kdev);
|
||||
/* Fall back to normal write to ensure interrupts are masked */
|
||||
NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]);
|
||||
}
|
||||
} else {
|
||||
NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]);
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&ic->run_user_thread, 1);
|
||||
wake_up_interruptible(&ic->user_thread_wq);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Interrupt handler for kernel driver.
|
||||
*
|
||||
* Typically used by the KNET driver.
|
||||
*
|
||||
* \param [in] ic Interrupt control information.
|
||||
*
|
||||
* \retval 1 One or more kernel mode interrupts occurred.
|
||||
* \retval 0 No kernel mode interrupts occurred.
|
||||
*/
|
||||
static int
|
||||
ngbde_kernel_isr(ngbde_intr_ctrl_t *ic)
|
||||
{
|
||||
if (ic->isr_func) {
|
||||
return ic->isr_func(ic->isr_data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Acknowledge interrupt
|
||||
*
|
||||
* \param [in] data Interrupt control information
|
||||
*
|
||||
* \retval 0
|
||||
*/
|
||||
static int
|
||||
ngbde_intr_ack(ngbde_intr_ctrl_t *ic)
|
||||
{
|
||||
struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev);
|
||||
struct ngbde_intr_ack_reg_s *ar = &ic->intr_ack;
|
||||
|
||||
if (sd->use_msi) {
|
||||
if (ar->flags & NGBDE_INTR_ACK_F_PAXB) {
|
||||
NGBDE_IOWRITE32(ar->ack_val, &sd->paxb_mem[ar->ack_reg]);
|
||||
} else {
|
||||
NGBDE_IOWRITE32(ar->ack_val, &sd->pio_mem[ar->ack_reg]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Linux ISR
|
||||
*
|
||||
* Will call the user-mode interrupts handler and optionally also a
|
||||
* kernel mode interrupt handler (typically KNET).
|
||||
*
|
||||
* \param [in] irq_num Interrupt vector from kernel.
|
||||
* \param [in] data Interrupt control information
|
||||
*
|
||||
* \retval IRQ_NONE Interrupt not recognized.
|
||||
* \retval IRQ_HANDLED Interrupt recognized and handled (masked off).
|
||||
*/
|
||||
static irqreturn_t
|
||||
ngbde_isr(int irq_num, void *data)
|
||||
{
|
||||
struct ngbde_intr_ctrl_s *ic = (struct ngbde_intr_ctrl_s *)data;
|
||||
irqreturn_t rv = IRQ_NONE;
|
||||
|
||||
ngbde_intr_ack(ic);
|
||||
|
||||
if (ngbde_user_isr(ic)) {
|
||||
rv = IRQ_HANDLED;
|
||||
}
|
||||
if (ngbde_kernel_isr(ic)) {
|
||||
rv = IRQ_HANDLED;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_connect(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
unsigned long irq_flags;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (ic->irq_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sd->irq_line >= 0) {
|
||||
if (sd->pio_mem == NULL) {
|
||||
printk(KERN_WARNING "%s: No memory-mapped I/O for device %d\n",
|
||||
MOD_NAME, kdev);
|
||||
return -1;
|
||||
}
|
||||
ic->kdev = kdev;
|
||||
ic->iomem = sd->pio_mem;
|
||||
if (sd->iio_mem) {
|
||||
if (intr_debug) {
|
||||
printk("INTR: Using dedicated interrupt controller\n");
|
||||
}
|
||||
ic->iomem = sd->iio_mem;
|
||||
}
|
||||
init_waitqueue_head(&ic->user_thread_wq);
|
||||
atomic_set(&ic->run_user_thread, 0);
|
||||
irq_flags = IRQF_SHARED;
|
||||
ic->irq_vect = sd->irq_line;
|
||||
|
||||
/*
|
||||
* The pci_enable_msi function must be called after enabling
|
||||
* BAR0_PAXB_OARR_FUNC0_MSI_PAGE, otherwise, MSI interrupts
|
||||
* cannot be triggered!
|
||||
*/
|
||||
if (sd->use_msi) {
|
||||
if (pci_enable_msi(sd->pci_dev) == 0) {
|
||||
irq_flags = 0;
|
||||
ic->irq_vect = sd->pci_dev->irq;
|
||||
if (intr_debug) {
|
||||
printk("INTR: Enabled MSI interrupts\n");
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: Failed to enable MSI for device %d\n",
|
||||
MOD_NAME, kdev);
|
||||
sd->use_msi = 0;
|
||||
}
|
||||
}
|
||||
if (intr_debug) {
|
||||
printk("INTR: Request IRQ %d\n", ic->irq_vect);
|
||||
}
|
||||
if (request_irq(ic->irq_vect, ngbde_isr, irq_flags, MOD_NAME, ic) < 0) {
|
||||
printk(KERN_WARNING "%s: Could not get IRQ %d for device %d\n",
|
||||
MOD_NAME, ic->irq_vect, kdev);
|
||||
return -1;
|
||||
}
|
||||
ic->irq_active = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_disconnect(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (!ic->irq_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ic->isr_func) {
|
||||
printk(KERN_WARNING "%s: Disconnecting IRQ %d blocked by kernel ISR\n",
|
||||
MOD_NAME, irq_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ic->irq_vect >= 0) {
|
||||
free_irq(ic->irq_vect, ic);
|
||||
if (sd->use_msi) {
|
||||
pci_disable_msi(sd->pci_dev);
|
||||
}
|
||||
ic->irq_active = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_intr_cleanup(void)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx, irq_num;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
for (irq_num = 0; irq_num < NGBDE_NUM_IRQS_MAX; irq_num++) {
|
||||
ngbde_intr_disconnect(idx, irq_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_wait(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (!ic->irq_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
wait_event_interruptible(ic->user_thread_wq,
|
||||
atomic_read(&ic->run_user_thread) != 0);
|
||||
atomic_set(&ic->run_user_thread, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_stop(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (!ic->irq_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wake up user thread */
|
||||
atomic_set(&ic->run_user_thread, 1);
|
||||
wake_up_interruptible(&ic->user_thread_wq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_regs_clr(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (ic->irq_active) {
|
||||
/* Do not clear configuration with interrupt connected */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ic->num_regs = 0;
|
||||
memset(ic->regs, 0, sizeof(ic->regs));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_reg_add(int kdev, unsigned int irq_num,
|
||||
struct ngbde_irq_reg_s *ireg)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
struct ngbde_irq_reg_s *ir;
|
||||
unsigned int idx;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (ic->irq_active) {
|
||||
/*
|
||||
* If the interrupt is connected, then we only update the
|
||||
* kernel mask for existing entries.
|
||||
*/
|
||||
for (idx = 0; idx < ic->num_regs; idx++) {
|
||||
ir = &ic->regs[idx];
|
||||
if (ir->status_reg == ireg->status_reg &&
|
||||
ir->mask_reg == ireg->mask_reg) {
|
||||
ir->kmask = ireg->kmask;
|
||||
if (intr_debug) {
|
||||
printk("INTR: Updating interrupt register "
|
||||
"0x%08x/0x%08x (0x%08x)\n",
|
||||
ir->status_reg, ir->mask_reg, ir->kmask);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ic->num_regs >= NGBDE_NUM_IRQ_REGS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ir = &ic->regs[ic->num_regs++];
|
||||
|
||||
memcpy(ir, ireg, sizeof (*ir));
|
||||
|
||||
if (intr_debug) {
|
||||
printk("INTR: Adding interrupt register 0x%08x/0x%08x (0x%08x)\n",
|
||||
ir->status_reg, ir->mask_reg, ir->kmask);
|
||||
}
|
||||
|
||||
return ic->num_regs;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num,
|
||||
struct ngbde_intr_ack_reg_s *ackreg)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
struct ngbde_intr_ack_reg_s *ar;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
if (ic->irq_active) {
|
||||
/* Ignore request if interrupt is connected */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ar = &ic->intr_ack;
|
||||
|
||||
memcpy(ar, ackreg, sizeof (*ar));
|
||||
|
||||
if (intr_debug) {
|
||||
printk("INTR: Adding interrupt ACK register 0x%08x/0x%08x (0x%08x)\n",
|
||||
ar->ack_reg, ar->ack_val, ar->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi,
|
||||
uint32_t status_reg, uint32_t mask_val)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
struct ngbde_irq_reg_s *ir;
|
||||
unsigned int idx;
|
||||
uint32_t bmask;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
|
||||
ir = ic->regs;
|
||||
for (idx = 0; idx < ic->num_regs; idx++) {
|
||||
if (ir->status_reg == status_reg) {
|
||||
bmask = kapi ? ir->kmask : ~ir->kmask;
|
||||
ngbde_intr_shared_write32(sd, ic, ir->mask_reg, mask_val, bmask);
|
||||
return 0;
|
||||
}
|
||||
ir++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
237
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c
Normal file
237
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c
Normal file
@ -0,0 +1,237 @@
|
||||
/*! \file ngbde_ioctl.c
|
||||
*
|
||||
* NGBDE IOCTL interface.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <lkm/ngbde_ioctl.h>
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
long
|
||||
ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct ngbde_ioc_cmd_s ioc;
|
||||
struct ngbde_dev_s *swdev;
|
||||
struct ngbde_irq_reg_s ireg;
|
||||
struct ngbde_intr_ack_reg_s ackreg;
|
||||
phys_addr_t addr, size;
|
||||
unsigned int num_swdev;
|
||||
unsigned int rsrc_type, rsrc_idx;
|
||||
unsigned int irq_num, intr_cmd;
|
||||
uint32_t mreg, mval;
|
||||
|
||||
if (copy_from_user(&ioc, (void *)arg, sizeof(ioc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ioc.rc = NGBDE_IOC_SUCCESS;
|
||||
|
||||
switch (cmd) {
|
||||
case NGBDE_IOC_MOD_INFO:
|
||||
ioc.op.mod_info.version = NGBDE_IOC_VERSION;
|
||||
break;
|
||||
case NGBDE_IOC_PROBE_INFO:
|
||||
ngbde_swdev_get_all(NULL, &num_swdev);
|
||||
ioc.op.probe_info.num_swdev = num_swdev;
|
||||
break;
|
||||
case NGBDE_IOC_DEV_INFO:
|
||||
swdev = ngbde_swdev_get(ioc.devid);
|
||||
if (!swdev) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
ioc.op.dev_info.vendor_id = swdev->vendor_id;
|
||||
ioc.op.dev_info.device_id = swdev->device_id;
|
||||
ioc.op.dev_info.revision = swdev->revision;
|
||||
ioc.op.dev_info.model = swdev->model;
|
||||
if (swdev->use_msi) {
|
||||
ioc.op.dev_info.flags |= NGBDE_DEV_F_MSI;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_PHYS_ADDR:
|
||||
swdev = ngbde_swdev_get(ioc.devid);
|
||||
if (!swdev) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
rsrc_type = ioc.op.rsrc_id.type;
|
||||
rsrc_idx = ioc.op.rsrc_id.inst;
|
||||
switch (rsrc_type) {
|
||||
case NGBDE_IO_RSRC_DEV_IO:
|
||||
if (rsrc_idx >= NGBDE_NUM_IOWIN_MAX) {
|
||||
printk(KERN_WARNING
|
||||
"ngbde: invalid resource index (%d)\n",
|
||||
rsrc_idx);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
ioc.op.phys_addr.addr = swdev->iowin[rsrc_idx].addr;
|
||||
ioc.op.phys_addr.size = swdev->iowin[rsrc_idx].size;
|
||||
break;
|
||||
case NGBDE_IO_RSRC_DMA_MEM:
|
||||
if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) {
|
||||
printk(KERN_WARNING
|
||||
"ngbde: invalid resource index (%d)\n",
|
||||
rsrc_idx);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.paddr;
|
||||
ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size;
|
||||
break;
|
||||
case NGBDE_IO_RSRC_DMA_BUS:
|
||||
if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) {
|
||||
printk(KERN_WARNING
|
||||
"ngbde: invalid resource index (%d)\n",
|
||||
rsrc_idx);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.baddr;
|
||||
ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"ngbde: unknown resource type (%d)\n",
|
||||
rsrc_type);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_INTR_CTRL:
|
||||
irq_num = ioc.op.intr_ctrl.irq_num;
|
||||
intr_cmd = ioc.op.intr_ctrl.cmd;
|
||||
switch (intr_cmd) {
|
||||
case NGBDE_ICTL_INTR_CONN:
|
||||
if (ngbde_intr_connect(ioc.devid, irq_num) < 0) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_ICTL_INTR_DISC:
|
||||
if (ngbde_intr_disconnect(ioc.devid, irq_num) < 0) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_ICTL_INTR_WAIT:
|
||||
if (ngbde_intr_wait(ioc.devid, irq_num) < 0) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_ICTL_INTR_STOP:
|
||||
if (ngbde_intr_stop(ioc.devid, irq_num) < 0) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_ICTL_REGS_CLR:
|
||||
if (ngbde_intr_regs_clr(ioc.devid, irq_num) < 0) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: unknown interrupt control command (%d)\n",
|
||||
MOD_NAME, intr_cmd);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_IRQ_REG_ADD:
|
||||
irq_num = ioc.op.irq_reg_add.irq_num;
|
||||
ireg.status_reg = ioc.op.irq_reg_add.status_reg;
|
||||
ireg.mask_reg = ioc.op.irq_reg_add.mask_reg;
|
||||
ireg.kmask = ioc.op.irq_reg_add.kmask;
|
||||
if (ngbde_intr_reg_add(ioc.devid, irq_num, &ireg) < 0) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Unable to add interrupt register\n",
|
||||
MOD_NAME);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_INTR_ACK_REG_ADD:
|
||||
irq_num = ioc.op.intr_ack_reg_add.irq_num;
|
||||
ackreg.ack_reg = ioc.op.intr_ack_reg_add.ack_reg;
|
||||
ackreg.ack_val = ioc.op.intr_ack_reg_add.ack_val;
|
||||
ackreg.flags = ioc.op.intr_ack_reg_add.flags;
|
||||
if (ngbde_intr_ack_reg_add(ioc.devid, irq_num, &ackreg) < 0) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Unable to add interrupt ack register\n",
|
||||
MOD_NAME);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_IRQ_MASK_WR:
|
||||
irq_num = ioc.op.irq_mask_wr.irq_num;
|
||||
mreg = ioc.op.irq_mask_wr.offs;
|
||||
mval = ioc.op.irq_mask_wr.val;
|
||||
if (ngbde_intr_mask_write(ioc.devid, irq_num, 0, mreg, mval) < 0) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Unable to write shared register\n",
|
||||
MOD_NAME);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_PIO_WIN_MAP:
|
||||
swdev = ngbde_swdev_get(ioc.devid);
|
||||
if (!swdev) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
addr = ioc.op.pio_win.addr;
|
||||
size = ioc.op.pio_win.size;
|
||||
if (ngbde_pio_map(swdev, addr, size) == NULL) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_IIO_WIN_MAP:
|
||||
swdev = ngbde_swdev_get(ioc.devid);
|
||||
if (!swdev) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
addr = ioc.op.pio_win.addr;
|
||||
size = ioc.op.pio_win.size;
|
||||
if (ngbde_iio_map(swdev, addr, size) == NULL) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
case NGBDE_IOC_PAXB_WIN_MAP:
|
||||
swdev = ngbde_swdev_get(ioc.devid);
|
||||
if (!swdev) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
addr = ioc.op.pio_win.addr;
|
||||
size = ioc.op.pio_win.size;
|
||||
if (ngbde_paxb_map(swdev, addr, size) == NULL) {
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "ngbde: invalid ioctl (%08x)\n", cmd);
|
||||
ioc.rc = NGBDE_IOC_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/*! \file ngbde_iproc_probe.c
|
||||
*
|
||||
* BDE probe for IPROC internal bus devices.
|
||||
*
|
||||
* Validate CMICD existence on the platform. If Linux device tree matched,
|
||||
* probe function of platform driver is called and the switch device read from
|
||||
* CMICD register is added to the device list.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*! \cond */
|
||||
static int iproc_debug = 0;
|
||||
module_param(iproc_debug, int, 0);
|
||||
MODULE_PARM_DESC(iproc_debug,
|
||||
"IPROC debug output enable (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
/*!
|
||||
* \brief Probe devices on the IPROC internal bus.
|
||||
*
|
||||
* \param [in] pldev Platform device.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
static int
|
||||
iproc_cmicd_probe(struct platform_device *pldev)
|
||||
{
|
||||
int rv;
|
||||
uint32_t size;
|
||||
void *base_address;
|
||||
uint32_t dev_rev_id;
|
||||
struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev;
|
||||
struct resource *memres, *irqres;
|
||||
|
||||
memres = platform_get_resource(pldev, IORESOURCE_MEM, 0);
|
||||
if (memres == NULL) {
|
||||
printk("Unable to retrieve iProc CMIC memory resource.");
|
||||
return -1;
|
||||
}
|
||||
size = memres->end - memres->start + 1;
|
||||
|
||||
if (iproc_debug) {
|
||||
printk("CMIC info : Memory start=%p, end=%p\n",
|
||||
(void *)memres->start, (void *)memres->end);
|
||||
}
|
||||
|
||||
base_address = ioremap_nocache(memres->start, size);
|
||||
if (!base_address) {
|
||||
printk(KERN_WARNING "Error mapping iProc CMIC registers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(nd, 0, sizeof(*nd));
|
||||
nd->pci_dev = NULL; /* No PCI bus */
|
||||
nd->dma_dev = &pldev->dev;
|
||||
|
||||
/* Read switch device ID from CMIC */
|
||||
dev_rev_id = *((uint32_t*)(base_address + 0x10224));
|
||||
nd->vendor_id = 0x14e4;
|
||||
nd->device_id = dev_rev_id & 0xffff;
|
||||
nd->revision = (dev_rev_id >> 16) & 0xff;
|
||||
|
||||
irqres = platform_get_resource(pldev, IORESOURCE_IRQ, 0);
|
||||
if (irqres == NULL) {
|
||||
printk(KERN_WARNING "Unable to retrieve iProc CMIC IRQ resource.");
|
||||
return -1;
|
||||
}
|
||||
nd->irq_line = irqres->start;
|
||||
if (iproc_debug) {
|
||||
printk("CMIC info : IRQ line=%p\n", (void *)irqres->start);
|
||||
}
|
||||
|
||||
nd->iowin[0].addr = memres->start;
|
||||
nd->iowin[0].size = size;
|
||||
|
||||
if (base_address) {
|
||||
iounmap(base_address);
|
||||
}
|
||||
rv = ngbde_swdev_add(nd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove the platform device.
|
||||
*
|
||||
* \param [in] pldev Platform device.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
*/
|
||||
static int
|
||||
iproc_cmicd_remove(struct platform_device *pldev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Matching compatible property with device tree. */
|
||||
static const struct of_device_id iproc_cmicd_of_match[] = {
|
||||
{ .compatible = "brcm,iproc-cmicd" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match);
|
||||
|
||||
static char iproc_cmicd_string[] = "bcmiproc-cmicd";
|
||||
|
||||
/*! Platform driver definition. */
|
||||
static struct platform_driver iproc_cmicd_driver =
|
||||
{
|
||||
.probe = iproc_cmicd_probe,
|
||||
.remove = iproc_cmicd_remove,
|
||||
.driver =
|
||||
{
|
||||
.name = iproc_cmicd_string,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = iproc_cmicd_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Probe for Broadcom switch devices on IPROC internal bus.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
int
|
||||
ngbde_iproc_probe(void)
|
||||
{
|
||||
platform_driver_register(&iproc_cmicd_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clean up resources for Broadcom switch devices on IPROC internal bus.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
int
|
||||
ngbde_iproc_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&iproc_cmicd_driver);
|
||||
|
||||
return 0;
|
||||
}
|
216
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c
Normal file
216
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c
Normal file
@ -0,0 +1,216 @@
|
||||
/*! \file ngbde_kapi.c
|
||||
*
|
||||
* Public BDE kernel API for use with other kernel modules.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
#include <lkm/ngbde_kapi.h>
|
||||
|
||||
struct pci_dev *
|
||||
ngbde_kapi_pci_dev_get(int kdev)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sd->pci_dev;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_pci_dev_get);
|
||||
/*! \endcond */
|
||||
|
||||
struct device *
|
||||
ngbde_kapi_dma_dev_get(int kdev)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sd->dma_dev;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_dma_dev_get);
|
||||
/*! \endcond */
|
||||
|
||||
void *
|
||||
ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_dmamem_s *dmamem;
|
||||
size_t dma_offset;
|
||||
int idx;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) {
|
||||
dmamem = &sd->dmapool[idx].dmamem;
|
||||
dma_offset = baddr - dmamem->baddr;
|
||||
if (dma_offset < dmamem->size) {
|
||||
return (uint8_t *)dmamem->vaddr + dma_offset;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_dma_bus_to_virt);
|
||||
/*! \endcond */
|
||||
|
||||
dma_addr_t
|
||||
ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_dmamem_s *dmamem;
|
||||
size_t dma_offset;
|
||||
int idx;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) {
|
||||
dmamem = &sd->dmapool[idx].dmamem;
|
||||
dma_offset = (uintptr_t)vaddr - (uintptr_t)dmamem->vaddr;
|
||||
if (dma_offset < dmamem->size) {
|
||||
return dmamem->baddr + dma_offset;
|
||||
}
|
||||
}
|
||||
return 0UL;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_dma_virt_to_bus);
|
||||
/*! \endcond */
|
||||
|
||||
void
|
||||
ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (sd) {
|
||||
return ngbde_pio_write32(sd, offs, val);
|
||||
}
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_pio_write32);
|
||||
/*! \endcond */
|
||||
|
||||
uint32_t
|
||||
ngbde_kapi_pio_read32(int kdev, uint32_t offs)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (sd) {
|
||||
return ngbde_pio_read32(sd, offs);
|
||||
}
|
||||
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_pio_read32);
|
||||
/*! \endcond */
|
||||
|
||||
void *
|
||||
ngbde_kapi_pio_membase(int kdev)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sd->pio_mem;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_pio_membase);
|
||||
/*! \endcond */
|
||||
|
||||
int
|
||||
ngbde_kapi_intr_connect(int kdev, unsigned int irq_num,
|
||||
int (*isr_func)(void *), void *isr_data)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
ic->isr_func = isr_func;
|
||||
ic->isr_data = isr_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_intr_connect);
|
||||
/*! \endcond */
|
||||
|
||||
int
|
||||
ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num)
|
||||
{
|
||||
struct ngbde_dev_s *sd;
|
||||
struct ngbde_intr_ctrl_s *ic;
|
||||
|
||||
sd = ngbde_swdev_get(kdev);
|
||||
if (!sd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (irq_num >= NGBDE_NUM_IRQS_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ic = &sd->intr_ctrl[irq_num];
|
||||
ic->isr_func = NULL;
|
||||
ic->isr_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_intr_disconnect);
|
||||
/*! \endcond */
|
||||
|
||||
int
|
||||
ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num,
|
||||
uint32_t status_reg, uint32_t mask_val)
|
||||
{
|
||||
return ngbde_intr_mask_write(kdev, irq_num, 1, status_reg, mask_val);
|
||||
}
|
||||
/*! \cond */
|
||||
EXPORT_SYMBOL(ngbde_kapi_intr_mask_write);
|
||||
/*! \endcond */
|
297
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c
Normal file
297
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*! \file ngbde_main.c
|
||||
*
|
||||
* NGBDE module entry.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
/*! \cond */
|
||||
MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("NG BDE Module");
|
||||
MODULE_LICENSE("GPL");
|
||||
/*! \endcond */
|
||||
|
||||
/*! \cond */
|
||||
static int mmap_debug = 0;
|
||||
module_param(mmap_debug, int, 0);
|
||||
MODULE_PARM_DESC(mmap_debug,
|
||||
"MMAP debug output enable (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
/*!
|
||||
* \brief Remap user space DMA memory to non-cached area.
|
||||
*
|
||||
* Since we cannot flush and invalidate DMA memory from user space,
|
||||
* the DMA memory pools need to be cache-coherent, even if this means
|
||||
* that we need to remap the DMA memory as non-cached.
|
||||
*
|
||||
* If undefined, we set this value according to kernel configuration.
|
||||
*/
|
||||
#ifndef REMAP_DMA_NONCACHED
|
||||
# ifdef CONFIG_DMA_NONCOHERENT
|
||||
# define REMAP_DMA_NONCACHED 1
|
||||
# else
|
||||
# define REMAP_DMA_NONCACHED 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static int
|
||||
ngbde_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ngbde_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check if memory range is within existing DMA memory pools.
|
||||
*
|
||||
* \param [in] paddr Physical start address of memory range.
|
||||
* \param [in] size Size of memory range.
|
||||
*
|
||||
* \retval true Range is valid.
|
||||
* \retval false Range is not valid.
|
||||
*/
|
||||
static bool
|
||||
ngbde_dma_range_valid(unsigned long paddr, unsigned long size)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
struct ngbde_dmamem_s *dmamem;
|
||||
unsigned int pool;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) {
|
||||
dmamem = &swdev[idx].dmapool[pool].dmamem;
|
||||
if (paddr >= dmamem->paddr &&
|
||||
(paddr + size) <= (dmamem->paddr + dmamem->size)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check if memory range is within device I/O ranges.
|
||||
*
|
||||
* \param [in] paddr Physical start address of I/O memory range.
|
||||
* \param [in] size Size of memory range.
|
||||
*
|
||||
* \retval true Range is valid.
|
||||
* \retval false Range is not valid.
|
||||
*/
|
||||
static bool
|
||||
ngbde_pio_range_valid(unsigned long paddr, unsigned long size)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
struct ngbde_memwin_s *iowin;
|
||||
unsigned long iowin_size;
|
||||
unsigned int wdx;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) {
|
||||
iowin = &swdev[idx].iowin[wdx];
|
||||
iowin_size = iowin->size;
|
||||
if (iowin_size < PAGE_SIZE) {
|
||||
iowin_size = PAGE_SIZE;
|
||||
}
|
||||
if (mmap_debug) {
|
||||
printk("MMAP: Check 0x%08lx/0x%08lx against "
|
||||
"0x%08lx/0x%08lx(0x%08lx)\n",
|
||||
paddr, size,
|
||||
(unsigned long)iowin->addr,
|
||||
(unsigned long)iowin->size, iowin_size);
|
||||
}
|
||||
if (paddr >= iowin->addr &&
|
||||
(paddr + size) <= (iowin->addr + iowin_size)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Match incomplete address with device base addresses.
|
||||
*
|
||||
* Use for physical addresses larger than 44 bits.
|
||||
*
|
||||
* \param [in] paddr Physical address from user space.
|
||||
*
|
||||
* \return Matched device base addess or 0 if no match.
|
||||
*/
|
||||
static unsigned long
|
||||
ngbde_pio_base_match(unsigned long paddr)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
struct ngbde_memwin_s *iowin;
|
||||
unsigned int wdx;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) {
|
||||
iowin = &swdev[idx].iowin[wdx];
|
||||
if (((paddr ^ iowin->addr) & 0xfffffffffffULL) == 0) {
|
||||
if (mmap_debug) {
|
||||
printk("MMAP: Matched 0x%08lx to 0x%08lx\n",
|
||||
(unsigned long)paddr,
|
||||
(unsigned long)iowin->addr);
|
||||
}
|
||||
return iowin->addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some kernels are configured to prevent mapping of kernel RAM memory
|
||||
* into user space via the /dev/mem device.
|
||||
*
|
||||
* The function below provides a backdoor to mapping the DMA pool to
|
||||
* user space via the BDE device file.
|
||||
*/
|
||||
static int
|
||||
ngbde_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long paddr = vma->vm_pgoff << PAGE_SHIFT;
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
int map_noncached = REMAP_DMA_NONCACHED;
|
||||
int range_valid = 0;
|
||||
|
||||
if (mmap_debug) {
|
||||
printk("MMAP: Mapping %lu Kbytes at 0x%08lx (0x%lx)\n",
|
||||
size / 1024, paddr, vma->vm_pgoff);
|
||||
}
|
||||
|
||||
if (ngbde_dma_range_valid(paddr, size)) {
|
||||
range_valid = 1;
|
||||
} else {
|
||||
map_noncached = 1;
|
||||
if (ngbde_pio_range_valid(paddr, size)) {
|
||||
range_valid = 1;
|
||||
} else {
|
||||
paddr = ngbde_pio_base_match(paddr);
|
||||
if (ngbde_pio_range_valid(paddr, size)) {
|
||||
range_valid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_valid) {
|
||||
printk("BDE: Invalid mmap range 0x%08lx/0x%lx\n", paddr, size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (map_noncached) {
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
}
|
||||
|
||||
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
size, vma->vm_page_prot)) {
|
||||
printk("BDE: Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n",
|
||||
paddr, paddr + size, vma->vm_start, vma->vm_end);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations fops = {
|
||||
.open = ngbde_open,
|
||||
.release = ngbde_release,
|
||||
.unlocked_ioctl = ngbde_ioctl,
|
||||
.compat_ioctl = ngbde_ioctl,
|
||||
.mmap = ngbde_mmap,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Standard module cleanup.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
void __exit
|
||||
cleanup_module(void)
|
||||
{
|
||||
ngbde_intr_cleanup();
|
||||
ngbde_iio_cleanup();
|
||||
ngbde_paxb_cleanup();
|
||||
ngbde_pio_cleanup();
|
||||
ngbde_dma_cleanup();
|
||||
ngbde_procfs_cleanup();
|
||||
unregister_chrdev(MOD_MAJOR, MOD_NAME);
|
||||
ngbde_pci_cleanup();
|
||||
ngbde_iproc_cleanup();
|
||||
printk(KERN_INFO "Broadcom NGBDE unloaded successfully\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Standard module initialization.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
int __init
|
||||
init_module(void)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = register_chrdev(MOD_MAJOR, MOD_NAME, &fops);
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: can't get major %d\n",
|
||||
MOD_NAME, MOD_MAJOR);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = ngbde_iproc_probe();
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: Error probing for AXI bus devices.\n",
|
||||
MOD_NAME);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = ngbde_pci_probe();
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: Error probing for PCI bus devices.\n",
|
||||
MOD_NAME);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = ngbde_procfs_init();
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: Unable to initialize proc files\n",
|
||||
MOD_NAME);
|
||||
return rv;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Broadcom NGBDE loaded successfully\n");
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
/*! \file ngbde_pci_probe.c
|
||||
*
|
||||
* NG BDE probe for PCI devices.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
/*! \cond */
|
||||
static int use_msi = 1;
|
||||
module_param(use_msi, int, 0);
|
||||
MODULE_PARM_DESC(use_msi,
|
||||
"Use MSI interrupts if supported by the kernel (default 1).");
|
||||
/*! \endcond */
|
||||
|
||||
/*! \cond */
|
||||
static int pci_debug = 0;
|
||||
module_param(pci_debug, int, 0);
|
||||
MODULE_PARM_DESC(pci_debug,
|
||||
"PCI debug output enable (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
/*!
|
||||
* Use BCMDRD_DEVLIST_ENTRY macro to generate a device list based on
|
||||
* supported/installed devices.
|
||||
*/
|
||||
#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \
|
||||
{ _vn, _dv, PCI_ANY_ID, PCI_ANY_ID },
|
||||
|
||||
/*! Include all chip variants in the list of supported devices. */
|
||||
#define BCMDRD_DEVLIST_INCLUDE_ALL
|
||||
|
||||
static struct pci_device_id pci_id_table[] = {
|
||||
#include <bcmdrd/bcmdrd_devlist.h>
|
||||
{ BROADCOM_VENDOR_ID, 0xb524, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ BROADCOM_VENDOR_ID, 0xb684, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent)
|
||||
{
|
||||
int rv;
|
||||
int bdx;
|
||||
int cmic_bar = 0;
|
||||
uint8_t rev;
|
||||
struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev;
|
||||
int bus_no = pci_dev->bus ? pci_dev->bus->number : 0;
|
||||
int slot_no = PCI_SLOT(pci_dev->devfn);
|
||||
|
||||
if (PCI_FUNC(pci_dev->devfn) > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pci_debug) {
|
||||
printk("PCI: pci_probe: bus %d slot %d: %04x:%04x\n",
|
||||
bus_no, slot_no,
|
||||
pci_dev->vendor, pci_dev->device);
|
||||
}
|
||||
|
||||
memset(nd, 0, sizeof(*nd));
|
||||
nd->pci_dev = pci_dev;
|
||||
nd->dma_dev = &pci_dev->dev;
|
||||
nd->vendor_id = pci_dev->vendor;
|
||||
nd->device_id = pci_dev->device;
|
||||
nd->bus_no = bus_no;
|
||||
nd->slot_no = slot_no;
|
||||
|
||||
/* PCI revision must extracted "manually */
|
||||
pci_read_config_byte(pci_dev, PCI_REVISION_ID, &rev);
|
||||
nd->revision = rev;
|
||||
|
||||
if (pci_enable_device(pci_dev)) {
|
||||
printk(KERN_WARNING "%s: Cannot enable PCI device: "
|
||||
"vendor_id = %x, device_id = %x\n",
|
||||
MOD_NAME, pci_dev->vendor, pci_dev->device);
|
||||
}
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
/* IRQ number is only valid if PCI device is enabled */
|
||||
nd->irq_line = pci_dev->irq;
|
||||
|
||||
/* Check for iProc */
|
||||
if (pci_resource_len(pci_dev, 2)) {
|
||||
nd->iowin[1].addr = pci_resource_start(pci_dev, 0);
|
||||
nd->iowin[1].size = pci_resource_len(pci_dev, 0);
|
||||
cmic_bar = 2;
|
||||
}
|
||||
nd->iowin[0].addr = pci_resource_start(pci_dev, cmic_bar);
|
||||
nd->iowin[0].size = pci_resource_len(pci_dev, cmic_bar);
|
||||
|
||||
/* Verify basic I/O access by reading first word of each BAR window */
|
||||
for (bdx = 0; bdx < 2; bdx++) {
|
||||
if (nd->iowin[bdx].size == 0) {
|
||||
continue;
|
||||
}
|
||||
if (ngbde_pio_map(nd, nd->iowin[bdx].addr, nd->iowin[bdx].size)) {
|
||||
if (pci_debug) {
|
||||
printk("PCI: BAR %d adddress 0 = 0x%x\n",
|
||||
bdx, (unsigned int)ngbde_pio_read32(nd, 0));
|
||||
}
|
||||
ngbde_pio_unmap(nd);
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: Cannot map PCI BAR %d: "
|
||||
"start = %08lx, len = %lx\n",
|
||||
MOD_NAME, bdx,
|
||||
(unsigned long)nd->iowin[bdx].addr,
|
||||
(unsigned long)nd->iowin[bdx].size);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&nd->lock);
|
||||
|
||||
/* Determine MSI configuration by enabling MSI on the device */
|
||||
nd->use_msi = use_msi;
|
||||
if (nd->use_msi) {
|
||||
if (pci_enable_msi(nd->pci_dev) == 0) {
|
||||
pci_disable_msi(nd->pci_dev);
|
||||
} else {
|
||||
nd->use_msi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ngbde_swdev_add(nd);
|
||||
|
||||
if (rv == 0) {
|
||||
/* Update DMA pools for all devices */
|
||||
rv = ngbde_dma_init();
|
||||
if (rv < 0) {
|
||||
printk(KERN_WARNING "%s: Error initializing DMA memory\n",
|
||||
MOD_NAME);
|
||||
/* Mark device as inactive */
|
||||
nd->inactive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_remove(struct pci_dev* pci_dev)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
int bus_no = pci_dev->bus ? pci_dev->bus->number : 0;
|
||||
int slot_no = PCI_SLOT(pci_dev->devfn);
|
||||
|
||||
if (pci_debug) {
|
||||
printk("PCI: pci_remove: bus %d slot %d: %04x:%04x\n",
|
||||
bus_no, slot_no,
|
||||
pci_dev->vendor, pci_dev->device);
|
||||
}
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
if (swdev[idx].bus_no == bus_no &&
|
||||
swdev[idx].slot_no == slot_no) {
|
||||
if (swdev[idx].inactive) {
|
||||
printk(KERN_WARNING "%s: Device already removed\n",
|
||||
MOD_NAME);
|
||||
}
|
||||
/* Active device in this slot already? */
|
||||
swdev[idx].inactive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update DMA pools for all devices */
|
||||
ngbde_dma_cleanup();
|
||||
}
|
||||
|
||||
static struct pci_driver pci_driver = {
|
||||
.name = MOD_NAME,
|
||||
.probe = pci_probe,
|
||||
.remove = pci_remove,
|
||||
.id_table = pci_id_table,
|
||||
/* The rest are dynamic */
|
||||
};
|
||||
|
||||
int
|
||||
ngbde_pci_probe(void)
|
||||
{
|
||||
if (pci_register_driver(&pci_driver) < 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_pci_cleanup(void)
|
||||
{
|
||||
pci_unregister_driver(&pci_driver);
|
||||
|
||||
return 0;
|
||||
}
|
472
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c
Normal file
472
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c
Normal file
@ -0,0 +1,472 @@
|
||||
/*! \file ngbde_pgmem.c
|
||||
*
|
||||
* \brief PGMEM allocator.
|
||||
*
|
||||
* This module is used to allocate large physically contiguous memory
|
||||
* blocks using the Linux kernel page allocator.
|
||||
*
|
||||
* The Linux page allocator can allocate contiguous memory up until a
|
||||
* certain size, which depends on the kernel version and the CPU
|
||||
* architecture.
|
||||
*
|
||||
* If a larger contiguous memory block is requested, then we need to
|
||||
* allocate multiple blocks from the Linux page allocator and then
|
||||
* check if which ones are contiguous.
|
||||
*
|
||||
* The smaller memory blocks from which the larger block is assembled
|
||||
* are referred to as "chunks".
|
||||
*
|
||||
* The PGMEM allocator will continue to allocate chunks from the Linux
|
||||
* page allocator, until a contiguous memory block of the requested
|
||||
* size has been assembled, or until a predefined maximum number of
|
||||
* chunks have been allocated. Obviously the process is also stopped
|
||||
* if the Linux page allocator returns an error.
|
||||
*
|
||||
* A physically contiguous memory block assembled from smaller memory
|
||||
* chunks are referred to as "cmblocks".
|
||||
*
|
||||
* The chance of success depends on the requested memory block size as
|
||||
* well as the fragmentation level of the system memory, i.e. the
|
||||
* sooner after system boot these memory block are requested, the more
|
||||
* likely these requests are to succeed.
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Local definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! Maximum size the kernel can allocate in a single allocation. */
|
||||
#define MEM_CHUNK_SIZE_MAX (1 << (MAX_ORDER - 1 + PAGE_SHIFT))
|
||||
|
||||
/*! Default block size we wil request from the kernel. */
|
||||
#define MEM_CHUNK_SIZE_DEFAULT (512 * ONE_KB)
|
||||
|
||||
/*! \cond */
|
||||
static int pgmem_chunk_size = 0;
|
||||
module_param(pgmem_chunk_size, int, 0);
|
||||
MODULE_PARM_DESC(pgmem_chunk_size,
|
||||
"Memory chunk size in KB used by page allocator (default auto).");
|
||||
/*! \endcond */
|
||||
|
||||
/*! \cond */
|
||||
static int pgmem_debug = 0;
|
||||
module_param(pgmem_debug, int, 0);
|
||||
MODULE_PARM_DESC(pgmem_debug,
|
||||
"Enable page memory allocator debug output (default 0).");
|
||||
/*! \endcond */
|
||||
|
||||
/*! Helper macro for debug trace output. */
|
||||
#define PGMEM_TRACE(_s) \
|
||||
do { \
|
||||
if (pgmem_debug) { \
|
||||
printk(_s); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*!
|
||||
* Chunk memory block descriptor.
|
||||
*/
|
||||
typedef struct cmblock_desc_s {
|
||||
|
||||
/*! Linked-list handle. */
|
||||
struct list_head list;
|
||||
|
||||
/*! Requested cmblock size. */
|
||||
unsigned long req_size;
|
||||
|
||||
/*! Memory chunk size. */
|
||||
unsigned long chunk_size;
|
||||
|
||||
/*! Memory chunk size in alternate format (2^x). */
|
||||
unsigned long chunk_order;
|
||||
|
||||
/*! Current cmblock size. */
|
||||
unsigned long cmblk_size;
|
||||
|
||||
/*! Logical address of cmblock. */
|
||||
unsigned long cmblk_begin;
|
||||
|
||||
/*! Logical end address of cmblock. */
|
||||
unsigned long cmblk_end;
|
||||
|
||||
/*! Array of logical chunk addresses. */
|
||||
unsigned long *chunk_ptr;
|
||||
|
||||
/*! Maximum number of chunks to allocate. */
|
||||
int chunk_cnt_max;
|
||||
|
||||
/*! Current number of chunks allocated. */
|
||||
int chunk_cnt;
|
||||
|
||||
} cmblock_desc_t;
|
||||
|
||||
static LIST_HEAD(cmblocks_list);
|
||||
|
||||
|
||||
/*!
|
||||
* \name Chunk tag mask.
|
||||
* \anchor CT_xxx
|
||||
*
|
||||
* The lower two bits of the chunk address is used to tag the chunk
|
||||
* with its current state.
|
||||
*/
|
||||
#define CT_MASK 0x3
|
||||
|
||||
/*! Chunk is untagged. */
|
||||
#define CT_UNTAGGED 0
|
||||
|
||||
/*! Chunk was discarded. */
|
||||
#define CT_DISCARDED 1
|
||||
|
||||
/*! Chunk is part of largest cmblock. */
|
||||
#define CT_LARGEST 2
|
||||
|
||||
/*! Chunk is part of current cmblock. */
|
||||
#define CT_CURRENT 3
|
||||
|
||||
/*! Set block as untagged. */
|
||||
#define CTAG_SET(_a, _t) \
|
||||
do { \
|
||||
(_a) &= ~CT_MASK; \
|
||||
(_a) |= _t; \
|
||||
} while (0)
|
||||
|
||||
/*! Set block as untagged. */
|
||||
#define CTAG_GET(_a) \
|
||||
((_a) & CT_MASK)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Private Functions
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* \brief Find largest contiguous memory block.
|
||||
*
|
||||
* Find largest contiguous memory block from a pool of memory chunks.
|
||||
*
|
||||
* Assembly stops if a cmblock of the requested cmblock size has been
|
||||
* obtained.
|
||||
*
|
||||
* The lower two address bits of the memory chunks are encoded as a
|
||||
* tag according to \ref CT_xxx.
|
||||
*
|
||||
* \param [in] cmbd cmblock descriptor.
|
||||
*
|
||||
* \return Always 0.
|
||||
*/
|
||||
static int
|
||||
find_largest_cmblock(cmblock_desc_t *cmbd)
|
||||
{
|
||||
int i, j, chunks, found;
|
||||
unsigned long b, e, a;
|
||||
unsigned long *cptr;
|
||||
|
||||
/* Convenience variable */
|
||||
chunks = cmbd->chunk_cnt;
|
||||
cptr = cmbd->chunk_ptr;
|
||||
|
||||
/* Clear all chunk tags */
|
||||
for (i = 0; i < chunks; i++) {
|
||||
CTAG_SET(cptr[i], CT_UNTAGGED);
|
||||
}
|
||||
for (i = 0; i < chunks && cmbd->cmblk_size < cmbd->req_size; i++) {
|
||||
/* First chunk must be an untagged chunk */
|
||||
if (CTAG_GET(cptr[i]) == CT_UNTAGGED) {
|
||||
/* Initial cmblock size is the chunk size */
|
||||
b = cptr[i];
|
||||
e = b + cmbd->chunk_size;
|
||||
CTAG_SET(cptr[i], CT_CURRENT);
|
||||
/* Loop looking for adjacent chunks */
|
||||
do {
|
||||
found = 0;
|
||||
for (j = i + 1; j < chunks && (e - b) < cmbd->req_size; j++) {
|
||||
a = cptr[j];
|
||||
/* Check untagged chunks only */
|
||||
if (CTAG_GET(a) == CT_UNTAGGED) {
|
||||
if (a == (b - cmbd->chunk_size)) {
|
||||
/* Found adjacent chunk below current cmblock */
|
||||
CTAG_SET(cptr[j], CT_CURRENT);
|
||||
b = a;
|
||||
found = 1;
|
||||
} else if (a == e) {
|
||||
/* Found adjacent chunk above current cmblock */
|
||||
CTAG_SET(cptr[j], CT_CURRENT);
|
||||
e += cmbd->chunk_size;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
/* Now check the size of the assembled memory block */
|
||||
if ((e - b) > cmbd->cmblk_size) {
|
||||
/* The current block is largest so far */
|
||||
cmbd->cmblk_begin = b;
|
||||
cmbd->cmblk_end = e;
|
||||
cmbd->cmblk_size = e - b;
|
||||
/* Re-tag current and previous largest cmblock */
|
||||
for (j = 0; j < chunks; j++) {
|
||||
if (CTAG_GET(cptr[j]) == CT_CURRENT) {
|
||||
/* Tag current cmblock as the largest */
|
||||
CTAG_SET(cptr[j], CT_LARGEST);
|
||||
} else if (CTAG_GET(cptr[j]) == CT_LARGEST) {
|
||||
/* Discard previous largest cmblock */
|
||||
CTAG_SET(cptr[j], CT_DISCARDED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Discard all chunks in current cmblock */
|
||||
for (j = 0; j < chunks; j++) {
|
||||
if (CTAG_GET(cptr[j]) == CT_CURRENT) {
|
||||
CTAG_SET(cptr[j], CT_DISCARDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Allocate memory chunks and add them to the pool.
|
||||
*
|
||||
* Memory chunks are allocated using the kernel page allocator.
|
||||
*
|
||||
* \param [in] cmbd - cmblock descriptor.
|
||||
* \param [in] chunks - Number of memory chunks to allocate.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
static int
|
||||
alloc_mem_chunks(cmblock_desc_t *cmbd, int chunks)
|
||||
{
|
||||
int i, start;
|
||||
unsigned long addr;
|
||||
|
||||
if (cmbd->chunk_cnt + chunks > cmbd->chunk_cnt_max) {
|
||||
printk("PGMEM: No more memory chunks\n");
|
||||
return -1;
|
||||
}
|
||||
start = cmbd->chunk_cnt;
|
||||
cmbd->chunk_cnt += chunks;
|
||||
for (i = start; i < cmbd->chunk_cnt; i++) {
|
||||
/* Get chunk from kernel allocator */
|
||||
addr = __get_free_pages(GFP_KERNEL | GFP_DMA32, cmbd->chunk_order);
|
||||
PGMEM_TRACE(".");
|
||||
if (addr) {
|
||||
cmbd->chunk_ptr[i] = addr;
|
||||
} else {
|
||||
printk("PGMEM: Page memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Allocate large physically contiguous memory block.
|
||||
*
|
||||
* If we cannot allocate a sufficiently large block of contiguous
|
||||
* memory from the kernel, then we simply keep allocating smaller
|
||||
* chunks until we can assemble a contiguous block of the desired
|
||||
* size.
|
||||
*
|
||||
* When maximum amount of system memory has been allocated without the
|
||||
* successful assembly of a contiguous memory block, the allocation
|
||||
* function will return the largest contiguous block found so far. It
|
||||
* is then up to the calling function to decide whether this amount is
|
||||
* sufficient to proceed.
|
||||
*
|
||||
* \param [in] size Requested memory block size.
|
||||
* \param [in] chunk_size Assemble cmblock from chunks of this size.
|
||||
*
|
||||
* \return Pointer to cmblock descriptor, or NULL if error.
|
||||
*/
|
||||
static cmblock_desc_t *
|
||||
cmblock_alloc(size_t size, size_t chunk_size)
|
||||
{
|
||||
cmblock_desc_t *cmbd;
|
||||
int i, chunk_ptr_size;
|
||||
unsigned long page_addr;
|
||||
struct sysinfo si;
|
||||
|
||||
/* Sanity check */
|
||||
if (size == 0 || chunk_size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an initialize memory cmblock descriptor */
|
||||
if ((cmbd = kmalloc(sizeof(cmblock_desc_t), GFP_KERNEL)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(cmbd, 0, sizeof(*cmbd));
|
||||
cmbd->req_size = size;
|
||||
cmbd->chunk_size = PAGE_ALIGN(chunk_size);
|
||||
while ((PAGE_SIZE << cmbd->chunk_order) < cmbd->chunk_size) {
|
||||
cmbd->chunk_order++;
|
||||
}
|
||||
|
||||
/* Determine the maximum possible number of memory chunks */
|
||||
si_meminfo(&si);
|
||||
cmbd->chunk_cnt_max = (si.totalram << PAGE_SHIFT) / cmbd->chunk_size;
|
||||
chunk_ptr_size = cmbd->chunk_cnt_max * sizeof(unsigned long);
|
||||
|
||||
/* Allocate an initialize memory chunk pool */
|
||||
cmbd->chunk_ptr = kmalloc(chunk_ptr_size, GFP_KERNEL);
|
||||
if (cmbd->chunk_ptr == NULL) {
|
||||
kfree(cmbd);
|
||||
return NULL;
|
||||
}
|
||||
memset(cmbd->chunk_ptr, 0, chunk_ptr_size);
|
||||
|
||||
/* Allocate minimum number of memory chunks */
|
||||
(void)alloc_mem_chunks(cmbd, cmbd->req_size / cmbd->chunk_size);
|
||||
|
||||
/* Allocate more chunks until we have a complete cmblock */
|
||||
do {
|
||||
find_largest_cmblock(cmbd);
|
||||
PGMEM_TRACE("o");
|
||||
if (cmbd->cmblk_size >= cmbd->req_size) {
|
||||
break;
|
||||
}
|
||||
} while (alloc_mem_chunks(cmbd, 8) == 0);
|
||||
|
||||
/* Reserve all pages in the cmblock and free unused chunks */
|
||||
for (i = 0; i < cmbd->chunk_cnt; i++) {
|
||||
if (CTAG_GET(cmbd->chunk_ptr[i]) == CT_LARGEST) {
|
||||
CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED);
|
||||
for (page_addr = cmbd->chunk_ptr[i];
|
||||
page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size;
|
||||
page_addr += PAGE_SIZE) {
|
||||
SetPageReserved(virt_to_page((void *)page_addr));
|
||||
}
|
||||
} else if (cmbd->chunk_ptr[i]) {
|
||||
CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED);
|
||||
free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order);
|
||||
PGMEM_TRACE("x");
|
||||
cmbd->chunk_ptr[i] = 0;
|
||||
}
|
||||
}
|
||||
PGMEM_TRACE("O\n");
|
||||
return cmbd;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Free cmblock and associated resources.
|
||||
*
|
||||
* Free all memory chunks and other associated resources associated
|
||||
* with a contiguous memory block.
|
||||
*
|
||||
* See alse \ref cmblock_alloc.
|
||||
*
|
||||
* \param [in] cmbd Command block descriptor to free.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
static void
|
||||
cmblock_free(cmblock_desc_t *cmbd)
|
||||
{
|
||||
int i;
|
||||
unsigned long page_addr;
|
||||
|
||||
if (cmbd->chunk_ptr) {
|
||||
for (i = 0; i < cmbd->chunk_cnt; i++) {
|
||||
if (cmbd->chunk_ptr[i]) {
|
||||
for (page_addr = cmbd->chunk_ptr[i];
|
||||
page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size;
|
||||
page_addr += PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page((void *)page_addr));
|
||||
}
|
||||
free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order);
|
||||
PGMEM_TRACE("X");
|
||||
}
|
||||
}
|
||||
kfree(cmbd->chunk_ptr);
|
||||
kfree(cmbd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Public Functions
|
||||
******************************************************************************/
|
||||
|
||||
void *
|
||||
ngbde_pgmem_alloc(size_t size, gfp_t flags)
|
||||
{
|
||||
cmblock_desc_t *cmbd;
|
||||
size_t chunk_size;
|
||||
|
||||
chunk_size = size;
|
||||
|
||||
if (pgmem_chunk_size > 0) {
|
||||
chunk_size = pgmem_chunk_size * ONE_KB;
|
||||
}
|
||||
|
||||
if (chunk_size > MEM_CHUNK_SIZE_MAX) {
|
||||
chunk_size = MEM_CHUNK_SIZE_DEFAULT;
|
||||
}
|
||||
|
||||
if (pgmem_debug) {
|
||||
printk("PGMEM: Allocate %d MB in %d KB chunks\n",
|
||||
(int)(size / ONE_MB), (int)(chunk_size / ONE_KB));
|
||||
}
|
||||
|
||||
if ((cmbd = cmblock_alloc(size, chunk_size)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (cmbd->cmblk_size < size) {
|
||||
/* If we didn't get the full size then forget it */
|
||||
cmblock_free(cmbd);
|
||||
return NULL;
|
||||
}
|
||||
list_add(&cmbd->list, &cmblocks_list);
|
||||
return (void *)cmbd->cmblk_begin;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_pgmem_free(void *ptr)
|
||||
{
|
||||
struct list_head *pos;
|
||||
|
||||
list_for_each(pos, &cmblocks_list) {
|
||||
cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list);
|
||||
if (ptr == (void *)cmbd->cmblk_begin) {
|
||||
list_del(&cmbd->list);
|
||||
cmblock_free(cmbd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_pgmem_free_all(void)
|
||||
{
|
||||
struct list_head *pos, *tmp;
|
||||
|
||||
list_for_each_safe(pos, tmp, &cmblocks_list) {
|
||||
cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list);
|
||||
list_del(&cmbd->list);
|
||||
cmblock_free(cmbd);
|
||||
}
|
||||
}
|
97
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c
Normal file
97
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*! \file ngbde_pio.c
|
||||
*
|
||||
* API for managing and accessing memory-mapped I/O for switch
|
||||
* registers.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
void *
|
||||
ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->pio_mem) {
|
||||
if (addr == sd->pio_win.addr && size == sd->pio_win.size) {
|
||||
/* Already mapped */
|
||||
return sd->pio_mem;
|
||||
}
|
||||
ngbde_pio_unmap(devh);
|
||||
}
|
||||
|
||||
sd->pio_mem = ioremap_nocache(addr, size);
|
||||
|
||||
if (sd->pio_mem) {
|
||||
/* Save mapped resources */
|
||||
sd->pio_win.addr = addr;
|
||||
sd->pio_win.size = size;
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: Unable to map address 0x%08lu\n",
|
||||
MOD_NAME, (unsigned long)addr);
|
||||
}
|
||||
|
||||
return sd->pio_mem;
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_pio_unmap(void *devh)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->pio_mem) {
|
||||
iounmap(sd->pio_mem);
|
||||
sd->pio_mem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_pio_cleanup(void)
|
||||
{
|
||||
struct ngbde_dev_s *swdev, *sd;
|
||||
unsigned int num_swdev, idx;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
sd = ngbde_swdev_get(idx);
|
||||
ngbde_pio_unmap(sd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->pio_mem) {
|
||||
NGBDE_IOWRITE32(val, sd->pio_mem + offs);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ngbde_pio_read32(void *devh, uint32_t offs)
|
||||
{
|
||||
struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh;
|
||||
|
||||
if (sd->pio_mem) {
|
||||
return NGBDE_IOREAD32(sd->pio_mem + offs);
|
||||
}
|
||||
return 0;
|
||||
}
|
120
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c
Normal file
120
platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*! \file ngbde_procfs.c
|
||||
*
|
||||
* <description>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
static int
|
||||
proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngbde_dev_s *swdev;
|
||||
unsigned int num_swdev, idx;
|
||||
struct ngbde_dmamem_s *dmamem;
|
||||
unsigned int pool;
|
||||
unsigned int dma_pools;
|
||||
char *dma_str;
|
||||
|
||||
ngbde_swdev_get_all(&swdev, &num_swdev);
|
||||
|
||||
seq_printf(m, "Broadcom Device Enumerator (%s)\n", MOD_NAME);
|
||||
|
||||
seq_printf(m, "Found %d switch device(s):\n", num_swdev);
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
if (swdev->inactive) {
|
||||
seq_printf(m, "%d:removed\n", idx);
|
||||
continue;
|
||||
}
|
||||
seq_printf(m, "%d:%04x:%04x:%02x,%s(%d)\n", idx,
|
||||
swdev->vendor_id, swdev->device_id, swdev->revision,
|
||||
swdev->use_msi ? "MSI" : "IRQ", swdev->irq_line);
|
||||
}
|
||||
|
||||
seq_printf(m, "DMA pools:\n");
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
seq_printf(m, "%d", idx);
|
||||
dma_pools = 0;
|
||||
for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) {
|
||||
dmamem = &swdev[idx].dmapool[pool].dmamem;
|
||||
dma_str = "unknown";
|
||||
if (dmamem->type == NGBDE_DMA_T_NONE) {
|
||||
/* Skip empty DMA pools */
|
||||
continue;
|
||||
} else if (dmamem->type == NGBDE_DMA_T_KAPI) {
|
||||
dma_str = "kapi";
|
||||
} else if (dmamem->type == NGBDE_DMA_T_PGMEM) {
|
||||
dma_str = "pgmem";
|
||||
}
|
||||
seq_printf(m, ":%dMB@0x%08lx(%s)",
|
||||
(int)(dmamem->size / ONE_MB),
|
||||
(unsigned long)dmamem->baddr, dma_str);
|
||||
dma_pools++;
|
||||
}
|
||||
if (dma_pools == 0) {
|
||||
seq_printf(m, ":none");
|
||||
}
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_release,
|
||||
};
|
||||
|
||||
int
|
||||
ngbde_procfs_init(void)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
PROC_CREATE(entry, MOD_NAME, 0666, NULL, &proc_fops);
|
||||
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngbde: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_procfs_cleanup(void)
|
||||
{
|
||||
remove_proc_entry(MOD_NAME, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*! \file ngbde_swdev.c
|
||||
*
|
||||
* <description>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <ngbde.h>
|
||||
|
||||
/* Switch devices */
|
||||
static struct ngbde_dev_s swdevs[NGBDE_NUM_SWDEV_MAX];
|
||||
|
||||
/* Number of probed switch devices */
|
||||
static unsigned int num_swdev;
|
||||
|
||||
int
|
||||
ngbde_swdev_add(struct ngbde_dev_s *nd)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
/* Look for existing slot */
|
||||
for (idx = 0; idx < num_swdev; idx++) {
|
||||
if (swdevs[idx].bus_no == nd->bus_no &&
|
||||
swdevs[idx].slot_no == nd->slot_no) {
|
||||
if (swdevs[idx].inactive) {
|
||||
memcpy(&swdevs[idx], nd, sizeof(swdevs[0]));
|
||||
return 0;
|
||||
}
|
||||
/* Active device in this slot already? */
|
||||
printk(KERN_WARNING "%s: Device exists\n",
|
||||
MOD_NAME);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add new device */
|
||||
if (num_swdev >= NGBDE_NUM_SWDEV_MAX) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(&swdevs[num_swdev], nd, sizeof(swdevs[0]));
|
||||
++num_swdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ngbde_dev_s *
|
||||
ngbde_swdev_get(int kdev)
|
||||
{
|
||||
if ((unsigned int)kdev < num_swdev) {
|
||||
return &swdevs[kdev];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd)
|
||||
{
|
||||
if (nd) {
|
||||
*nd = swdevs;
|
||||
}
|
||||
if (num_nd) {
|
||||
*num_nd = num_swdev;
|
||||
}
|
||||
return 0;
|
||||
}
|
126
platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h
Normal file
126
platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h
Normal file
@ -0,0 +1,126 @@
|
||||
/*! \file lkm.h
|
||||
*
|
||||
* <description>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef LKM_H
|
||||
#define LKM_H
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#error Kernel too old
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
|
||||
#include <linux/kconfig.h>
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
||||
#include <linux/slab.h>
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
|
||||
#include <linux/smp_lock.h>
|
||||
#endif
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hardirq.h>
|
||||
|
||||
#ifdef CONFIG_DEVFS_FS
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#endif
|
||||
|
||||
/* Compatibility Macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
||||
#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \
|
||||
do { \
|
||||
_entry = proc_create(_name, _acc, _path, _fops); \
|
||||
} while (0)
|
||||
|
||||
#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \
|
||||
do { \
|
||||
_entry = proc_create_data(_name, _acc, _path, _fops, _data); \
|
||||
} while (0)
|
||||
|
||||
#define PROC_PDE_DATA(_node) PDE_DATA(_node)
|
||||
#else
|
||||
#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \
|
||||
do { \
|
||||
_entry = create_proc_entry(_name, _acc, _path); \
|
||||
if (_entry) { \
|
||||
_entry->proc_fops = _fops; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \
|
||||
do { \
|
||||
_entry = create_proc_entry(_name, _acc, _path); \
|
||||
if (_entry) { \
|
||||
_entry->proc_fops = _fops; \
|
||||
_entry->data=_data; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PROC_PDE_DATA(_node) PROC_I(_node)->pde->data
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
|
||||
#define timer_arg(var, context, timer_fieldname) \
|
||||
(typeof(var))(context)
|
||||
#define timer_context_t unsigned long
|
||||
#else
|
||||
#define timer_context_t struct timer_list *
|
||||
#define timer_arg(var, context, timer_fieldname) \
|
||||
from_timer(var, context, timer_fieldname)
|
||||
#endif
|
||||
|
||||
#ifndef setup_timer
|
||||
#define setup_timer(timer, fn, data) \
|
||||
timer_setup(timer, fn, 0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0)
|
||||
static inline void page_ref_inc(struct page *page)
|
||||
{
|
||||
atomic_inc(&page->_count);
|
||||
}
|
||||
|
||||
static inline void page_ref_dec(struct page *page)
|
||||
{
|
||||
atomic_dec(&page->_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LKM_H */
|
@ -0,0 +1,345 @@
|
||||
/*! \file ngbde_ioctl.h
|
||||
*
|
||||
* NGBDE device I/O control definitions.
|
||||
*
|
||||
* This file is intended for use in both kernel mode and user mode.
|
||||
*
|
||||
* IMPORTANT!
|
||||
* All shared structures must be properly 64-bit aligned.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGBDE_IOCTL_H
|
||||
#define NGBDE_IOCTL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/*! Must be updated if backward compatibility is broken. */
|
||||
#define NGBDE_IOC_VERSION 2
|
||||
|
||||
/*! LUBDE IOCTL command magic. */
|
||||
#define NGBDE_IOC_MAGIC 'L'
|
||||
|
||||
/*!
|
||||
* \name IOCTL commands for the NGBDE kernel module.
|
||||
* \anchor NGBDE_IOC_xxx
|
||||
*
|
||||
* Note that we use __u64 for the IOCTL parameter size because
|
||||
* sizeof(void *) is different between 32-bit and 64-bit code, and we
|
||||
* need a 32-bit user mode application to generate the same IOCTL
|
||||
* command codes as a 64-bit kernel when using the _IOW macro.
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! Get kernel module information. */
|
||||
#define NGBDE_IOC_MOD_INFO _IOW(NGBDE_IOC_MAGIC, 0, __u64)
|
||||
|
||||
/*! Get information about registered devices. */
|
||||
#define NGBDE_IOC_PROBE_INFO _IOW(NGBDE_IOC_MAGIC, 1, __u64)
|
||||
|
||||
/*! Get detailed switch device information. */
|
||||
#define NGBDE_IOC_DEV_INFO _IOW(NGBDE_IOC_MAGIC, 2, __u64)
|
||||
|
||||
/*! Get a physical memory address associated with a switch device. */
|
||||
#define NGBDE_IOC_PHYS_ADDR _IOW(NGBDE_IOC_MAGIC, 3, __u64)
|
||||
|
||||
/*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */
|
||||
#define NGBDE_IOC_INTR_CTRL _IOW(NGBDE_IOC_MAGIC, 4, __u64)
|
||||
|
||||
/*! Add interrupt status/mask register for kernel to control. */
|
||||
#define NGBDE_IOC_IRQ_REG_ADD _IOW(NGBDE_IOC_MAGIC, 5, __u64)
|
||||
|
||||
/*! Write to a shared interrupt mask register. */
|
||||
#define NGBDE_IOC_IRQ_MASK_WR _IOW(NGBDE_IOC_MAGIC, 6, __u64)
|
||||
|
||||
/*! Map device registers in kernel space. */
|
||||
#define NGBDE_IOC_PIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 7, __u64)
|
||||
|
||||
/*! Map interrupt controller registers in kernel space. */
|
||||
#define NGBDE_IOC_IIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 8, __u64)
|
||||
|
||||
/*! Map PCI bridge registers in kernel space. */
|
||||
#define NGBDE_IOC_PAXB_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 9, __u64)
|
||||
|
||||
/*! Add interrupt ACK register for kernel to control. */
|
||||
#define NGBDE_IOC_INTR_ACK_REG_ADD _IOW(NGBDE_IOC_MAGIC, 10, __u64)
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*! IOCTL command return code for success. */
|
||||
#define NGBDE_IOC_SUCCESS 0
|
||||
|
||||
/*! IOCTL command return code for failure. */
|
||||
#define NGBDE_IOC_FAIL ((__u32)-1)
|
||||
|
||||
/*!
|
||||
* \name Device flags.
|
||||
* \anchor NGBDE_DEV_F_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! Message-signaled interrupts, PCI interrupts are operating in MSI mode. */
|
||||
#define NGBDE_DEV_F_MSI (1 << 0)
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \name Interrupt control commands.
|
||||
* \anchor NGBDE_ICTL_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! Connect interrupt handler. */
|
||||
#define NGBDE_ICTL_INTR_CONN 0
|
||||
|
||||
/*! Disconnect interrupt handler. */
|
||||
#define NGBDE_ICTL_INTR_DISC 1
|
||||
|
||||
/*! Wait for interrupt. */
|
||||
#define NGBDE_ICTL_INTR_WAIT 2
|
||||
|
||||
/*! Force waiting thread to return. */
|
||||
#define NGBDE_ICTL_INTR_STOP 3
|
||||
|
||||
/*! Clear list of interrupt status/mask registers. */
|
||||
#define NGBDE_ICTL_REGS_CLR 4
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*! Kernel module information. */
|
||||
struct ngbde_ioc_mod_info_s {
|
||||
|
||||
/*! IOCTL version used by kernel module. */
|
||||
__u16 version;
|
||||
};
|
||||
|
||||
/*! Probing results. */
|
||||
struct ngbde_ioc_probe_info_s {
|
||||
|
||||
/*! Number of switch devices. */
|
||||
__u16 num_swdev;
|
||||
};
|
||||
|
||||
/*! Device information. */
|
||||
struct ngbde_ioc_dev_info_s {
|
||||
|
||||
/*! Device type. */
|
||||
__u16 type;
|
||||
|
||||
/*! Device flags (\ref NGBDE_DEV_F_xxx). */
|
||||
__u16 flags;
|
||||
|
||||
/*! Vendor ID (typically the PCI vendor ID). */
|
||||
__u16 vendor_id;
|
||||
|
||||
/*! Device ID (typically the PCI vendor ID). */
|
||||
__u16 device_id;
|
||||
|
||||
/*! Device revision (typically the PCI device revision). */
|
||||
__u16 revision;
|
||||
|
||||
/*! Device model (device-identification beyond PCI generic ID). */
|
||||
__u16 model;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \name I/O resource types.
|
||||
* \anchor NGBDE_IO_RSRC_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! Memory-mapped I/O. */
|
||||
#define NGBDE_IO_RSRC_DEV_IO 0
|
||||
|
||||
/*! DMA memory pool. */
|
||||
#define NGBDE_IO_RSRC_DMA_MEM 1
|
||||
|
||||
/*! DMA memory pool as mapped by IOMMU. */
|
||||
#define NGBDE_IO_RSRC_DMA_BUS 2
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*!
|
||||
* \brief Resource ID (IOCTL input).
|
||||
*
|
||||
* This structure is used to query a physical address resource in the
|
||||
* kernel module. The caller must provide a resource type (device I/O,
|
||||
* DMA memory, etc.) and a resource instance number (e.g. a PCI BAR
|
||||
* address will have multiple instances).
|
||||
*
|
||||
* Also see \ref ngbde_ioc_phys_addr_s.
|
||||
*/
|
||||
struct ngbde_ioc_rsrc_id_s {
|
||||
|
||||
/*! Resource type (\ref NGBDE_IO_RSRC_xxx). */
|
||||
__u32 type;
|
||||
|
||||
/*! Resource instance number. */
|
||||
__u32 inst;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Physical device address.
|
||||
*
|
||||
* This structure is returned in response to the \ref
|
||||
* NGBDE_IOC_PHYS_ADDR command. The caller must identify the requested
|
||||
* physical address using the \ref ngbde_ioc_rsrc_id_s structure.
|
||||
*/
|
||||
struct ngbde_ioc_phys_addr_s {
|
||||
|
||||
/*! Physical address. */
|
||||
__u64 addr;
|
||||
|
||||
/*! Resource size (in bytes). */
|
||||
__u32 size;
|
||||
};
|
||||
|
||||
/*! Interrupt control operation */
|
||||
struct ngbde_ioc_intr_ctrl_s {
|
||||
|
||||
/*! Interrupt instance for this device. */
|
||||
__u32 irq_num;
|
||||
|
||||
/*! Interrupt control command. */
|
||||
__u32 cmd;
|
||||
};
|
||||
|
||||
/*! Add interrupt register information. */
|
||||
struct ngbde_ioc_irq_reg_add_s {
|
||||
|
||||
/*! Interrupt instance for this device. */
|
||||
__u32 irq_num;
|
||||
|
||||
/*! Interrupt status register address offset. */
|
||||
__u32 status_reg;
|
||||
|
||||
/*! Interrupt mask register address offset. */
|
||||
__u32 mask_reg;
|
||||
|
||||
/*! Interrupt mask for interrupts handled by the kernel. */
|
||||
__u32 kmask;
|
||||
|
||||
/*! Reserved for future use. */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \name Interrupt ACK register access flags.
|
||||
* \anchor NGBDE_DEV_INTR_ACK_F_xxx
|
||||
*/
|
||||
|
||||
/*! \{ */
|
||||
|
||||
/*! ACK registers resides in PCI bridge I/O window. */
|
||||
#define NGBDE_DEV_INTR_ACK_F_PAXB (1 << 0)
|
||||
|
||||
/*! \} */
|
||||
|
||||
/*! Add interrupt ACK register information. */
|
||||
struct ngbde_ioc_intr_ack_reg_add_s {
|
||||
|
||||
/*! Interrupt instance for this device. */
|
||||
__u32 irq_num;
|
||||
|
||||
/*! Interrupt ACK register address offset. */
|
||||
__u32 ack_reg;
|
||||
|
||||
/*! Interrupt ACK value. */
|
||||
__u32 ack_val;
|
||||
|
||||
/*! Flags to indicate ack_reg resides in PCI bridge window. */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/*! Memory-mapped I/O window */
|
||||
struct ngbde_ioc_pio_win_s {
|
||||
|
||||
/*! Physical address */
|
||||
__u64 addr;
|
||||
|
||||
/*! Resource size */
|
||||
__u32 size;
|
||||
};
|
||||
|
||||
/*! Interrupt mask register write */
|
||||
struct ngbde_ioc_irq_mask_wr_s {
|
||||
|
||||
/*! Interrupt instance for this device. */
|
||||
__u32 irq_num;
|
||||
|
||||
/*! Register offset. */
|
||||
__u32 offs;
|
||||
|
||||
/*! Value to write. */
|
||||
__u32 val;
|
||||
};
|
||||
|
||||
/*! IOCTL operation data. */
|
||||
union ngbde_ioc_op_s {
|
||||
|
||||
/*! Get kernel module information. */
|
||||
struct ngbde_ioc_mod_info_s mod_info;
|
||||
|
||||
/*! Get information about registered devices. */
|
||||
struct ngbde_ioc_probe_info_s probe_info;
|
||||
|
||||
/*! Get detailed switch device information. */
|
||||
struct ngbde_ioc_dev_info_s dev_info;
|
||||
|
||||
/*! Resource ID (input). */
|
||||
struct ngbde_ioc_rsrc_id_s rsrc_id;
|
||||
|
||||
/*! Get a physical memory address associated with a switch device. */
|
||||
struct ngbde_ioc_phys_addr_s phys_addr;
|
||||
|
||||
/*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */
|
||||
struct ngbde_ioc_intr_ctrl_s intr_ctrl;
|
||||
|
||||
/*! Add interrupt status/mask register for kernel to control. */
|
||||
struct ngbde_ioc_irq_reg_add_s irq_reg_add;
|
||||
|
||||
/*! Add interrupt ACK register for kernel to control. */
|
||||
struct ngbde_ioc_intr_ack_reg_add_s intr_ack_reg_add;
|
||||
|
||||
/*! Write to a shared interrupt mask register. */
|
||||
struct ngbde_ioc_irq_mask_wr_s irq_mask_wr;
|
||||
|
||||
/*! Map device registers in kernel space. */
|
||||
struct ngbde_ioc_pio_win_s pio_win;
|
||||
};
|
||||
|
||||
/*! IOCTL command message. */
|
||||
typedef struct ngbde_ioc_cmd_s {
|
||||
|
||||
/*! Device handle. */
|
||||
__u32 devid;
|
||||
|
||||
/*! Return code (0 means success). */
|
||||
__u32 rc;
|
||||
|
||||
/*! IOCTL operation. */
|
||||
union ngbde_ioc_op_s op;
|
||||
} ngbde_ioc_cmd_t;
|
||||
|
||||
#endif /* NGBDE_IOCTL_H */
|
@ -0,0 +1,169 @@
|
||||
/*! \file ngbde_kapi.h
|
||||
*
|
||||
* NGBDE kernel API.
|
||||
*
|
||||
* This file is intended for use by other kernel modules relying on the BDE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGBDE_KAPI_H
|
||||
#define NGBDE_KAPI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*! Maximum number of switch devices supported. */
|
||||
#ifndef NGBDE_NUM_SWDEV_MAX
|
||||
#define NGBDE_NUM_SWDEV_MAX 16
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Get Linux PCI device handle for a switch device.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
*
|
||||
* \return Linux PCI device handle or NULL if unavailable.
|
||||
*/
|
||||
extern struct pci_dev *
|
||||
ngbde_kapi_pci_dev_get(int kdev);
|
||||
|
||||
/*!
|
||||
* \brief Get Linux kernel device handle for a switch device.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
*
|
||||
* \return Linux kernel device handle or NULL if unavailable.
|
||||
*/
|
||||
extern struct device *
|
||||
ngbde_kapi_dma_dev_get(int kdev);
|
||||
|
||||
/*!
|
||||
* \brief Convert DMA bus address to virtual address.
|
||||
*
|
||||
* This API will convert a physical DMA bus address to a kernel
|
||||
* virtual address for a memory location that belongs to one of the
|
||||
* DMA memory pools allocated by the BDE module.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] baddr Physical DMA bus address for this device.
|
||||
*
|
||||
* \return Virtual kernel address or NULL on error.
|
||||
*/
|
||||
void *
|
||||
ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr);
|
||||
|
||||
/*!
|
||||
* \brief Convert virtual address to DMA bus address.
|
||||
*
|
||||
* This API will convert a kernel virtual address to a physical DMA
|
||||
* bus address for a memory location that belongs to one of the DMA
|
||||
* memory pools allocated by the BDE module.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] vaddr Virtual kernel address.
|
||||
*
|
||||
* \return Physical DMA bus address for this device or 0 on error.
|
||||
*/
|
||||
dma_addr_t
|
||||
ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr);
|
||||
|
||||
/*!
|
||||
* \brief Write a memory-mapped register from kernel driver.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] offs Register address offset.
|
||||
* \param [in] val Value to write to register.
|
||||
*
|
||||
* \return Nothing.
|
||||
*/
|
||||
extern void
|
||||
ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val);
|
||||
|
||||
/*!
|
||||
* \brief Read a memory-mapped register from kernel driver.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] offs Register address offset.
|
||||
*
|
||||
* \return Value read from register.
|
||||
*/
|
||||
extern uint32_t
|
||||
ngbde_kapi_pio_read32(int kdev, uint32_t offs);
|
||||
|
||||
/*!
|
||||
* \brief Get base address fo memory-mapped I/O memory.
|
||||
*
|
||||
* The lgical base address returned can be used with ioread32, etc.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
*
|
||||
* \return Logical base address or NULL if unavailable.
|
||||
*/
|
||||
extern void *
|
||||
ngbde_kapi_pio_membase(int kdev);
|
||||
|
||||
/*!
|
||||
* \brief Install kernel mode interrupt handler.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num MSI interrupt number.
|
||||
* \param [in] isr_func Interrupt handler function.
|
||||
* \param [in] isr_data Interrupt handler context.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
*/
|
||||
extern int
|
||||
ngbde_kapi_intr_connect(int kdev, unsigned int irq_num,
|
||||
int (*isr_func)(void *), void *isr_data);
|
||||
|
||||
/*!
|
||||
* \brief Uninstall kernel mode interrupt handler.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num MSI interrupt number.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
*/
|
||||
extern int
|
||||
ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num);
|
||||
|
||||
/*!
|
||||
* \brief Write shared interrupt mask register.
|
||||
*
|
||||
* This function is used by an interrupt handler when a shared
|
||||
* interrupt mask register needs to be updated.
|
||||
*
|
||||
* Note that the mask register to access is referenced by the
|
||||
* corrsponding status register. This is because the mask register may
|
||||
* be different depending on the host CPU interface being used
|
||||
* (e.g. PCI vs. AXI). On the other hand, the status register is the
|
||||
* same irrespective of the host CPU interface.
|
||||
*
|
||||
* \param [in] kdev Device number.
|
||||
* \param [in] irq_num Interrupt number (MSI vector).
|
||||
* \param [in] status_reg Corresponding interrupt status register offset.
|
||||
* \param [in] mask_val New value to write to mask register.
|
||||
*
|
||||
* \retval 0 No errors
|
||||
* \retval -1 Something went wrong.
|
||||
*/
|
||||
extern int
|
||||
ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num,
|
||||
uint32_t status_reg, uint32_t mask_val);
|
||||
|
||||
#endif /* NGBDE_KAPI_H */
|
@ -0,0 +1,408 @@
|
||||
/*! \file ngknet_dev.h
|
||||
*
|
||||
* NGKNET device definitions.
|
||||
*
|
||||
* This file is intended for use in both kernel mode and user mode.
|
||||
*
|
||||
* IMPORTANT!
|
||||
* All shared structures must be properly 64-bit aligned.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_DEV_H
|
||||
#define NGKNET_DEV_H
|
||||
|
||||
#include <bcmcnet/bcmcnet_types.h>
|
||||
|
||||
/*! Device name length */
|
||||
#define NGKNET_DEV_NAME_MAX 16
|
||||
|
||||
/*! Maximum number of virtual network devices */
|
||||
#ifndef NGKNET_NETIF_MAX
|
||||
#define NUM_VDEV_MAX 128
|
||||
#else
|
||||
#define NUM_VDEV_MAX NGKNET_NETIF_MAX
|
||||
#endif
|
||||
|
||||
/*! Maximum number of filters */
|
||||
#ifndef NGKNET_FILTER_MAX
|
||||
#define NUM_FILTER_MAX 128
|
||||
#else
|
||||
#define NUM_FILTER_MAX NGKNET_FILTER_MAX
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief System network interface
|
||||
*
|
||||
* Network interface types:
|
||||
*
|
||||
* NGKNET_NETIF_T_VLAN
|
||||
* Transmits to this interface will go to ingress PIPE of switch
|
||||
* CPU port using specified VLAN ID. Packet will be switched.
|
||||
*
|
||||
* NGKNET_NETIF_T_PORT
|
||||
* Transmits to this interface will go to unmodified to specified
|
||||
* physical switch port. All switching logic is bypassed. Meta data
|
||||
* should be provided when this interface is created.
|
||||
*
|
||||
* NGKNET_NETIF_T_META
|
||||
* Transmits to this interface will be done using raw meta data
|
||||
* as DMA descriptors.
|
||||
*
|
||||
* Network interface flags:
|
||||
*
|
||||
* NGKNET_NETIF_F_RCPU_ENCAP
|
||||
* Use RCPU encapsulation for packets that enter and exit this
|
||||
* interface.
|
||||
*
|
||||
* NGKNET_NETIF_F_ADD_TAG
|
||||
* Add VLAN tag to packets sent directly to physical port.
|
||||
*
|
||||
* NGKNET_NETIF_F_BIND_CHAN
|
||||
* Bind this interface to a Rx channel.
|
||||
*/
|
||||
/*! Max network interface name length */
|
||||
#define NGKNET_NETIF_NAME_MAX 16
|
||||
/*! Max network interface meta bytes */
|
||||
#define NGKNET_NETIF_META_MAX 16
|
||||
/*! Max netif user data in bytes */
|
||||
#define NGKNET_NETIF_USER_DATA 64
|
||||
|
||||
/*! Send packets to switch */
|
||||
#define NGKNET_NETIF_T_VLAN 0
|
||||
/*! Send packets to port */
|
||||
#define NGKNET_NETIF_T_PORT 1
|
||||
/*! Send packets with matadata attached */
|
||||
#define NGKNET_NETIF_T_META 2
|
||||
|
||||
/*! Send packets with RCPU encapsulation */
|
||||
#define NGKNET_NETIF_F_RCPU_ENCAP (1U << 0)
|
||||
/*! Send packets with vlan tag */
|
||||
#define NGKNET_NETIF_F_ADD_TAG (1U << 1)
|
||||
/*! Bind network interface to Rx channel */
|
||||
#define NGKNET_NETIF_F_BIND_CHAN (1U << 2)
|
||||
|
||||
/*!
|
||||
* \brief Network interface description.
|
||||
*/
|
||||
typedef struct ngknet_netif_s {
|
||||
/*! This network interface ID */
|
||||
uint16_t id;
|
||||
|
||||
/*! Next network interface ID */
|
||||
uint16_t next;
|
||||
|
||||
/*! Network interface type */
|
||||
uint16_t type;
|
||||
|
||||
/*! Network interface flags */
|
||||
uint16_t flags;
|
||||
|
||||
/*! Network interface VLAN ID */
|
||||
uint16_t vlan;
|
||||
|
||||
/*! Network interface MAC address */
|
||||
uint8_t macaddr[6];
|
||||
|
||||
/*! Network interface MTU */
|
||||
uint32_t mtu;
|
||||
|
||||
/*! Network interface bound to channel */
|
||||
uint32_t chan;
|
||||
|
||||
/*! Network interface name */
|
||||
char name[NGKNET_NETIF_NAME_MAX];
|
||||
|
||||
/*! Metadata offset from Ethernet header */
|
||||
uint16_t meta_off;
|
||||
|
||||
/*! Metadata length */
|
||||
uint16_t meta_len;
|
||||
|
||||
/*! Metadata used to send packets to physical port */
|
||||
uint8_t meta_data[NGKNET_NETIF_META_MAX];
|
||||
|
||||
/*! User data gotten back through callbacks */
|
||||
uint8_t user_data[NGKNET_NETIF_USER_DATA];
|
||||
} ngknet_netif_t;
|
||||
|
||||
/*!
|
||||
* \brief Packet filters
|
||||
*
|
||||
* Filters work like software TCAMs where a mask is applied to the
|
||||
* source data, and the result is then compared to the filter data.
|
||||
*
|
||||
* Filters are checked in priority order with the lowest priority
|
||||
* values being checked first (i.e. 0 is the highest priority).
|
||||
*
|
||||
* Filter types:
|
||||
*
|
||||
* NGKNET_FILTER_T_RX_PKT
|
||||
* Filter data and mask are applied to the Rx DMA control block
|
||||
* as well as to the Rx packet contents.
|
||||
*
|
||||
* Destination types:
|
||||
*
|
||||
* NGKNET_FILTER_DEST_T_NULL
|
||||
* Packet is dropped.
|
||||
*
|
||||
* NGKNET_FILTER_DEST_T_NETIF
|
||||
* Packet is sent to network interface with ID <dest_id>.
|
||||
*
|
||||
* NGKNET_FILTER_DEST_T_VNET
|
||||
* Packet is sent to VNET in user space.
|
||||
*
|
||||
* Filter flags:
|
||||
*
|
||||
* NGKNET_FILTER_F_ANY_DATA
|
||||
* When this flags is set the filter will match any packet on
|
||||
* the associated unit.
|
||||
*
|
||||
* NGKNET_FILTER_F_STRIP_TAG
|
||||
* Strip VLAN tag before packet is sent to destination.
|
||||
*/
|
||||
/*! Roundup to word */
|
||||
#define NGKNET_BYTES2WORDS(bytes) ((bytes + 3) / 4)
|
||||
|
||||
/*! Max filter description length */
|
||||
#define NGKNET_FILTER_DESC_MAX 32
|
||||
/*! Max filter bytes size */
|
||||
#define NGKNET_FILTER_BYTES_MAX 256
|
||||
/*! Max filter words size */
|
||||
#define NGKNET_FILTER_WORDS_MAX NGKNET_BYTES2WORDS(NGKNET_FILTER_BYTES_MAX)
|
||||
/*! Max filter user data in bytes */
|
||||
#define NGKNET_FILTER_USER_DATA 64
|
||||
|
||||
/*! Filter to Rx */
|
||||
#define NGKNET_FILTER_T_RX_PKT 1
|
||||
|
||||
/*! Drop packet */
|
||||
#define NGKNET_FILTER_DEST_T_NULL 0
|
||||
/*! Send packet to netif */
|
||||
#define NGKNET_FILTER_DEST_T_NETIF 1
|
||||
/*! Send packet to VNET */
|
||||
#define NGKNET_FILTER_DEST_T_VNET 2
|
||||
/*! Send packet to kernel callback function (BCMPKT_DEST_T_CALLBACK) */
|
||||
#define NGKNET_FILTER_DEST_T_CB 3
|
||||
|
||||
/*! Match any data */
|
||||
#define NGKNET_FILTER_F_ANY_DATA (1U << 0)
|
||||
/*! Strip vlan tag */
|
||||
#define NGKNET_FILTER_F_STRIP_TAG (1U << 1)
|
||||
/*! Match Rx channel */
|
||||
#define NGKNET_FILTER_F_MATCH_CHAN (1U << 2)
|
||||
/*! Filter created with raw metadata */
|
||||
#define NGKNET_FILTER_F_RAW_PMD (1U << 15)
|
||||
|
||||
/*!
|
||||
* \brief Filter description.
|
||||
*/
|
||||
typedef struct ngknet_filter_s {
|
||||
/*! This filter ID */
|
||||
uint16_t id;
|
||||
|
||||
/*! Next filter ID */
|
||||
uint16_t next;
|
||||
|
||||
/*! Filter type. Refer to \ref NGKNET_FILTER_T_XXX. */
|
||||
uint16_t type;
|
||||
|
||||
/*! Filter flags. Refer to \ref NGKNET_FILTER_F_XXX. */
|
||||
uint16_t flags;
|
||||
|
||||
/*! Filter priority */
|
||||
uint32_t priority;
|
||||
|
||||
/*! Filter belong to */
|
||||
uint32_t chan;
|
||||
|
||||
/*! Filter description */
|
||||
char desc[NGKNET_FILTER_DESC_MAX];
|
||||
|
||||
/*! Destination type. Refer to \ref NGKNET_FILTER_DEST_T_XXX. */
|
||||
uint16_t dest_type;
|
||||
|
||||
/*! Destination network interface ID */
|
||||
uint16_t dest_id;
|
||||
|
||||
/*! Destination network interface protocol type */
|
||||
uint16_t dest_proto;
|
||||
|
||||
/*! Mirror type */
|
||||
uint16_t mirror_type;
|
||||
|
||||
/*! Mirror network interface ID */
|
||||
uint16_t mirror_id;
|
||||
|
||||
/*! Mirror network interface protocol type */
|
||||
uint16_t mirror_proto;
|
||||
|
||||
/*! Out band data offset */
|
||||
uint16_t oob_data_offset;
|
||||
|
||||
/*! Out band data size */
|
||||
uint16_t oob_data_size;
|
||||
|
||||
/*! Packet data offset */
|
||||
uint16_t pkt_data_offset;
|
||||
|
||||
/*! Packet data size */
|
||||
uint16_t pkt_data_size;
|
||||
|
||||
/*! Filtering data */
|
||||
union {
|
||||
uint8_t b[NGKNET_FILTER_BYTES_MAX];
|
||||
uint32_t w[NGKNET_FILTER_WORDS_MAX];
|
||||
} data;
|
||||
|
||||
/*! Filtering mask */
|
||||
union {
|
||||
uint8_t b[NGKNET_FILTER_BYTES_MAX];
|
||||
uint32_t w[NGKNET_FILTER_WORDS_MAX];
|
||||
} mask;
|
||||
|
||||
/*! User data gotten back through callbacks */
|
||||
uint8_t user_data[NGKNET_FILTER_USER_DATA];
|
||||
} ngknet_filter_t;
|
||||
|
||||
/*!
|
||||
* \brief Device configure structure.
|
||||
*/
|
||||
typedef struct ngknet_dev_cfg_s {
|
||||
/*! Device name */
|
||||
char name[NGKNET_DEV_NAME_MAX];
|
||||
|
||||
/*! Device type string */
|
||||
char type_str[NGKNET_DEV_NAME_MAX];
|
||||
|
||||
/*! Device ID */
|
||||
uint32_t dev_id;
|
||||
|
||||
/*! Device mode */
|
||||
dev_mode_t mode;
|
||||
|
||||
/*! Number of groups */
|
||||
uint32_t nb_grp;
|
||||
|
||||
/*! Bitmap of groups */
|
||||
uint32_t bm_grp;
|
||||
|
||||
/*! Rx packet header size */
|
||||
uint32_t rx_ph_size;
|
||||
|
||||
/*! Tx packet header size */
|
||||
uint32_t tx_ph_size;
|
||||
|
||||
/*! Base network interface */
|
||||
ngknet_netif_t base_netif;
|
||||
} ngknet_dev_cfg_t;
|
||||
|
||||
/*!
|
||||
* \brief Channel configure structure.
|
||||
*/
|
||||
typedef struct ngknet_chan_cfg_s {
|
||||
/*! Channel number */
|
||||
int chan;
|
||||
|
||||
/*! Number of descriptors */
|
||||
uint32_t nb_desc;
|
||||
|
||||
/*! Rx buffer size */
|
||||
uint32_t rx_buf_size;
|
||||
|
||||
/*! Channel control */
|
||||
uint32_t chan_ctrl;
|
||||
/*! Packet_byte_swap */
|
||||
#define NGKNET_PKT_BYTE_SWAP (1 << 0)
|
||||
/*! Non packet_byte_swap */
|
||||
#define NGKNET_OTH_BYTE_SWAP (1 << 1)
|
||||
/*! Header_byte_swap */
|
||||
#define NGKNET_HDR_BYTE_SWAP (1 << 2)
|
||||
|
||||
/*! Rx or Tx */
|
||||
int dir;
|
||||
/*! Rx channel */
|
||||
#define NGKNET_RX_CHAN 0
|
||||
/*! Tx channel */
|
||||
#define NGKNET_TX_CHAN 1
|
||||
} ngknet_chan_cfg_t;
|
||||
|
||||
/*!
|
||||
* \brief RCPU header structure.
|
||||
*/
|
||||
struct ngknet_rcpu_hdr {
|
||||
/*! Destination MAC address */
|
||||
uint8_t dst_mac[6];
|
||||
|
||||
/*! Source MAC address */
|
||||
uint8_t src_mac[6];
|
||||
|
||||
/*! VLAN TPID */
|
||||
uint16_t vlan_tpid;
|
||||
|
||||
/*! VLAN TCI */
|
||||
uint16_t vlan_tci;
|
||||
|
||||
/*! Ethernet type */
|
||||
uint16_t eth_type;
|
||||
|
||||
/*! Packet signature */
|
||||
uint16_t pkt_sig;
|
||||
|
||||
/*! Operation code */
|
||||
uint8_t op_code;
|
||||
|
||||
/*! Flags */
|
||||
uint8_t flags;
|
||||
|
||||
/*! Transaction number */
|
||||
uint16_t trans_id;
|
||||
|
||||
/*! Packet data length */
|
||||
uint16_t data_len;
|
||||
|
||||
/*! Reserved must be 0 */
|
||||
uint16_t rsvd0;
|
||||
|
||||
/*! packet meta data length */
|
||||
uint8_t meta_len;
|
||||
|
||||
/*! Transmission queue number */
|
||||
uint8_t queue_id;
|
||||
|
||||
/*! Reserved must be 0 */
|
||||
uint16_t rsvd1;
|
||||
};
|
||||
|
||||
/*! RCPU Rx operation */
|
||||
#define RCPU_OPCODE_RX 0x10
|
||||
/*! RCPU Tx operation */
|
||||
#define RCPU_OPCODE_TX 0x20
|
||||
|
||||
/*! RCPU purge flag */
|
||||
#define RCPU_FLAG_PURGE (1 << 0)
|
||||
/*! RCPU pause flag */
|
||||
#define RCPU_FLAG_PAUSE (1 << 1)
|
||||
/*! RCPU modhdr flag */
|
||||
#define RCPU_FLAG_MODHDR (1 << 2)
|
||||
/*! RCPU bind queue flag */
|
||||
#define RCPU_FLAG_BIND_QUE (1 << 3)
|
||||
|
||||
#endif /* NGKNET_DEV_H */
|
||||
|
@ -0,0 +1,112 @@
|
||||
/*! \file ngknet_ioctl.h
|
||||
*
|
||||
* NGKNET I/O control definitions.
|
||||
*
|
||||
* This file is intended for use in both kernel mode and user mode.
|
||||
*
|
||||
* IMPORTANT!
|
||||
* All shared structures must be properly 64-bit aligned.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_IOCTL_H
|
||||
#define NGKNET_IOCTL_H
|
||||
|
||||
/*! Module information */
|
||||
#define NGKNET_MODULE_NAME "linux_ngknet"
|
||||
#define NGKNET_MODULE_MAJOR 121
|
||||
|
||||
/*! Must be updated if backward compatibility is broken */
|
||||
#define NGKNET_IOC_VERSION 2
|
||||
|
||||
/*! Max number of input arguments */
|
||||
#define NGKNET_IOC_IARG_MAX 2
|
||||
|
||||
#define NGKNET_IOC_MAGIC 'K'
|
||||
|
||||
#define NGKNET_VERSION_GET _IOR(NGKNET_IOC_MAGIC, 0xa0, unsigned int)
|
||||
#define NGKNET_RX_RATE_LIMIT _IOWR(NGKNET_IOC_MAGIC, 0xa1, unsigned int)
|
||||
#define NGKNET_DEV_INIT _IOWR(NGKNET_IOC_MAGIC, 0xb0, unsigned int)
|
||||
#define NGKNET_DEV_DEINIT _IOWR(NGKNET_IOC_MAGIC, 0xb1, unsigned int)
|
||||
#define NGKNET_DEV_SUSPEND _IOWR(NGKNET_IOC_MAGIC, 0xb2, unsigned int)
|
||||
#define NGKNET_DEV_RESUME _IOWR(NGKNET_IOC_MAGIC, 0xb3, unsigned int)
|
||||
#define NGKNET_DEV_VNET_WAIT _IOWR(NGKNET_IOC_MAGIC, 0xb4, unsigned int)
|
||||
#define NGKNET_DEV_HNET_WAKE _IOWR(NGKNET_IOC_MAGIC, 0xb5, unsigned int)
|
||||
#define NGKNET_DEV_VNET_DOCK _IOWR(NGKNET_IOC_MAGIC, 0xb6, unsigned int)
|
||||
#define NGKNET_DEV_VNET_UNDOCK _IOWR(NGKNET_IOC_MAGIC, 0xb7, unsigned int)
|
||||
#define NGKNET_QUEUE_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc0, unsigned int)
|
||||
#define NGKNET_QUEUE_QUERY _IOR(NGKNET_IOC_MAGIC, 0xc1, unsigned int)
|
||||
#define NGKNET_RCPU_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc2, unsigned int)
|
||||
#define NGKNET_RCPU_GET _IOR(NGKNET_IOC_MAGIC, 0xc3, unsigned int)
|
||||
#define NGKNET_NETIF_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xd0, unsigned int)
|
||||
#define NGKNET_NETIF_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xd1, unsigned int)
|
||||
#define NGKNET_NETIF_GET _IOR(NGKNET_IOC_MAGIC, 0xd2, unsigned int)
|
||||
#define NGKNET_NETIF_NEXT _IOR(NGKNET_IOC_MAGIC, 0xd3, unsigned int)
|
||||
#define NGKNET_NETIF_LINK_SET _IOW(NGKNET_IOC_MAGIC, 0xd4, unsigned int)
|
||||
#define NGKNET_FILT_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xe0, unsigned int)
|
||||
#define NGKNET_FILT_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xe1, unsigned int)
|
||||
#define NGKNET_FILT_GET _IOR(NGKNET_IOC_MAGIC, 0xe2, unsigned int)
|
||||
#define NGKNET_FILT_NEXT _IOR(NGKNET_IOC_MAGIC, 0xe3, unsigned int)
|
||||
#define NGKNET_INFO_GET _IOR(NGKNET_IOC_MAGIC, 0xf0, unsigned int)
|
||||
#define NGKNET_STATS_GET _IOR(NGKNET_IOC_MAGIC, 0xf1, unsigned int)
|
||||
#define NGKNET_STATS_RESET _IOWR(NGKNET_IOC_MAGIC, 0xf2, unsigned int)
|
||||
#define NGKNET_PTP_DEV_CTRL _IOWR(NGKNET_IOC_MAGIC, 0x90, unsigned int)
|
||||
|
||||
/*! Kernel module information. */
|
||||
struct ngknet_ioc_mod_info {
|
||||
/*! IOCTL version used by kernel module */
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
/*! Data transmission */
|
||||
struct ngknet_ioc_data_xmit {
|
||||
/*! Data buffer address */
|
||||
uint64_t buf;
|
||||
|
||||
/*! Data buffer length */
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/*! IOCTL operations */
|
||||
union ngknet_ioc_op {
|
||||
/*! Get module info */
|
||||
struct ngknet_ioc_mod_info info;
|
||||
/*! Transmit data */
|
||||
struct ngknet_ioc_data_xmit data;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief NGKNET IOCTL command message.
|
||||
*/
|
||||
struct ngknet_ioctl {
|
||||
/*! Device number */
|
||||
uint32_t unit;
|
||||
|
||||
/*! Return code (0 means success) */
|
||||
uint32_t rc;
|
||||
|
||||
/*! Input arguments */
|
||||
int iarg[NGKNET_IOC_IARG_MAX];
|
||||
|
||||
/*! IOCTL operation */
|
||||
union ngknet_ioc_op op;
|
||||
};
|
||||
|
||||
#endif /* NGKNET_IOCTL_H */
|
||||
|
@ -0,0 +1,24 @@
|
||||
#ifndef __NET_PSAMPLE_H
|
||||
#define __NET_PSAMPLE_H
|
||||
|
||||
#include <lkm/lkm.h>
|
||||
#include <uapi/linux/psample.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct psample_group {
|
||||
struct list_head list;
|
||||
struct net *net;
|
||||
u32 group_num;
|
||||
u32 refcount;
|
||||
u32 seq;
|
||||
};
|
||||
|
||||
extern struct psample_group *psample_group_get(struct net *net, u32 group_num);
|
||||
extern void psample_group_put(struct psample_group *group);
|
||||
|
||||
extern void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
|
||||
u32 trunc_size, int in_ifindex, int out_ifindex,
|
||||
u32 sample_rate);
|
||||
|
||||
#endif /* __NET_PSAMPLE_H */
|
@ -0,0 +1,35 @@
|
||||
#ifndef __UAPI_PSAMPLE_H
|
||||
#define __UAPI_PSAMPLE_H
|
||||
|
||||
enum {
|
||||
/* sampled packet metadata */
|
||||
PSAMPLE_ATTR_IIFINDEX,
|
||||
PSAMPLE_ATTR_OIFINDEX,
|
||||
PSAMPLE_ATTR_ORIGSIZE,
|
||||
PSAMPLE_ATTR_SAMPLE_GROUP,
|
||||
PSAMPLE_ATTR_GROUP_SEQ,
|
||||
PSAMPLE_ATTR_SAMPLE_RATE,
|
||||
PSAMPLE_ATTR_DATA,
|
||||
|
||||
/* commands attributes */
|
||||
PSAMPLE_ATTR_GROUP_REFCOUNT,
|
||||
|
||||
__PSAMPLE_ATTR_MAX
|
||||
};
|
||||
|
||||
enum psample_command {
|
||||
PSAMPLE_CMD_SAMPLE,
|
||||
PSAMPLE_CMD_GET_GROUP,
|
||||
PSAMPLE_CMD_NEW_GROUP,
|
||||
PSAMPLE_CMD_DEL_GROUP,
|
||||
};
|
||||
|
||||
/* Can be overridden at runtime by module option */
|
||||
#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1)
|
||||
|
||||
#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config"
|
||||
#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets"
|
||||
#define PSAMPLE_GENL_NAME "psample"
|
||||
#define PSAMPLE_GENL_VERSION 1
|
||||
|
||||
#endif
|
44
platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild
Normal file
44
platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild
Normal file
@ -0,0 +1,44 @@
|
||||
# -*- Kbuild -*-
|
||||
#
|
||||
# Linux KNET module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
obj-m := linux_ngknet.o
|
||||
|
||||
ccflags-y := $(KNET_CPPFLAGS) $(LKM_CFLAGS) \
|
||||
-I$(SDK)/shr/include \
|
||||
-I$(SDK)/bcmdrd/include \
|
||||
-I$(SDK)/linux/include \
|
||||
-I$(SDK)/linux/knet/include \
|
||||
-I$(SDK)/linux/knet
|
||||
|
||||
linux_ngknet-y := $(CHIP_OBJS) \
|
||||
bcmcnet_cmicd_pdma_hw.o \
|
||||
bcmcnet_cmicd_pdma_rxtx.o \
|
||||
bcmcnet_cmicx_pdma_hw.o \
|
||||
bcmcnet_cmicx_pdma_rxtx.o \
|
||||
bcmcnet_core.o \
|
||||
bcmcnet_dev.o \
|
||||
bcmcnet_rxtx.o \
|
||||
ngknet_buff.o \
|
||||
ngknet_callback.o \
|
||||
ngknet_extra.o \
|
||||
ngknet_linux.o \
|
||||
ngknet_main.o \
|
||||
ngknet_procfs.o \
|
||||
ngknet_ptp.o
|
105
platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile
Normal file
105
platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- Makefile -*-
|
||||
#
|
||||
# Linux KNET module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
CNETDIR = $(SDK)/bcmcnet
|
||||
KNETDIR = $(SDK)/linux/knet
|
||||
SRCIDIR = $(CNETDIR)/include/bcmcnet
|
||||
DSTIDIR = $(KNETDIR)/include/bcmcnet
|
||||
|
||||
# Change comma-separated list to space-separated list
|
||||
comma = ,
|
||||
empty =
|
||||
space = $(empty) $(empty)
|
||||
spc_sep = $(subst $(comma),$(space),$1)
|
||||
|
||||
# Convert chip name to uppercase
|
||||
chip_uc = $(subst a,A,$(subst b,B,$(subst c,C,$(subst m,M,$1))))
|
||||
|
||||
# Convert chip name to lowercase
|
||||
chip_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst M,m,$1))))
|
||||
|
||||
#
|
||||
# If SDK_CHIPS is defined, then exclude any chip directory which is
|
||||
# not part of this list.
|
||||
#
|
||||
KNET_CHIPS := $(subst $(CNETDIR)/chip/,,$(wildcard $(CNETDIR)/chip/bcm*))
|
||||
ifdef SDK_CHIPS
|
||||
# Create space-separated lowercase version of chip list
|
||||
SDK_CHIPS_SPC := $(call spc_sep,$(SDK_CHIPS))
|
||||
SDK_CHIPS_LC := $(call chip_lc,$(SDK_CHIPS_SPC))
|
||||
# Configure build flags according to chip list
|
||||
KNET_CHIPS := $(filter $(SDK_CHIPS_LC),$(KNET_CHIPS))
|
||||
KNET_CPPFLAGS := CHIP_DEFAULT=0 $(addsuffix =1,$(call chip_uc,$(KNET_CHIPS)))
|
||||
KNET_CPPFLAGS := $(addprefix -DBCMDRD_CONFIG_INCLUDE_,$(KNET_CPPFLAGS))
|
||||
export KNET_CPPFLAGS
|
||||
endif
|
||||
|
||||
.PHONY: mklinks rmlinks
|
||||
|
||||
knet: mklinks
|
||||
$(MAKE) all
|
||||
|
||||
#
|
||||
# Suppress symlink error messages.
|
||||
#
|
||||
# Note that we do not use "ln -f" as this may cause failures if
|
||||
# multiple builds are done in parallel on the same source tree.
|
||||
#
|
||||
R = 2>/dev/null
|
||||
|
||||
mklinks:
|
||||
mkdir -p $(DSTIDIR)
|
||||
-ln -s $(KNETDIR)/ngknet_dep.h $(DSTIDIR)/bcmcnet_dep.h $(R)
|
||||
-ln -s $(KNETDIR)/ngknet_buff.h $(DSTIDIR)/bcmcnet_buff.h $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_types.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_internal.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_core.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_dev.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_rxtx.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_cmicd.h $(DSTIDIR) $(R)
|
||||
-ln -s $(SRCIDIR)/bcmcnet_cmicx.h $(DSTIDIR) $(R)
|
||||
-ln -s $(CNETDIR)/chip/*/*attach.c $(KNETDIR) $(R)
|
||||
-ln -s $(CNETDIR)/hmi/cmicd/*.c $(KNETDIR) $(R)
|
||||
-ln -s $(CNETDIR)/hmi/cmicx/*.c $(KNETDIR) $(R)
|
||||
-ln -s $(CNETDIR)/main/bcmcnet_core.c $(KNETDIR) $(R)
|
||||
-ln -s $(CNETDIR)/main/bcmcnet_dev.c $(KNETDIR) $(R)
|
||||
-ln -s $(CNETDIR)/main/bcmcnet_rxtx.c $(KNETDIR) $(R)
|
||||
|
||||
rmlinks:
|
||||
-rm -f bcm*
|
||||
-rm -rf include
|
||||
|
||||
CHIP_SRCS := $(addsuffix _pdma_attach.c,$(KNET_CHIPS))
|
||||
CHIP_OBJS ?= $(patsubst %.c, %.o, $(CHIP_SRCS))
|
||||
export CHIP_OBJS
|
||||
|
||||
include Kbuild
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
MOD_NAME = linux_ngknet
|
||||
|
||||
include $(SDK)/make/lkm.mk
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: distclean
|
||||
|
||||
distclean: rmlinks
|
326
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c
Normal file
326
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c
Normal file
@ -0,0 +1,326 @@
|
||||
/*! \file ngknet_buff.c
|
||||
*
|
||||
* Utility routines for NGKNET packet buffer management in Linux kernel mode.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include <bcmcnet/bcmcnet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_rxtx.h>
|
||||
#include "ngknet_main.h"
|
||||
#include "ngknet_buff.h"
|
||||
|
||||
/*!
|
||||
* Allocate coherent memory
|
||||
*/
|
||||
static void *
|
||||
bcmcnet_ring_buf_alloc(struct pdma_dev *dev, uint32_t size, dma_addr_t *dma)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
|
||||
return dma_alloc_coherent(kdev->dev, size, dma, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free coherent memory
|
||||
*/
|
||||
static void
|
||||
bcmcnet_ring_buf_free(struct pdma_dev *dev, uint32_t size, void *addr, dma_addr_t dma)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
|
||||
dma_free_coherent(kdev->dev, size, addr, dma);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate Rx buffer
|
||||
*/
|
||||
static int
|
||||
bcmcnet_rx_buf_alloc(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
page = kal_dev_alloc_page();
|
||||
if (unlikely(!page)) {
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
dma = dma_map_page(kdev->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(kdev->dev, dma))) {
|
||||
__free_page(page);
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
pbuf->dma = dma;
|
||||
pbuf->page = page;
|
||||
pbuf->page_offset = 0;
|
||||
} else {
|
||||
skb = netdev_alloc_skb(kdev->net_dev, PDMA_RXB_RESV + pbuf->adj + rxq->buf_size);
|
||||
if (unlikely(!skb)) {
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
skb_reserve(skb, PDMA_RXB_ALIGN - (((unsigned long)skb->data) & (PDMA_RXB_ALIGN - 1)));
|
||||
pbuf->skb = skb;
|
||||
pbuf->pkb = (struct pkt_buf *)skb->data;
|
||||
dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj, rxq->buf_size, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(kdev->dev, dma))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
pbuf->dma = dma;
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get Rx buffer DMA address
|
||||
*/
|
||||
static void
|
||||
bcmcnet_rx_buf_dma(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, dma_addr_t *addr)
|
||||
{
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
*addr = pbuf->dma + pbuf->page_offset + PDMA_RXB_RESV + pbuf->adj;
|
||||
} else {
|
||||
*addr = pbuf->dma;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check Rx buffer
|
||||
*/
|
||||
static int
|
||||
bcmcnet_rx_buf_avail(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf)
|
||||
{
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
pbuf->skb = NULL;
|
||||
}
|
||||
|
||||
return pbuf->dma != 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get Rx buffer
|
||||
*/
|
||||
static struct pkt_hdr *
|
||||
bcmcnet_rx_buf_get(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, int len)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
if (pbuf->skb) {
|
||||
return &pbuf->pkb->pkh;
|
||||
}
|
||||
skb = kal_build_skb(page_address(pbuf->page) + pbuf->page_offset,
|
||||
PDMA_SKB_RESV + pbuf->adj + rxq->buf_size);
|
||||
if (unlikely(!skb)) {
|
||||
return NULL;
|
||||
}
|
||||
skb_reserve(skb, PDMA_RXB_ALIGN);
|
||||
dma_sync_single_range_for_cpu(kdev->dev, pbuf->dma, pbuf->page_offset,
|
||||
PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE);
|
||||
pbuf->skb = skb;
|
||||
pbuf->pkb = (struct pkt_buf *)skb->data;
|
||||
|
||||
/* Try to reuse this page */
|
||||
if (unlikely(page_count(pbuf->page) != 1)) {
|
||||
dma_unmap_page(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
pbuf->dma = 0;
|
||||
} else {
|
||||
pbuf->page_offset ^= PDMA_PAGE_BUF_MAX;
|
||||
page_ref_inc(pbuf->page);
|
||||
dma_sync_single_range_for_device(kdev->dev, pbuf->dma, pbuf->page_offset,
|
||||
PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE);
|
||||
}
|
||||
} else {
|
||||
if (!pbuf->dma) {
|
||||
return &pbuf->pkb->pkh;
|
||||
}
|
||||
skb = pbuf->skb;
|
||||
dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE);
|
||||
pbuf->dma = 0;
|
||||
}
|
||||
|
||||
skb_put(skb, PKT_HDR_SIZE + pbuf->adj + len);
|
||||
|
||||
return &pbuf->pkb->pkh;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Put Rx buffer
|
||||
*/
|
||||
static int
|
||||
bcmcnet_rx_buf_put(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf, int len)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
dma_addr_t dma;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
dev_kfree_skb_any(pbuf->skb);
|
||||
} else {
|
||||
skb = pbuf->skb;
|
||||
dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj,
|
||||
rxq->buf_size, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(kdev->dev, dma))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
pbuf->dma = 0;
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
pbuf->dma = dma;
|
||||
skb_trim(skb, skb->len - (PKT_HDR_SIZE + pbuf->adj + len));
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free Rx buffer
|
||||
*/
|
||||
static void
|
||||
bcmcnet_rx_buf_free(struct pdma_dev *dev, struct pdma_rx_queue *rxq,
|
||||
struct pdma_rx_buf *pbuf)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
|
||||
if (rxq->mode == PDMA_BUF_MODE_PAGE) {
|
||||
dma_unmap_single(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
__free_page(pbuf->page);
|
||||
} else {
|
||||
dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(pbuf->skb);
|
||||
}
|
||||
|
||||
pbuf->dma = 0;
|
||||
pbuf->page = NULL;
|
||||
pbuf->page_offset = 0;
|
||||
pbuf->skb = NULL;
|
||||
pbuf->pkb = NULL;
|
||||
pbuf->adj = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get Rx buffer mode
|
||||
*/
|
||||
static enum buf_mode
|
||||
bcmcnet_rx_buf_mode(struct pdma_dev *dev, struct pdma_rx_queue *rxq)
|
||||
{
|
||||
uint32_t len;
|
||||
|
||||
len = dev->rx_ph_size ? rxq->buf_size : rxq->buf_size + PDMA_RXB_META;
|
||||
if (PDMA_RXB_SIZE(len) <= PDMA_PAGE_BUF_MAX && PAGE_SIZE < 8192 &&
|
||||
kal_support_paged_skb()) {
|
||||
return PDMA_BUF_MODE_PAGE;
|
||||
}
|
||||
|
||||
return PDMA_BUF_MODE_SKB;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get Tx buffer
|
||||
*/
|
||||
static struct pkt_hdr *
|
||||
bcmcnet_tx_buf_get(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf, void *buf)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
struct sk_buff *skb = (struct sk_buff *)buf;
|
||||
struct pkt_buf *pkb = (struct pkt_buf *)skb->data;
|
||||
dma_addr_t dma;
|
||||
|
||||
pbuf->len = pkb->pkh.data_len + (pbuf->adj ? pkb->pkh.meta_len : 0);
|
||||
dma = dma_map_single(kdev->dev, &pkb->data + (pbuf->adj ? 0 : pkb->pkh.meta_len),
|
||||
pbuf->len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(kdev->dev, dma))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return NULL;
|
||||
}
|
||||
pbuf->dma = dma;
|
||||
pbuf->skb = skb;
|
||||
pbuf->pkb = pkb;
|
||||
|
||||
return &pkb->pkh;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get Tx buffer DMA address
|
||||
*/
|
||||
static void
|
||||
bcmcnet_tx_buf_dma(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf, dma_addr_t *addr)
|
||||
{
|
||||
*addr = pbuf->dma;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free Tx buffer
|
||||
*/
|
||||
static void
|
||||
bcmcnet_tx_buf_free(struct pdma_dev *dev, struct pdma_tx_queue *txq,
|
||||
struct pdma_tx_buf *pbuf)
|
||||
{
|
||||
struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv;
|
||||
|
||||
dma_unmap_single(kdev->dev, pbuf->dma, pbuf->len, DMA_TO_DEVICE);
|
||||
if (skb_shinfo(pbuf->skb)->tx_flags & SKBTX_IN_PROGRESS) {
|
||||
skb_queue_tail(&kdev->ptp_tx_queue, pbuf->skb);
|
||||
schedule_work(&kdev->ptp_tx_work);
|
||||
} else {
|
||||
dev_kfree_skb_any(pbuf->skb);
|
||||
}
|
||||
|
||||
pbuf->dma = 0;
|
||||
pbuf->len = 0;
|
||||
pbuf->skb = NULL;
|
||||
pbuf->pkb = NULL;
|
||||
pbuf->adj = 0;
|
||||
}
|
||||
|
||||
static const struct pdma_buf_mngr buf_mngr = {
|
||||
.ring_buf_alloc = bcmcnet_ring_buf_alloc,
|
||||
.ring_buf_free = bcmcnet_ring_buf_free,
|
||||
.rx_buf_alloc = bcmcnet_rx_buf_alloc,
|
||||
.rx_buf_dma = bcmcnet_rx_buf_dma,
|
||||
.rx_buf_avail = bcmcnet_rx_buf_avail,
|
||||
.rx_buf_get = bcmcnet_rx_buf_get,
|
||||
.rx_buf_put = bcmcnet_rx_buf_put,
|
||||
.rx_buf_free = bcmcnet_rx_buf_free,
|
||||
.rx_buf_mode = bcmcnet_rx_buf_mode,
|
||||
.tx_buf_get = bcmcnet_tx_buf_get,
|
||||
.tx_buf_dma = bcmcnet_tx_buf_dma,
|
||||
.tx_buf_free = bcmcnet_tx_buf_free,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Open a device
|
||||
*/
|
||||
void
|
||||
bcmcnet_buf_mngr_init(struct pdma_dev *dev)
|
||||
{
|
||||
dev->ctrl.buf_mngr = (struct pdma_buf_mngr *)&buf_mngr;
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*! \file ngknet_buff.h
|
||||
*
|
||||
* Generic data structure definitions for NGKNET packet buffer management.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_BUFF_H
|
||||
#define NGKNET_BUFF_H
|
||||
|
||||
/*! Rx buffer align size */
|
||||
#define PDMA_RXB_ALIGN 32
|
||||
/*! Rx buffer reserved size */
|
||||
#define PDMA_RXB_RESV (PDMA_RXB_ALIGN + PKT_HDR_SIZE)
|
||||
/*! Rx SKB reserved size */
|
||||
#define PDMA_SKB_RESV (PDMA_RXB_RESV + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||
/*! Rx buffer size */
|
||||
#define PDMA_RXB_SIZE(len) (SKB_DATA_ALIGN(len + NET_SKB_PAD) + PDMA_SKB_RESV)
|
||||
/*! Rx reserved meta size */
|
||||
#define PDMA_RXB_META 64
|
||||
/*! Max page buffer size */
|
||||
#define PDMA_PAGE_BUF_MAX 2048
|
||||
|
||||
/*!
|
||||
* \brief Rx buffer.
|
||||
*/
|
||||
struct pdma_rx_buf {
|
||||
/*! DMA address */
|
||||
dma_addr_t dma;
|
||||
|
||||
/*! Buffer page */
|
||||
struct page *page;
|
||||
|
||||
/*! Buffer page offset */
|
||||
unsigned int page_offset;
|
||||
|
||||
/*! Rx SKB */
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*! Packet buffer point */
|
||||
struct pkt_buf *pkb;
|
||||
|
||||
/*! Packet buffer adjustment */
|
||||
uint32_t adj;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Tx buffer.
|
||||
*/
|
||||
struct pdma_tx_buf {
|
||||
/*! DMA address */
|
||||
dma_addr_t dma;
|
||||
|
||||
/*! Tx buffer length */
|
||||
uint32_t len;
|
||||
|
||||
/*! Tx SKB */
|
||||
struct sk_buff *skb;
|
||||
|
||||
/*! Packet buffer point */
|
||||
struct pkt_buf *pkb;
|
||||
|
||||
/*! Packet buffer adjustment */
|
||||
uint32_t adj;
|
||||
};
|
||||
|
||||
#endif /* NGKNET_BUFF_H */
|
||||
|
@ -0,0 +1,315 @@
|
||||
/*! \file ngknet_callback.c
|
||||
*
|
||||
* Utility routines for NGKNET callbacks.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include "ngknet_callback.h"
|
||||
|
||||
static struct ngknet_callback_ctrl callback_ctrl;
|
||||
|
||||
int
|
||||
ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc)
|
||||
{
|
||||
*cbc = &callback_ctrl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Call-back interfaces for other Linux kernel drivers.
|
||||
*
|
||||
* The Rx call-back allows an external module to modify packet contents
|
||||
* before it is handed off to the Linux network stack.
|
||||
*
|
||||
* The Tx call-back allows an external module to modify packet contents
|
||||
* before it is injected into the switch.
|
||||
*/
|
||||
|
||||
int
|
||||
ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb)
|
||||
{
|
||||
if (callback_ctrl.rx_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.rx_cb = rx_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb)
|
||||
{
|
||||
if (rx_cb == NULL || callback_ctrl.rx_cb != rx_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.rx_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb)
|
||||
{
|
||||
if (callback_ctrl.tx_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.tx_cb = tx_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb)
|
||||
{
|
||||
if (tx_cb == NULL || callback_ctrl.tx_cb != tx_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.tx_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_rx_config_set_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_rx_config_set_cb = ptp_rx_config_set_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb)
|
||||
{
|
||||
if (ptp_rx_config_set_cb == NULL ||
|
||||
callback_ctrl.ptp_rx_config_set_cb != ptp_rx_config_set_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_rx_config_set_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_tx_config_set_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_config_set_cb = ptp_tx_config_set_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb)
|
||||
{
|
||||
if (ptp_tx_config_set_cb == NULL ||
|
||||
callback_ctrl.ptp_tx_config_set_cb != ptp_tx_config_set_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_config_set_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_rx_hwts_get_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_rx_hwts_get_cb = ptp_rx_hwts_get_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb)
|
||||
{
|
||||
if (ptp_rx_hwts_get_cb == NULL ||
|
||||
callback_ctrl.ptp_rx_hwts_get_cb != ptp_rx_hwts_get_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_rx_hwts_get_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_tx_hwts_get_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_hwts_get_cb = ptp_tx_hwts_get_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb)
|
||||
{
|
||||
if (ptp_tx_hwts_get_cb == NULL ||
|
||||
callback_ctrl.ptp_tx_hwts_get_cb != ptp_tx_hwts_get_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_hwts_get_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_tx_meta_set_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_meta_set_cb = ptp_tx_meta_set_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb)
|
||||
{
|
||||
if (ptp_tx_meta_set_cb == NULL ||
|
||||
callback_ctrl.ptp_tx_meta_set_cb != ptp_tx_meta_set_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_tx_meta_set_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_phc_index_get_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_phc_index_get_cb = ptp_phc_index_get_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb)
|
||||
{
|
||||
if (ptp_phc_index_get_cb == NULL ||
|
||||
callback_ctrl.ptp_phc_index_get_cb != ptp_phc_index_get_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_phc_index_get_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb)
|
||||
{
|
||||
if (callback_ctrl.ptp_dev_ctrl_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_dev_ctrl_cb = ptp_dev_ctrl_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb)
|
||||
{
|
||||
if (ptp_dev_ctrl_cb == NULL ||
|
||||
callback_ctrl.ptp_dev_ctrl_cb != ptp_dev_ctrl_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.ptp_dev_ctrl_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb)
|
||||
{
|
||||
if (callback_ctrl.netif_create_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.netif_create_cb = netif_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb)
|
||||
{
|
||||
if (netif_cb == NULL || callback_ctrl.netif_create_cb != netif_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.netif_create_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb)
|
||||
{
|
||||
if (callback_ctrl.netif_destroy_cb != NULL) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.netif_destroy_cb = netif_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb)
|
||||
{
|
||||
if (netif_cb == NULL || callback_ctrl.netif_destroy_cb != netif_cb) {
|
||||
return -1;
|
||||
}
|
||||
callback_ctrl.netif_destroy_cb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ngknet_rx_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_rx_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_tx_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_tx_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_netif_create_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_netif_create_cb_unregister);
|
||||
EXPORT_SYMBOL(ngknet_netif_destroy_cb_register);
|
||||
EXPORT_SYMBOL(ngknet_netif_destroy_cb_unregister);
|
@ -0,0 +1,364 @@
|
||||
/*! \file ngknet_callback.h
|
||||
*
|
||||
* Data structure definitions for NGKNET callbacks.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_CALLBACK_H
|
||||
#define NGKNET_CALLBACK_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include "ngknet_main.h"
|
||||
|
||||
/*!
|
||||
* \brief NGKNET callback description.
|
||||
*/
|
||||
struct ngknet_callback_desc {
|
||||
/*! Device number */
|
||||
int dev_no;
|
||||
|
||||
/*! Device ID */
|
||||
uint32_t dev_id;
|
||||
|
||||
/*! Device type string */
|
||||
const char *type_str;
|
||||
|
||||
/*! Network interface private data */
|
||||
struct ngknet_private *priv;
|
||||
|
||||
/*! Matched filter */
|
||||
struct ngknet_filter_s *filt;
|
||||
|
||||
/*! Packet meta data */
|
||||
uint8_t *pmd;
|
||||
|
||||
/*! Packet meta data length */
|
||||
int pmd_len;
|
||||
|
||||
/*! Packet data length */
|
||||
int pkt_len;
|
||||
|
||||
/*! Matched callback filter */
|
||||
struct ngknet_filter_s *filt_cb;
|
||||
};
|
||||
|
||||
#define NGKNET_SKB_CB(_skb) ((struct ngknet_callback_desc *)_skb->cb)
|
||||
|
||||
/*! Handle Rx packet */
|
||||
typedef struct sk_buff *
|
||||
(*ngknet_rx_cb_f)(struct sk_buff *skb);
|
||||
|
||||
/*! Handle Tx packet */
|
||||
typedef struct sk_buff *
|
||||
(*ngknet_tx_cb_f)(struct sk_buff *skb);
|
||||
|
||||
/*! PTP Rx/Tx config set */
|
||||
typedef int
|
||||
(*ngknet_ptp_config_set_cb_f)(struct ngknet_private *priv, int *value);
|
||||
|
||||
/*! PTP Rx/Tx HW timestamp get */
|
||||
typedef int
|
||||
(*ngknet_ptp_hwts_get_cb_f)(struct sk_buff *skb, uint64_t *ts);
|
||||
|
||||
/*! PTP Tx meta set */
|
||||
typedef int
|
||||
(*ngknet_ptp_meta_set_cb_f)(struct sk_buff *skb);
|
||||
|
||||
/*! PTP PHC index get */
|
||||
typedef int
|
||||
(*ngknet_ptp_phc_index_get_cb_f)(struct ngknet_private *priv, int *index);
|
||||
|
||||
/*! PTP device control */
|
||||
typedef int
|
||||
(*ngknet_ptp_dev_ctrl_cb_f)(struct ngknet_dev *dev, int cmd, char *data, int len);
|
||||
|
||||
/*! Netif callback */
|
||||
typedef int
|
||||
(*ngknet_netif_cb_f)(struct net_device *dev);
|
||||
|
||||
/*!
|
||||
* \brief NGKNET callback control.
|
||||
*/
|
||||
struct ngknet_callback_ctrl {
|
||||
/*! Handle Rx packet */
|
||||
ngknet_rx_cb_f rx_cb;
|
||||
|
||||
/*! Handle Tx packet */
|
||||
ngknet_tx_cb_f tx_cb;
|
||||
|
||||
/*! PTP Rx config set */
|
||||
ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb;
|
||||
|
||||
/*! PTP Tx config set */
|
||||
ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb;
|
||||
|
||||
/*! PTP Rx HW timestamp get */
|
||||
ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb;
|
||||
|
||||
/*! PTP Tx HW timestamp get */
|
||||
ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb;
|
||||
|
||||
/*! PTP Tx meta set */
|
||||
ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb;
|
||||
|
||||
/*! PTP PHC index get */
|
||||
ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb;
|
||||
|
||||
/*! PTP device control */
|
||||
ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb;
|
||||
|
||||
/*! Handle Netif create */
|
||||
ngknet_netif_cb_f netif_create_cb;
|
||||
|
||||
/*! Handle Netif destroy */
|
||||
ngknet_netif_cb_f netif_destroy_cb;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Get callback control.
|
||||
*
|
||||
* \param [in] cbc Pointer to callback control.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc);
|
||||
|
||||
/*!
|
||||
* \brief Register Rx callback.
|
||||
*
|
||||
* \param [in] rx_cb Rx callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister Rx callback.
|
||||
*
|
||||
* \param [in] rx_cb Rx callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register Tx callback.
|
||||
*
|
||||
* \param [in] tx_cb Tx callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister Tx callback.
|
||||
*
|
||||
* \param [in] tx_cb Tx callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP Rx config set callback.
|
||||
*
|
||||
* \param [in] ptp_rx_config_set_cb Rx config set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP Rx config set callback.
|
||||
*
|
||||
* \param [in] ptp_rx_config_set_cb Rx config set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP Tx config set callback.
|
||||
*
|
||||
* \param [in] ptp_tx_config_set_cb Tx config set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP Tx config set callback.
|
||||
*
|
||||
* \param [in] ptp_tx_config_set_cb Tx config set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP Rx HW timestamp get callback.
|
||||
*
|
||||
* \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP Rx HW timestamp get callback.
|
||||
*
|
||||
* \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP Tx HW timestamp get callback.
|
||||
*
|
||||
* \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP Tx HW timestamp get callback.
|
||||
*
|
||||
* \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP Tx meta set callback.
|
||||
*
|
||||
* \param [in] ptp_tx_meta_set_cb Tx meta set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP Tx meta set callback.
|
||||
*
|
||||
* \param [in] ptp_tx_meta_set_cb Tx meta set callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP PHC index get callback.
|
||||
*
|
||||
* \param [in] ptp_phc_index_get_cb PHC index get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP PHC index get callback.
|
||||
*
|
||||
* \param [in] ptp_phc_index_get_cb PHC index get callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register PTP device control callback.
|
||||
*
|
||||
* \param [in] ptp_dev_ctrl_cb Device control callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister PTP device control callback.
|
||||
*
|
||||
* \param [in] ptp_dev_ctrl_cb Device control callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register Netif Create callback.
|
||||
*
|
||||
* \param [netif_cb] netif_cb create callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister Netif Create callback.
|
||||
*
|
||||
* \param [netif_cb] netif_cb destroy callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb);
|
||||
|
||||
/*!
|
||||
* \brief Register Netif Destroy callback.
|
||||
*
|
||||
* \param [netif_cb] netif_cb destroy callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb);
|
||||
|
||||
/*!
|
||||
* \brief Unregister Netif Destroy callback.
|
||||
*
|
||||
* \param [netif_cb] netif_cb destroy callback function.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb);
|
||||
|
||||
#endif /* NGKNET_CALLBACK_H */
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*! \file ngknet_dep.h
|
||||
*
|
||||
* Macro definitions for NGKNET dependence.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_DEP_H
|
||||
#define NGKNET_DEP_H
|
||||
|
||||
#include <shr/shr_error.h>
|
||||
#include <ngknet_linux.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/*! Memorry barrier */
|
||||
#define MEMORY_BARRIER smp_mb()
|
||||
|
||||
/*! CNET print uitility */
|
||||
#define CNET_PR(fmt, args...) printk(fmt, ##args)
|
||||
|
||||
struct pdma_dev;
|
||||
|
||||
/*! Externs for the required functions. */
|
||||
#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \
|
||||
extern int _bd##_cnet_pdma_attach(struct pdma_dev *dev); \
|
||||
extern int _bd##_cnet_pdma_detach(struct pdma_dev *dev);
|
||||
#include <bcmdrd/bcmdrd_devlist.h>
|
||||
|
||||
/*! Create enumeration values from list of supported devices. */
|
||||
#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \
|
||||
NGKNET_DEV_T_##_bd,
|
||||
/*! Enumeration for all base device types. */
|
||||
typedef enum {
|
||||
NGKNET_DEV_T_NONE = 0,
|
||||
#include <bcmdrd/bcmdrd_devlist.h>
|
||||
NGKNET_DEV_T_COUNT
|
||||
} ngknet_dev_type_t;
|
||||
|
||||
#endif /* NGKNET_DEP_H */
|
||||
|
505
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c
Normal file
505
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c
Normal file
@ -0,0 +1,505 @@
|
||||
/*! \file ngknet_extra.c
|
||||
*
|
||||
* Utility routines for NGKNET enhancement.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#include <lkm/ngknet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
#include "ngknet_main.h"
|
||||
#include "ngknet_extra.h"
|
||||
#include "ngknet_callback.h"
|
||||
|
||||
static struct ngknet_rl_ctrl rl_ctrl;
|
||||
|
||||
int
|
||||
ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter)
|
||||
{
|
||||
struct filt_ctrl *fc = NULL;
|
||||
struct list_head *list = NULL;
|
||||
ngknet_filter_t *filt = NULL;
|
||||
unsigned long flags;
|
||||
int num, id, done = 0;
|
||||
|
||||
switch (filter->type) {
|
||||
case NGKNET_FILTER_T_RX_PKT:
|
||||
break;
|
||||
default:
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
switch (filter->dest_type) {
|
||||
case NGKNET_FILTER_DEST_T_NULL:
|
||||
case NGKNET_FILTER_DEST_T_NETIF:
|
||||
case NGKNET_FILTER_DEST_T_VNET:
|
||||
case NGKNET_FILTER_DEST_T_CB: /* SDKLT-26907: support NGKNET_FILTER_DEST_T_CB */
|
||||
break;
|
||||
default:
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
num = (long)dev->fc[0];
|
||||
for (id = 1; id < num + 1; id++) {
|
||||
if (!dev->fc[id]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id > NUM_FILTER_MAX) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_RESOURCE;
|
||||
}
|
||||
|
||||
fc = kzalloc(sizeof(*fc), GFP_KERNEL);
|
||||
if (!fc) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_MEMORY;
|
||||
}
|
||||
|
||||
dev->fc[id] = fc;
|
||||
num += id == (num + 1) ? 1 : 0;
|
||||
dev->fc[0] = (void *)(long)num;
|
||||
|
||||
memcpy(&fc->filt, filter, sizeof(fc->filt));
|
||||
fc->filt.id = id;
|
||||
|
||||
list_for_each(list, &dev->filt_list) {
|
||||
filt = &((struct filt_ctrl *)list)->filt;
|
||||
if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN) {
|
||||
if (!(fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN) ||
|
||||
fc->filt.chan > filt->chan) {
|
||||
continue;
|
||||
}
|
||||
if (fc->filt.chan < filt->chan ||
|
||||
fc->filt.priority < filt->priority) {
|
||||
list_add_tail(&fc->list, list);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN ||
|
||||
fc->filt.priority < filt->priority) {
|
||||
list_add_tail(&fc->list, list);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
list_add_tail(&fc->list, &dev->filt_list);
|
||||
}
|
||||
|
||||
filter->id = fc->filt.id;
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_filter_destroy(struct ngknet_dev *dev, int id)
|
||||
{
|
||||
struct filt_ctrl *fc = NULL;
|
||||
unsigned long flags;
|
||||
int num;
|
||||
|
||||
if (id <= 0 || id > NUM_FILTER_MAX) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
fc = (struct filt_ctrl *)dev->fc[id];
|
||||
if (!fc) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
list_del(&fc->list);
|
||||
kfree(fc);
|
||||
|
||||
dev->fc[id] = NULL;
|
||||
num = (long)dev->fc[0];
|
||||
while (num-- == id--) {
|
||||
if (dev->fc[id]) {
|
||||
dev->fc[0] = (void *)(long)num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_filter_destroy_all(struct ngknet_dev *dev)
|
||||
{
|
||||
int id;
|
||||
int rv;
|
||||
|
||||
for (id = 1; id <= NUM_FILTER_MAX; id++) {
|
||||
rv = ngknet_filter_destroy(dev, id);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter)
|
||||
{
|
||||
struct filt_ctrl *fc = NULL;
|
||||
unsigned long flags;
|
||||
int num;
|
||||
|
||||
if (id <= 0 || id > NUM_FILTER_MAX) {
|
||||
return SHR_E_PARAM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
fc = (struct filt_ctrl *)dev->fc[id];
|
||||
if (!fc) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
memcpy(filter, &fc->filt, sizeof(*filter));
|
||||
|
||||
num = (long)dev->fc[0];
|
||||
for (id++; id < num + 1; id++) {
|
||||
if (dev->fc[id]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filter->next = id == (num + 1) ? 0 : id;
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter)
|
||||
{
|
||||
int id;
|
||||
int rv;
|
||||
|
||||
if (!filter->next) {
|
||||
for (id = 1; id <= NUM_FILTER_MAX; id++) {
|
||||
rv = ngknet_filter_get(dev, id, filter);
|
||||
if (SHR_SUCCESS(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if (id > NUM_FILTER_MAX) {
|
||||
return SHR_E_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return ngknet_filter_get(dev, filter->next, filter);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev,
|
||||
struct net_device **mndev, struct sk_buff **mskb)
|
||||
{
|
||||
struct pkt_buf *pkb = (struct pkt_buf *)skb->data;
|
||||
struct net_device *dest_ndev = NULL, *mirror_ndev = NULL;
|
||||
struct sk_buff *mirror_skb = NULL;
|
||||
struct ngknet_private *priv = NULL;
|
||||
struct filt_ctrl *fc = NULL;
|
||||
struct list_head *list = NULL;
|
||||
ngknet_filter_t scratch, *filt = NULL, *filt_cb = NULL;
|
||||
uint8_t *oob = &pkb->data, *data = NULL;
|
||||
uint16_t tpid;
|
||||
unsigned long flags;
|
||||
int wsize;
|
||||
int chan_id;
|
||||
int idx, match = 0, match_cb = 0;
|
||||
|
||||
bcmcnet_pdma_dev_queue_to_chan(&dev->pdma_dev, pkb->pkh.queue_id,
|
||||
PDMA_Q_RX, &chan_id);
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
dest_ndev = dev->bdev[chan_id];
|
||||
if (dest_ndev) {
|
||||
skb->dev = dest_ndev;
|
||||
priv = netdev_priv(dest_ndev);
|
||||
priv->users++;
|
||||
*ndev = dest_ndev;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
if (list_empty(&dev->filt_list)) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
list_for_each(list, &dev->filt_list) {
|
||||
fc = (struct filt_ctrl *)list;
|
||||
filt = &fc->filt;
|
||||
if (filt->flags & NGKNET_FILTER_F_ANY_DATA) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN && filt->chan != chan_id) {
|
||||
continue;
|
||||
}
|
||||
memcpy(&scratch.data.b[0],
|
||||
&oob[filt->oob_data_offset], filt->oob_data_size);
|
||||
memcpy(&scratch.data.b[filt->oob_data_size],
|
||||
&pkb->data + pkb->pkh.meta_len + filt->pkt_data_offset,
|
||||
filt->pkt_data_size);
|
||||
wsize = NGKNET_BYTES2WORDS(filt->oob_data_size + filt->pkt_data_size);
|
||||
for (idx = 0; idx < wsize; idx++) {
|
||||
scratch.data.w[idx] &= filt->mask.w[idx];
|
||||
if (scratch.data.w[idx] != filt->data.w[idx]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == wsize) {
|
||||
if (NGKNET_FILTER_DEST_T_CB == filt->dest_type) {
|
||||
match_cb = 1;
|
||||
filt_cb = filt;
|
||||
continue;
|
||||
}
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
fc->hits++;
|
||||
switch (filt->dest_type) {
|
||||
case NGKNET_FILTER_DEST_T_NETIF:
|
||||
if (filt->dest_id == 0) {
|
||||
dest_ndev = dev->net_dev;
|
||||
} else {
|
||||
dest_ndev = dev->vdev[filt->dest_id];
|
||||
}
|
||||
if (dest_ndev) {
|
||||
skb->dev = dest_ndev;
|
||||
if (filt->dest_proto) {
|
||||
pkb->pkh.attrs |= PDMA_RX_SET_PROTO;
|
||||
skb->protocol = filt->dest_proto;
|
||||
}
|
||||
priv = netdev_priv(dest_ndev);
|
||||
priv->users++;
|
||||
}
|
||||
break;
|
||||
case NGKNET_FILTER_DEST_T_VNET:
|
||||
pkb->pkh.attrs |= PDMA_RX_TO_VNET;
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_NO_HANDLER;
|
||||
case NGKNET_FILTER_DEST_T_NULL:
|
||||
default:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (!dest_ndev) {
|
||||
return SHR_E_NONE;
|
||||
} else {
|
||||
*ndev = dest_ndev;
|
||||
}
|
||||
|
||||
if (filt->flags & NGKNET_FILTER_F_STRIP_TAG) {
|
||||
pkb->pkh.attrs |= PDMA_RX_STRIP_TAG;
|
||||
data = skb->data + PKT_HDR_SIZE + pkb->pkh.meta_len;
|
||||
tpid = data[12] << 8 | data[13];
|
||||
if (tpid == ETH_P_8021Q || tpid == ETH_P_8021AD) {
|
||||
pkb->pkh.data_len -= VLAN_HLEN;
|
||||
memmove(skb->data + VLAN_HLEN, skb->data,
|
||||
PKT_HDR_SIZE + pkb->pkh.meta_len + 2 * ETH_ALEN);
|
||||
skb_pull(skb, VLAN_HLEN);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->cbc->rx_cb) {
|
||||
NGKNET_SKB_CB(skb)->filt = filt;
|
||||
|
||||
/* Add callback filter if matched */
|
||||
if (match_cb) {
|
||||
NGKNET_SKB_CB(skb)->filt_cb = filt_cb;
|
||||
}
|
||||
}
|
||||
|
||||
if (filt->mirror_type == NGKNET_FILTER_DEST_T_NETIF) {
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (filt->mirror_id == 0) {
|
||||
mirror_ndev = dev->net_dev;
|
||||
} else {
|
||||
mirror_ndev = dev->vdev[filt->mirror_id];
|
||||
}
|
||||
if (mirror_ndev) {
|
||||
mirror_skb = pskb_copy(skb, GFP_ATOMIC);
|
||||
if (mirror_skb) {
|
||||
mirror_skb->dev = mirror_ndev;
|
||||
if (filt->mirror_proto) {
|
||||
pkb->pkh.attrs |= PDMA_RX_SET_PROTO;
|
||||
mirror_skb->protocol = filt->mirror_proto;
|
||||
}
|
||||
if (dev->cbc->rx_cb) {
|
||||
NGKNET_SKB_CB(mirror_skb)->filt = filt;
|
||||
}
|
||||
priv = netdev_priv(mirror_ndev);
|
||||
priv->users++;
|
||||
*mndev = mirror_ndev;
|
||||
*mskb = mirror_skb;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
}
|
||||
|
||||
return SHR_E_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
ngknet_rl_process(timer_context_t data)
|
||||
{
|
||||
struct ngknet_rl_ctrl *rc = timer_arg(rc, data, timer);
|
||||
struct ngknet_dev *dev;
|
||||
unsigned long flags;
|
||||
int idx;
|
||||
|
||||
spin_lock_irqsave(&rc->lock, flags);
|
||||
rc->rx_pkts = 0;
|
||||
for (idx = 0; idx < NUM_PDMA_DEV_MAX; idx++) {
|
||||
dev = &rc->devs[idx];
|
||||
if (rc->dev_active[idx] && rc->dev_paused[idx]) {
|
||||
bcmcnet_pdma_dev_rx_resume(&dev->pdma_dev);
|
||||
rl_ctrl.dev_paused[dev->dev_no] = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&rc->lock, flags);
|
||||
|
||||
rc->timer.expires = jiffies + HZ / rc->rx_ticks;
|
||||
add_timer(&rc->timer);
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_rx_rate_limit_init(struct ngknet_dev *devs)
|
||||
{
|
||||
sal_memset(&rl_ctrl, 0, sizeof(rl_ctrl));
|
||||
rl_ctrl.rx_ticks = 10;
|
||||
setup_timer(&rl_ctrl.timer, ngknet_rl_process, (timer_context_t)&rl_ctrl);
|
||||
spin_lock_init(&rl_ctrl.lock);
|
||||
rl_ctrl.devs = devs;
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_rx_rate_limit_cleanup(void)
|
||||
{
|
||||
del_timer_sync(&rl_ctrl.timer);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_rx_rate_limit_started(void)
|
||||
{
|
||||
return rl_ctrl.started;
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_rx_rate_limit_start(struct ngknet_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rl_ctrl.lock, flags);
|
||||
rl_ctrl.dev_active[dev->dev_no] = 1;
|
||||
spin_unlock_irqrestore(&rl_ctrl.lock, flags);
|
||||
|
||||
if (!rl_ctrl.started) {
|
||||
rl_ctrl.started = 1;
|
||||
rl_ctrl.timer.expires = jiffies + HZ / rl_ctrl.rx_ticks;
|
||||
add_timer(&rl_ctrl.timer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_rx_rate_limit_stop(struct ngknet_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rl_ctrl.lock, flags);
|
||||
rl_ctrl.dev_active[dev->dev_no] = 0;
|
||||
spin_unlock_irqrestore(&rl_ctrl.lock, flags);
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rl_ctrl.lock, flags);
|
||||
if ((++rl_ctrl.rx_pkts + rl_ctrl.rx_overruns > limit / rl_ctrl.rx_ticks) &&
|
||||
!rl_ctrl.dev_paused[dev->dev_no] && rl_ctrl.dev_active[dev->dev_no]) {
|
||||
rl_ctrl.dev_paused[dev->dev_no] = 1;
|
||||
rl_ctrl.rx_overruns = 0;
|
||||
bcmcnet_pdma_dev_rx_suspend(&dev->pdma_dev);
|
||||
}
|
||||
if (rl_ctrl.dev_paused[dev->dev_no]) {
|
||||
rl_ctrl.rx_overruns++;
|
||||
}
|
||||
spin_unlock_irqrestore(&rl_ctrl.lock, flags);
|
||||
}
|
||||
|
||||
void
|
||||
ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue)
|
||||
{
|
||||
struct pkt_buf *pkb = (struct pkt_buf *)skb->data;
|
||||
|
||||
if (pkb->pkh.attrs & PDMA_TX_BIND_QUE) {
|
||||
*queue = pkb->pkh.queue_id;
|
||||
}
|
||||
}
|
||||
|
218
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h
Normal file
218
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h
Normal file
@ -0,0 +1,218 @@
|
||||
/*! \file ngknet_extra.h
|
||||
*
|
||||
* Generic data structure definitions for NGKNET enhancement.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_EXTRA_H
|
||||
#define NGKNET_EXTRA_H
|
||||
|
||||
/*!
|
||||
* \brief Filter control.
|
||||
*/
|
||||
struct filt_ctrl {
|
||||
/*! List head */
|
||||
struct list_head list;
|
||||
|
||||
/*! Device number */
|
||||
int dev_no;
|
||||
|
||||
/*! Number of hits */
|
||||
uint64_t hits;
|
||||
|
||||
/*! Filter description */
|
||||
ngknet_filter_t filt;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Create filter.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] filter Filter structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter);
|
||||
|
||||
/*!
|
||||
* \brief Destroy filter.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] id Filter ID.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_filter_destroy(struct ngknet_dev *dev, int id);
|
||||
|
||||
/*!
|
||||
* \brief Destroy all the filters.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_filter_destroy_all(struct ngknet_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Get filter.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] id Filter ID.
|
||||
* \param [out] filter Filter structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter);
|
||||
|
||||
/*!
|
||||
* \brief Get the next filter.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [out] filter Filter structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter);
|
||||
|
||||
/*!
|
||||
* \brief Filter packet.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] skb Rx packet SKB.
|
||||
* \param [out] mndev Mirror network interface.
|
||||
* \param [out] mskb Mirror Rx packet SKB.
|
||||
*
|
||||
* \retval Matched network interface.
|
||||
* \retval NULL No matched network interface.
|
||||
*/
|
||||
extern int
|
||||
ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev,
|
||||
struct net_device **mndev, struct sk_buff **mskb);
|
||||
|
||||
/*!
|
||||
* \brief Rx rate limit control.
|
||||
*
|
||||
* This contains all the control information for Rx rate limit such as
|
||||
* the number of Rx packets, status related to Rx rate limit, etc.
|
||||
*
|
||||
* The rate limit is kernel-oriented, i.e. all the Rx packets from any
|
||||
* device/channel will be accounted for. Once the received packets reach
|
||||
* the limit value in an 1-Sec interval, the driver API XXXX_rx_suspend()
|
||||
* will be called to suspend Rx. The 1-Sec basis timer will call the driver
|
||||
* API XXXX_rx_resume() to resume Rx and reset rate-related status/counters
|
||||
* at the begin of the next 1-Sec interval.
|
||||
*
|
||||
* The NGKNET module parameter 'rx_rate_limit' is used to decide the maximum
|
||||
* Rx rate. Disable Rx rate limit if set 0. It can be set when inserting
|
||||
* NGKNET module or modified using its SYSFS attributions.
|
||||
*/
|
||||
struct ngknet_rl_ctrl {
|
||||
/*! Rx packets */
|
||||
int rx_pkts;
|
||||
|
||||
/*! Rx overruns */
|
||||
int rx_overruns;
|
||||
|
||||
/*! Rx ticks */
|
||||
int rx_ticks;
|
||||
|
||||
/*! Active devices under rate control */
|
||||
int dev_active[NUM_PDMA_DEV_MAX];
|
||||
|
||||
/*! Paused devices due to no Rx credit */
|
||||
int dev_paused[NUM_PDMA_DEV_MAX];
|
||||
|
||||
/*! Rate limit timer */
|
||||
struct timer_list timer;
|
||||
|
||||
/*! Rate limit lock */
|
||||
spinlock_t lock;
|
||||
|
||||
/*! Devices */
|
||||
struct ngknet_dev *devs;
|
||||
|
||||
/*! Rate limit status indicator */
|
||||
int started;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Initialize Rx rate limit.
|
||||
*
|
||||
* \param [in] devs Devices array.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit_init(struct ngknet_dev *devs);
|
||||
|
||||
/*!
|
||||
* \brief Cleanup Rx rate limit.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit_cleanup(void);
|
||||
|
||||
/*!
|
||||
* \brief Get Rx rate limit state.
|
||||
*/
|
||||
extern int
|
||||
ngknet_rx_rate_limit_started(void);
|
||||
|
||||
/*!
|
||||
* \brief Start Rx rate limit.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit_start(struct ngknet_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Stop Rx rate limit.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit_stop(struct ngknet_dev *dev);
|
||||
|
||||
/*!
|
||||
* \brief Limit Rx rate.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit);
|
||||
|
||||
/*!
|
||||
* \brief Schedule Tx queue.
|
||||
*
|
||||
* \param [in] dev Device structure point.
|
||||
* \param [in] queue Tx queue number.
|
||||
*/
|
||||
extern void
|
||||
ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue);
|
||||
|
||||
#endif /* NGKNET_EXTRA_H */
|
||||
|
173
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c
Normal file
173
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c
Normal file
@ -0,0 +1,173 @@
|
||||
/*! \file ngknet_linux.c
|
||||
*
|
||||
* Utility routines for Linux kernel APIs abstraction.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "ngknet_linux.h"
|
||||
|
||||
/*!
|
||||
* Time
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
sal_time_usecs(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
kal_time_val_get(&tv);
|
||||
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
void
|
||||
sal_usleep(unsigned long usec)
|
||||
{
|
||||
unsigned long then, now, hz;
|
||||
|
||||
hz = usec * HZ / 1000000;
|
||||
if (hz) {
|
||||
schedule_timeout(hz);
|
||||
}
|
||||
usec = usec * HZ % 1000000 / HZ;
|
||||
if (usec) {
|
||||
then = sal_time_usecs();
|
||||
do {
|
||||
schedule();
|
||||
now = sal_time_usecs();
|
||||
} while (now > then && (now - then) < usec);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Synchronization
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
struct semaphore sem;
|
||||
char *desc;
|
||||
int binary;
|
||||
} sem_ctrl_t;
|
||||
|
||||
sal_sem_t
|
||||
sal_sem_create(char *desc, int binary, int count)
|
||||
{
|
||||
sem_ctrl_t *sc = kmalloc(sizeof(*sc), GFP_KERNEL);
|
||||
|
||||
if (sc != NULL) {
|
||||
sema_init(&sc->sem, count);
|
||||
sc->desc = desc;
|
||||
sc->binary = binary;
|
||||
}
|
||||
|
||||
return (sal_sem_t)sc;
|
||||
}
|
||||
|
||||
void
|
||||
sal_sem_destroy(sal_sem_t sem)
|
||||
{
|
||||
sem_ctrl_t *sc = (sem_ctrl_t *)sem;
|
||||
|
||||
kfree(sc);
|
||||
}
|
||||
|
||||
int
|
||||
sal_sem_take(sal_sem_t sem, int usec)
|
||||
{
|
||||
sem_ctrl_t *sc = (sem_ctrl_t *)sem;
|
||||
int rv;
|
||||
|
||||
if (usec == SAL_SEM_FOREVER) {
|
||||
do {
|
||||
rv = down_interruptible(&sc->sem);
|
||||
} while (rv == -EINTR);
|
||||
return rv ? -1 : 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sal_sem_give(sal_sem_t sem)
|
||||
{
|
||||
sem_ctrl_t *sc = (sem_ctrl_t *)sem;
|
||||
|
||||
up(&sc->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct spinlock_ctrl_s {
|
||||
spinlock_t spinlock;
|
||||
unsigned long flags;
|
||||
char *desc;
|
||||
} *spinlock_ctrl_t;
|
||||
|
||||
sal_spinlock_t
|
||||
sal_spinlock_create(char *desc)
|
||||
{
|
||||
spinlock_ctrl_t sl = kmalloc(sizeof(*sl), GFP_KERNEL);
|
||||
|
||||
if (sl != NULL) {
|
||||
spin_lock_init(&sl->spinlock);
|
||||
sl->flags = 0;
|
||||
sl->desc = desc;
|
||||
}
|
||||
|
||||
return (sal_spinlock_t)sl;
|
||||
}
|
||||
|
||||
void
|
||||
sal_spinlock_destroy(sal_spinlock_t lock)
|
||||
{
|
||||
spinlock_ctrl_t sl = (spinlock_ctrl_t)lock;
|
||||
|
||||
kfree(sl);
|
||||
}
|
||||
|
||||
int
|
||||
sal_spinlock_lock(sal_spinlock_t lock)
|
||||
{
|
||||
spinlock_ctrl_t sl = (spinlock_ctrl_t)lock;
|
||||
|
||||
spin_lock_irqsave(&sl->spinlock, sl->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sal_spinlock_unlock(sal_spinlock_t lock)
|
||||
{
|
||||
spinlock_ctrl_t sl = (spinlock_ctrl_t)lock;
|
||||
|
||||
spin_unlock_irqrestore(&sl->spinlock, sl->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
240
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h
Normal file
240
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h
Normal file
@ -0,0 +1,240 @@
|
||||
/*! \file ngknet_linux.h
|
||||
*
|
||||
* Data structure and macro definitions for Linux kernel APIs abstraction.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_LINUX_H
|
||||
#define NGKNET_LINUX_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/*!
|
||||
* Kernel abstraction
|
||||
*/
|
||||
|
||||
#define MODULE_PARAM(n, t, p) module_param(n, t, p)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
|
||||
#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \
|
||||
__vlan_hwaccel_put_tag(skb, tci)
|
||||
#define NETIF_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_RX
|
||||
#define NETIF_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_TX
|
||||
#else
|
||||
#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \
|
||||
__vlan_hwaccel_put_tag(skb, htons(proto), tci)
|
||||
#endif /* KERNEL_VERSION(3,10,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
|
||||
static inline int
|
||||
kal_support_paged_skb(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
kal_support_paged_skb(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif /* KERNEL_VERSION(3,6,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
|
||||
static inline struct page *
|
||||
kal_dev_alloc_page(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
|
||||
static inline struct page *
|
||||
kal_dev_alloc_page(void)
|
||||
{
|
||||
return alloc_pages(GFP_ATOMIC | __GFP_ZERO | __GFP_COLD |
|
||||
__GFP_COMP | __GFP_MEMALLOC, 0);
|
||||
}
|
||||
#else
|
||||
static inline struct page *
|
||||
kal_dev_alloc_page(void)
|
||||
{
|
||||
return dev_alloc_page();
|
||||
}
|
||||
#endif /* KERNEL_VERSION(3,6,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
|
||||
static inline struct sk_buff *
|
||||
kal_build_skb(void *data, unsigned int frag_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static inline struct sk_buff *
|
||||
kal_build_skb(void *data, unsigned int frag_size)
|
||||
{
|
||||
return build_skb(data, frag_size);
|
||||
}
|
||||
#endif /* KERNEL_VERSION(3,6,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
|
||||
static inline void
|
||||
kal_netif_trans_update(struct net_device *dev)
|
||||
{
|
||||
dev->trans_start = jiffies;
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
kal_netif_trans_update(struct net_device *dev)
|
||||
{
|
||||
netif_trans_update(dev);
|
||||
}
|
||||
#endif /* KERNEL_VERSION(4,7,0) */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
|
||||
static inline void
|
||||
kal_time_val_get(struct timeval *tv)
|
||||
{
|
||||
do_gettimeofday(tv);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
kal_time_val_get(struct timeval *tv)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
ktime_get_real_ts64(&ts);
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
tv->tv_usec = ts.tv_nsec / 1000;
|
||||
}
|
||||
#endif /* KERNEL_VERSION(3,17,0) */
|
||||
|
||||
static inline unsigned long
|
||||
kal_copy_from_user(void *to, const void __user *from,
|
||||
unsigned int dl, unsigned int sl)
|
||||
{
|
||||
unsigned int len = dl;
|
||||
|
||||
if (unlikely(len != sl)) {
|
||||
printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n");
|
||||
len = min(dl, sl);
|
||||
}
|
||||
|
||||
return copy_from_user(to, from, len);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
kal_copy_to_user(void __user *to, const void *from,
|
||||
unsigned int dl, unsigned int sl)
|
||||
{
|
||||
unsigned int len = dl;
|
||||
|
||||
if (unlikely(len != sl)) {
|
||||
printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n");
|
||||
len = min(dl, sl);
|
||||
}
|
||||
|
||||
return copy_to_user(to, from, len);
|
||||
}
|
||||
|
||||
/*!
|
||||
* System abstraction
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
sal_alloc(unsigned int sz, char *s)
|
||||
{
|
||||
return kmalloc(sz, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sal_free(void *addr)
|
||||
{
|
||||
kfree(addr);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
sal_memset(void *dest, int c, size_t cnt)
|
||||
{
|
||||
return memset(dest, c, cnt);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
sal_memcpy(void *dest, const void *src, size_t cnt)
|
||||
{
|
||||
return memcpy(dest, src, cnt);
|
||||
}
|
||||
|
||||
static inline char *
|
||||
sal_strncpy(char *dest, const char *src, size_t cnt)
|
||||
{
|
||||
return strncpy(dest, src, cnt);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Time
|
||||
*/
|
||||
|
||||
extern unsigned long
|
||||
sal_time_usecs(void);
|
||||
|
||||
extern void
|
||||
sal_usleep(unsigned long usec);
|
||||
|
||||
/*!
|
||||
* Synchronization
|
||||
*/
|
||||
|
||||
typedef struct sal_sem_s {
|
||||
char semaphore_opaque_type;
|
||||
} *sal_sem_t;
|
||||
|
||||
typedef struct sal_spinlock_s {
|
||||
char spinlock_opaque_type;
|
||||
} *sal_spinlock_t;
|
||||
|
||||
#define SAL_SEM_FOREVER -1
|
||||
#define SAL_SEM_BINARY 1
|
||||
#define SAL_SEM_COUNTING 0
|
||||
|
||||
extern sal_sem_t
|
||||
sal_sem_create(char *desc, int binary, int count);
|
||||
|
||||
extern void
|
||||
sal_sem_destroy(sal_sem_t sem);
|
||||
|
||||
extern int
|
||||
sal_sem_take(sal_sem_t sem, int usec);
|
||||
|
||||
extern int
|
||||
sal_sem_give(sal_sem_t sem);
|
||||
|
||||
extern sal_spinlock_t
|
||||
sal_spinlock_create(char *desc);
|
||||
|
||||
extern void
|
||||
sal_spinlock_destroy(sal_spinlock_t lock);
|
||||
|
||||
extern int
|
||||
sal_spinlock_lock(sal_spinlock_t lock);
|
||||
|
||||
extern int
|
||||
sal_spinlock_unlock(sal_spinlock_t lock);
|
||||
|
||||
#endif /* NGKNET_LINUX_H */
|
||||
|
2689
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c
Normal file
2689
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c
Normal file
File diff suppressed because it is too large
Load Diff
278
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h
Normal file
278
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h
Normal file
@ -0,0 +1,278 @@
|
||||
/*! \file ngknet_main.h
|
||||
*
|
||||
* Data structure and macro definitions for NGKNET kernel module.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_MAIN_H
|
||||
#define NGKNET_MAIN_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <lkm/lkm.h>
|
||||
#include <lkm/ngknet_dev.h>
|
||||
#include <bcmcnet/bcmcnet_core.h>
|
||||
|
||||
/*! Maximum number of PDMA devices supported */
|
||||
#ifdef NGBDE_NUM_SWDEV_MAX
|
||||
#define NUM_PDMA_DEV_MAX NGBDE_NUM_SWDEV_MAX
|
||||
#else
|
||||
#define NUM_PDMA_DEV_MAX 16
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Debug levels
|
||||
*/
|
||||
#define DBG_LVL_VERB 0x0001
|
||||
#define DBG_LVL_PKT 0x0002
|
||||
#define DBG_LVL_CMD 0x0004
|
||||
#define DBG_LVL_IRQ 0x0008
|
||||
#define DBG_LVL_NAPI 0x0010
|
||||
#define DBG_LVL_NDEV 0x0020
|
||||
#define DBG_LVL_FILT 0x0040
|
||||
#define DBG_LVL_RCPU 0x0080
|
||||
#define DBG_LVL_WARN 0x0100
|
||||
#define DBG_LVL_PDMP 0x0200
|
||||
#define DBG_LVL_RATE 0x0400
|
||||
#define DBG_LVL_LINK 0x0800
|
||||
|
||||
#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) printk _s; } while (0)
|
||||
#define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) printk _s; } while (0)
|
||||
#define DBG_CMD(_s) do { if (debug & DBG_LVL_CMD) printk _s; } while (0)
|
||||
#define DBG_IRQ(_s) do { if (debug & DBG_LVL_IRQ) printk _s; } while (0)
|
||||
#define DBG_NAPI(_s) do { if (debug & DBG_LVL_NAPI) printk _s; } while (0)
|
||||
#define DBG_NDEV(_s) do { if (debug & DBG_LVL_NDEV) printk _s; } while (0)
|
||||
#define DBG_FILT(_s) do { if (debug & DBG_LVL_FILT) printk _s; } while (0)
|
||||
#define DBG_RCPU(_s) do { if (debug & DBG_LVL_RCPU) printk _s; } while (0)
|
||||
#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) printk _s; } while (0)
|
||||
#define DBG_PDMP(_s) do { if (debug & DBG_LVL_PDMP) printk _s; } while (0)
|
||||
#define DBG_RATE(_s) do { if (debug & DBG_LVL_RATE) printk _s; } while (0)
|
||||
#define DBG_LINK(_s) do { if (debug & DBG_LVL_LINK) printk _s; } while (0)
|
||||
|
||||
/*!
|
||||
* Device description
|
||||
*/
|
||||
struct ngknet_dev {
|
||||
/*! Base address for PCI register access */
|
||||
volatile void *base_addr;
|
||||
|
||||
/*! Required for DMA memory control */
|
||||
struct device *dev;
|
||||
|
||||
/*! Required for PCI memory control */
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
/*! Base network device */
|
||||
struct net_device *net_dev;
|
||||
|
||||
/*! PDMA device */
|
||||
struct pdma_dev pdma_dev;
|
||||
|
||||
/*! Device number (from BDE) */
|
||||
int dev_no;
|
||||
|
||||
/*! Vitual network devices, 0 is reserved */
|
||||
struct net_device *vdev[NUM_VDEV_MAX + 1];
|
||||
|
||||
/*! Vitual network devices bound to queue */
|
||||
struct net_device *bdev[NUM_QUE_MAX];
|
||||
|
||||
/*! Filter list */
|
||||
struct list_head filt_list;
|
||||
|
||||
/*! Filter control, 0 is reserved */
|
||||
void *fc[NUM_FILTER_MAX + 1];
|
||||
|
||||
/*! Callback control */
|
||||
struct ngknet_callback_ctrl *cbc;
|
||||
|
||||
/*! RCPU control */
|
||||
struct ngknet_rcpu_hdr rcpu_ctrl;
|
||||
|
||||
/*! NGKNET lock */
|
||||
spinlock_t lock;
|
||||
|
||||
/*! NGKNET wait queue */
|
||||
wait_queue_head_t wq;
|
||||
|
||||
/*! VNET wait queue */
|
||||
wait_queue_head_t vnet_wq;
|
||||
|
||||
/*! VNET is active */
|
||||
atomic_t vnet_active;
|
||||
|
||||
/*! HNET wait queue */
|
||||
wait_queue_head_t hnet_wq;
|
||||
|
||||
/*! HNET is active */
|
||||
atomic_t hnet_active;
|
||||
|
||||
/*! HNET deamon */
|
||||
struct task_struct *hnet_task;
|
||||
|
||||
/*! HNET work */
|
||||
struct work_struct hnet_work;
|
||||
|
||||
/*! PTP Tx queue */
|
||||
struct sk_buff_head ptp_tx_queue;
|
||||
|
||||
/*! PTP Tx work */
|
||||
struct work_struct ptp_tx_work;
|
||||
|
||||
/*! Flags */
|
||||
int flags;
|
||||
/*! NGKNET device is active */
|
||||
#define NGKNET_DEV_ACTIVE (1 << 0)
|
||||
};
|
||||
|
||||
/*!
|
||||
* Network interface specific private data
|
||||
*/
|
||||
struct ngknet_private {
|
||||
/*! Network device */
|
||||
struct net_device *net_dev;
|
||||
|
||||
/*! Network stats */
|
||||
struct net_device_stats stats;
|
||||
|
||||
/*! NGKNET device */
|
||||
struct ngknet_dev *bkn_dev;
|
||||
|
||||
/*! Network interface ID */
|
||||
int id;
|
||||
|
||||
/*! Network interface type */
|
||||
int type;
|
||||
|
||||
/*! Network interface flags */
|
||||
uint32_t flags;
|
||||
|
||||
/*! Network interface vlan */
|
||||
uint32_t vlan;
|
||||
|
||||
/*! Network interface bound to */
|
||||
uint32_t chan;
|
||||
|
||||
/*! Metadata offset from Ethernet header */
|
||||
uint32_t meta_off;
|
||||
|
||||
/*! Metadata length */
|
||||
uint32_t meta_len;
|
||||
|
||||
/*! Metadata used to send packets to physical port */
|
||||
uint8_t meta_data[NGKNET_NETIF_META_MAX];
|
||||
|
||||
/*! User data gotten back through callbacks */
|
||||
uint8_t user_data[NGKNET_NETIF_USER_DATA];
|
||||
|
||||
/*! Users of this network interface */
|
||||
int users;
|
||||
|
||||
/*! Wait for this network interface free */
|
||||
int wait;
|
||||
|
||||
/*! HW timestamp Rx filter */
|
||||
int hwts_rx_filter;
|
||||
|
||||
/*! HW timestamp Tx type */
|
||||
int hwts_tx_type;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Create network interface.
|
||||
*
|
||||
* \param [in] dev NGKNET device structure point.
|
||||
* \param [in] netif Network interface structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_create(struct ngknet_dev *dev, ngknet_netif_t *netif);
|
||||
|
||||
/*!
|
||||
* \brief Destroy network interface.
|
||||
*
|
||||
* \param [in] dev NGKNET device structure point.
|
||||
* \param [in] id Network interface ID.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_destroy(struct ngknet_dev *dev, int id);
|
||||
|
||||
/*!
|
||||
* \brief Get network interface.
|
||||
*
|
||||
* \param [in] dev NGKNET device structure point.
|
||||
* \param [in] id Network interface ID.
|
||||
* \param [out] netif Network interface structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_get(struct ngknet_dev *dev, int id, ngknet_netif_t *netif);
|
||||
|
||||
/*!
|
||||
* \brief Get the next network interface.
|
||||
*
|
||||
* \param [in] dev NGKNET device structure point.
|
||||
* \param [out] netif Network interface structure point.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
* \retval SHR_E_XXXX Operation failed.
|
||||
*/
|
||||
extern int
|
||||
ngknet_netif_get_next(struct ngknet_dev *dev, ngknet_netif_t *netif);
|
||||
|
||||
/*!
|
||||
* \brief Get debug level.
|
||||
*
|
||||
* \retval Current debug level.
|
||||
*/
|
||||
extern int
|
||||
ngknet_debug_level_get(void);
|
||||
|
||||
/*!
|
||||
* \brief Set debug level.
|
||||
*
|
||||
* \param [in] debug_level Debug level to be set.
|
||||
*/
|
||||
extern void
|
||||
ngknet_debug_level_set(int debug_level);
|
||||
|
||||
/*!
|
||||
* \brief Get Rx rate limit.
|
||||
*
|
||||
* \retval Current Rx rate limit.
|
||||
*/
|
||||
extern int
|
||||
ngknet_rx_rate_limit_get(void);
|
||||
|
||||
/*!
|
||||
* \brief Set Rx rate limit.
|
||||
*
|
||||
* \param [in] rate_limit Rx rate limit to be set.
|
||||
*/
|
||||
extern void
|
||||
ngknet_rx_rate_limit_set(int rate_limit);
|
||||
|
||||
#endif /* NGKNET_MAIN_H */
|
||||
|
@ -0,0 +1,655 @@
|
||||
/*! \file ngknet_procfs.c
|
||||
*
|
||||
* <description>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include <lkm/lkm.h>
|
||||
#include <lkm/ngknet_ioctl.h>
|
||||
#include "ngknet_main.h"
|
||||
#include "ngknet_extra.h"
|
||||
|
||||
extern struct ngknet_dev ngknet_devices[];
|
||||
|
||||
static struct proc_dir_entry *proc_root = NULL;
|
||||
|
||||
static void
|
||||
proc_data_show(struct seq_file *m, const unsigned char *buf, size_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (!buf || !len) {
|
||||
seq_printf(m, "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
seq_printf(m, "%02x ", buf[i]);
|
||||
if ((i + 1) % 32 == 0 || (i + 1) == len) {
|
||||
seq_printf(m, "\n");
|
||||
if ((i + 1) < len) {
|
||||
seq_printf(m, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
proc_debug_level_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "Debug level: 0x%x\n", ngknet_debug_level_get());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_debug_level_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_debug_level_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
proc_debug_level_write(struct file *file, const char *buf,
|
||||
size_t count, loff_t *loff)
|
||||
{
|
||||
char level_str[11] = {0};
|
||||
int debug_level;
|
||||
|
||||
if (copy_from_user(level_str, buf, sizeof(level_str) - 1)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
debug_level = simple_strtol(level_str, NULL, 16);
|
||||
|
||||
ngknet_debug_level_set(debug_level);
|
||||
printk("Debug level set to: 0x%x\n", debug_level);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_debug_level_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_debug_level_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_debug_level_open,
|
||||
read: seq_read,
|
||||
write: proc_debug_level_write,
|
||||
llseek: seq_lseek,
|
||||
release: proc_debug_level_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_device_info_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
struct bcmcnet_dev_info *info;
|
||||
int di, qi, ai = 0;
|
||||
int rv;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
ai++;
|
||||
|
||||
rv = bcmcnet_pdma_dev_info_get(&dev->pdma_dev);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
printk("ngknet: get device%d info failed\n", di);
|
||||
break;
|
||||
}
|
||||
|
||||
info = &dev->pdma_dev.info;
|
||||
seq_printf(m, "dev_no: %d\n", di);
|
||||
seq_printf(m, "dev_name: %s\n", info->dev_name);
|
||||
seq_printf(m, "dev_id: 0x%x\n", info->dev_id);
|
||||
seq_printf(m, "dev_type: %d\n", info->dev_type);
|
||||
seq_printf(m, "max_groups: %d\n", info->max_groups);
|
||||
seq_printf(m, "max_queues: %d\n", info->max_queues);
|
||||
seq_printf(m, "bm_groups: 0x%x\n", info->bm_groups);
|
||||
seq_printf(m, "bm_rx_queues: 0x%x\n", info->bm_rx_queues);
|
||||
seq_printf(m, "bm_tx_queues: 0x%x\n", info->bm_tx_queues);
|
||||
seq_printf(m, "nb_groups: %d\n", info->nb_groups);
|
||||
seq_printf(m, "nb_rx_queues: %d\n", info->nb_rx_queues);
|
||||
seq_printf(m, "nb_tx_queues: %d\n", info->nb_tx_queues);
|
||||
seq_printf(m, "rx_desc_size: %d\n", info->rx_desc_size);
|
||||
seq_printf(m, "tx_desc_size: %d\n", info->tx_desc_size);
|
||||
seq_printf(m, "rx_ph_size: %d\n", info->rx_ph_size);
|
||||
seq_printf(m, "tx_ph_size: %d\n", info->tx_ph_size);
|
||||
for (qi = 0; qi < info->nb_rx_queues; qi++) {
|
||||
seq_printf(m, "rx_buf_sz[%d]: %d\n", qi, info->rx_buf_size[qi]);
|
||||
}
|
||||
for (qi = 0; qi < info->nb_rx_queues; qi++) {
|
||||
seq_printf(m, "nb_rx_desc[%d]: %d\n", qi, info->nb_rx_desc[qi]);
|
||||
}
|
||||
for (qi = 0; qi < info->nb_tx_queues; qi++) {
|
||||
seq_printf(m, "nb_tx_desc[%d]: %d\n", qi, info->nb_tx_desc[qi]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ai) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "------------------------\n");
|
||||
seq_printf(m, "Total %d devices\n", ai);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_device_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_device_info_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_device_info_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_device_info_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_device_info_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_device_info_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_filter_info_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
ngknet_filter_t filt = {0};
|
||||
int di, dn = 0, fn = 0;
|
||||
int rv;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
dn++;
|
||||
|
||||
do {
|
||||
rv = ngknet_filter_get_next(dev, &filt);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
printk("ngknet: get device%d filter failed\n", di);
|
||||
break;
|
||||
}
|
||||
fn++;
|
||||
|
||||
seq_printf(m, "\n");
|
||||
seq_printf(m, "dev_no: %d\n", di);
|
||||
seq_printf(m, "id: %d\n", filt.id);
|
||||
seq_printf(m, "next: %d\n", filt.next);
|
||||
seq_printf(m, "type: %d\n", filt.type);
|
||||
seq_printf(m, "flags: 0x%x\n", filt.flags);
|
||||
seq_printf(m, "prio: %d\n", filt.priority);
|
||||
seq_printf(m, "chan: %d\n", filt.chan);
|
||||
seq_printf(m, "desc: %s\n", filt.desc);
|
||||
seq_printf(m, "dest_type: %d\n", filt.dest_type);
|
||||
seq_printf(m, "dest_id: %d\n", filt.dest_id);
|
||||
seq_printf(m, "dest_proto: 0x%x\n", filt.dest_proto);
|
||||
seq_printf(m, "mirror_type: %d\n", filt.mirror_type);
|
||||
seq_printf(m, "mirror_id: %d\n", filt.mirror_id);
|
||||
seq_printf(m, "mirror_proto: 0x%x\n", filt.mirror_proto);
|
||||
seq_printf(m, "oob_offset: %d\n", filt.oob_data_offset);
|
||||
seq_printf(m, "oob_size: %d\n", filt.oob_data_size);
|
||||
seq_printf(m, "pkt_offset: %d\n", filt.pkt_data_offset);
|
||||
seq_printf(m, "pkt_size: %d\n", filt.pkt_data_size);
|
||||
seq_printf(m, "filt_data: ");
|
||||
proc_data_show(m, filt.data.b, filt.oob_data_size + filt.pkt_data_size);
|
||||
seq_printf(m, "filt_mask: ");
|
||||
proc_data_show(m, filt.mask.b, filt.oob_data_size + filt.pkt_data_size);
|
||||
seq_printf(m, "user_data: ");
|
||||
proc_data_show(m, filt.user_data, NGKNET_FILTER_USER_DATA);
|
||||
seq_printf(m, "hits: %llu\n", ((struct filt_ctrl *)dev->fc[filt.id])->hits);
|
||||
} while (filt.next);
|
||||
}
|
||||
|
||||
if (!dn) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "--------------------------------\n");
|
||||
seq_printf(m, "Total %d devices, %d filters\n", dn, fn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_filter_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_filter_info_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_filter_info_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_filter_info_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_filter_info_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_filter_info_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_netif_info_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
struct net_device *ndev;
|
||||
struct ngknet_private *priv;
|
||||
ngknet_netif_t netif = {0};
|
||||
int di, ma, dn = 0, nn = 0;
|
||||
int rv;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
dn++;
|
||||
|
||||
do {
|
||||
rv = ngknet_netif_get_next(dev, &netif);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
printk("ngknet: get device%d netif failed\n", di);
|
||||
break;
|
||||
}
|
||||
nn++;
|
||||
ndev = netif.id == 0 ? dev->net_dev : dev->vdev[netif.id];
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
seq_printf(m, "\n");
|
||||
seq_printf(m, "dev_no: %d\n", di);
|
||||
seq_printf(m, "id: %d\n", netif.id);
|
||||
seq_printf(m, "next: %d\n", netif.next);
|
||||
seq_printf(m, "type: %d\n", netif.type);
|
||||
seq_printf(m, "flags: 0x%x\n", netif.flags);
|
||||
seq_printf(m, "vlan: %d\n", netif.vlan);
|
||||
seq_printf(m, "mac: ");
|
||||
for (ma = 0; ma < 6; ma++) {
|
||||
if (ma == 5) {
|
||||
seq_printf(m, "%02x\n", netif.macaddr[ma]);
|
||||
} else {
|
||||
seq_printf(m, "%02x:", netif.macaddr[ma]);
|
||||
}
|
||||
}
|
||||
seq_printf(m, "mtu: %d\n", netif.mtu);
|
||||
seq_printf(m, "chan: %d\n", netif.chan);
|
||||
seq_printf(m, "name: %s\n", netif.name);
|
||||
seq_printf(m, "meta_off: %d\n", netif.meta_off);
|
||||
seq_printf(m, "meta_len: %d\n", netif.meta_len);
|
||||
seq_printf(m, "meta_data: ");
|
||||
proc_data_show(m, netif.meta_data, netif.meta_len);
|
||||
seq_printf(m, "user_data: ");
|
||||
proc_data_show(m, netif.user_data, NGKNET_NETIF_USER_DATA);
|
||||
seq_printf(m, "rx_packets: %lu\n", priv->stats.rx_packets);
|
||||
seq_printf(m, "rx_bytes: %lu\n", priv->stats.rx_bytes);
|
||||
seq_printf(m, "rx_dropped: %lu\n", priv->stats.rx_dropped);
|
||||
seq_printf(m, "rx_errors: %lu\n", priv->stats.rx_errors);
|
||||
seq_printf(m, "tx_packets: %lu\n", priv->stats.tx_packets);
|
||||
seq_printf(m, "tx_bytes: %lu\n", priv->stats.tx_bytes);
|
||||
seq_printf(m, "tx_dropped: %lu\n", priv->stats.tx_dropped);
|
||||
seq_printf(m, "tx_errors: %lu\n", priv->stats.tx_errors);
|
||||
} while (netif.next);
|
||||
}
|
||||
|
||||
if (!dn) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "--------------------------------\n");
|
||||
seq_printf(m, "Total %d devices, %d netifs\n", dn, nn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_netif_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_netif_info_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_netif_info_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_netif_info_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_netif_info_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_netif_info_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_pkt_stats_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
struct bcmcnet_dev_stats *stats;
|
||||
int di, qi, ai = 0;
|
||||
int rv;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
ai++;
|
||||
|
||||
rv = bcmcnet_pdma_dev_stats_get(&dev->pdma_dev);
|
||||
if (SHR_FAILURE(rv)) {
|
||||
printk("ngknet: get device%d stats failed\n", di);
|
||||
break;
|
||||
}
|
||||
|
||||
stats = &dev->pdma_dev.stats;
|
||||
seq_printf(m, "rx_packets: %llu\n", (unsigned long long)stats->rx_packets);
|
||||
seq_printf(m, "rx_bytes: %llu\n", (unsigned long long)stats->rx_bytes);
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) {
|
||||
seq_printf(m, "rx_packets[%d]: %llu\n", qi, (unsigned long long)stats->rxq_packets[qi]);
|
||||
seq_printf(m, "rx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->rxq_bytes[qi]);
|
||||
}
|
||||
seq_printf(m, "rx_dropped: %llu\n", (unsigned long long)stats->rx_dropped);
|
||||
seq_printf(m, "rx_errors: %llu\n", (unsigned long long)stats->rx_errors);
|
||||
seq_printf(m, "rx_nomems: %llu\n", (unsigned long long)stats->rx_nomems);
|
||||
seq_printf(m, "tx_packets: %llu\n", (unsigned long long)stats->tx_packets);
|
||||
seq_printf(m, "tx_bytes: %llu\n", (unsigned long long)stats->tx_bytes);
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) {
|
||||
seq_printf(m, "tx_packets[%d]: %llu\n", qi, (unsigned long long)stats->txq_packets[qi]);
|
||||
seq_printf(m, "tx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->txq_bytes[qi]);
|
||||
}
|
||||
seq_printf(m, "tx_dropped: %llu\n", (unsigned long long)stats->tx_dropped);
|
||||
seq_printf(m, "tx_errors: %llu\n", (unsigned long long)stats->tx_errors);
|
||||
seq_printf(m, "tx_xoffs: %llu\n", (unsigned long long)stats->tx_xoffs);
|
||||
seq_printf(m, "interrupts: %llu\n", (unsigned long long)stats->intrs);
|
||||
}
|
||||
|
||||
if (!ai) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "------------------------\n");
|
||||
seq_printf(m, "Total %d devices\n", ai);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_pkt_stats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_pkt_stats_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_pkt_stats_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_pkt_stats_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_pkt_stats_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_pkt_stats_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_rate_limit_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "Rx rate limit: %d pps\n", ngknet_rx_rate_limit_get());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_rate_limit_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_rate_limit_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
proc_rate_limit_write(struct file *file, const char *buf,
|
||||
size_t count, loff_t *loff)
|
||||
{
|
||||
char limit_str[9] = {0};
|
||||
int rate_limit;
|
||||
|
||||
if (copy_from_user(limit_str, buf, sizeof(limit_str) - 1)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
rate_limit = simple_strtol(limit_str, NULL, 10);
|
||||
|
||||
ngknet_rx_rate_limit_set(rate_limit);
|
||||
printk("Rx rate limit set to: %d pps\n", rate_limit);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_rate_limit_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_rate_limit_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_rate_limit_open,
|
||||
read: seq_read,
|
||||
write: proc_rate_limit_write,
|
||||
llseek: seq_lseek,
|
||||
release: proc_rate_limit_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_reg_status_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
int di, qi, ai = 0;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
ai++;
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) {
|
||||
bcmcnet_pdma_rx_queue_reg_dump(&dev->pdma_dev, qi);
|
||||
}
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) {
|
||||
bcmcnet_pdma_tx_queue_reg_dump(&dev->pdma_dev, qi);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ai) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "------------------------\n");
|
||||
seq_printf(m, "Total %d devices\n", ai);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_reg_status_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_reg_status_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_reg_status_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_reg_status_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_reg_status_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_reg_status_release,
|
||||
};
|
||||
|
||||
static int
|
||||
proc_ring_status_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct ngknet_dev *dev;
|
||||
int di, qi, ai = 0;
|
||||
|
||||
for (di = 0; di < NUM_PDMA_DEV_MAX; di++) {
|
||||
dev = &ngknet_devices[di];
|
||||
if (!(dev->flags & NGKNET_DEV_ACTIVE)) {
|
||||
continue;
|
||||
}
|
||||
ai++;
|
||||
seq_printf(m, "%s-%d, ", "Unit", di);
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) {
|
||||
bcmcnet_pdma_rx_ring_dump(&dev->pdma_dev, qi);
|
||||
}
|
||||
seq_printf(m, "%s%d, ", "Rx queues: ", qi);
|
||||
for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) {
|
||||
bcmcnet_pdma_tx_ring_dump(&dev->pdma_dev, qi);
|
||||
}
|
||||
seq_printf(m, "%s%d. ", "Tx queues: ", qi);
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
|
||||
if (!ai) {
|
||||
seq_printf(m, "%s\n", "No active device");
|
||||
} else {
|
||||
seq_printf(m, "------------------------\n");
|
||||
seq_printf(m, "Total %d devices\n", ai);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_ring_status_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_ring_status_show, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_ring_status_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static struct file_operations proc_ring_status_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: proc_ring_status_open,
|
||||
read: seq_read,
|
||||
llseek: seq_lseek,
|
||||
release: proc_ring_status_release,
|
||||
};
|
||||
|
||||
int
|
||||
ngknet_procfs_init(void)
|
||||
{
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
|
||||
proc_root = proc_mkdir(NGKNET_MODULE_NAME, NULL);
|
||||
if (proc_root == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_mkdir failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "debug_level", 0666, proc_root, &proc_debug_level_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "device_info", 0444, proc_root, &proc_device_info_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "filter_info", 0444, proc_root, &proc_filter_info_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "netif_info", 0444, proc_root, &proc_netif_info_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "pkt_stats", 0444, proc_root, &proc_pkt_stats_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "rate_limit", 0666, proc_root, &proc_rate_limit_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "reg_status", 0444, proc_root, &proc_reg_status_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "ring_status", 0444, proc_root, &proc_ring_status_fops);
|
||||
if (entry == NULL) {
|
||||
printk(KERN_ERR "ngknet: proc_create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_procfs_cleanup(void)
|
||||
{
|
||||
remove_proc_entry("debug_level", proc_root);
|
||||
remove_proc_entry("device_info", proc_root);
|
||||
remove_proc_entry("filter_info", proc_root);
|
||||
remove_proc_entry("netif_info", proc_root);
|
||||
remove_proc_entry("pkt_stats", proc_root);
|
||||
remove_proc_entry("rate_limit", proc_root);
|
||||
remove_proc_entry("reg_status", proc_root);
|
||||
remove_proc_entry("ring_status", proc_root);
|
||||
|
||||
remove_proc_entry(NGKNET_MODULE_NAME, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*! \file ngknet_procfs.h
|
||||
*
|
||||
* Procfs-related definitions and APIs for NGKNET module.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_PROCFS_H
|
||||
#define NGKNET_PROCFS_H
|
||||
|
||||
/*!
|
||||
* \brief Initialize procfs for KNET driver.
|
||||
*
|
||||
* Create procfs read/write interfaces.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngknet_procfs_init(void);
|
||||
|
||||
/*!
|
||||
* \brief Clean up procfs for KNET driver.
|
||||
*
|
||||
* Clean up resources allocated by \ref ngknet_procfs_init.
|
||||
*
|
||||
* \return 0 if no errors, otherwise -1.
|
||||
*/
|
||||
extern int
|
||||
ngknet_procfs_cleanup(void);
|
||||
|
||||
#endif /* NGKNET_PROCFS_H */
|
||||
|
194
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c
Normal file
194
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*! \file ngknet_ptp.c
|
||||
*
|
||||
* Utility routines for PTP.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#include "ngknet_callback.h"
|
||||
#include "ngknet_ptp.h"
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
|
||||
if (!dev->cbc->ptp_rx_config_set_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The expected Rx filter value is passed to the callback. The callback
|
||||
* should pass back the actual filter value by the paramter <filter>.
|
||||
* The callback can use priv->user_data to get other private parameters
|
||||
* such as phys_port, dev_type, etc, which should be introduced when the
|
||||
* netif is created.
|
||||
*/
|
||||
return dev->cbc->ptp_rx_config_set_cb(priv, filter);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_config_set(struct net_device *ndev, int type)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
|
||||
if (!dev->cbc->ptp_tx_config_set_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Tx type value is passed to the callback by the parameter <type>.
|
||||
* The callback should do the configuration according to the type.
|
||||
* The callback can use priv->user_data to get other private parameters
|
||||
* such as phys_port, dev_type, etc, which should be introduced when the
|
||||
* netif is created.
|
||||
*/
|
||||
return dev->cbc->ptp_tx_config_set_cb(priv, &type);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb);
|
||||
struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data;
|
||||
|
||||
if (!dev->cbc->ptp_rx_hwts_get_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
cbd->dev_no = dev->dev_no;
|
||||
cbd->dev_id = dev->pdma_dev.dev_id;
|
||||
cbd->priv = priv;
|
||||
cbd->pmd = skb->data + PKT_HDR_SIZE;
|
||||
cbd->pmd_len = pkh->meta_len;
|
||||
cbd->pkt_len = pkh->data_len;
|
||||
|
||||
/*
|
||||
* The callback should get timestamp value for a Rx packet and return
|
||||
* by the parameter <ts>.
|
||||
* Some parameters have been consolidated to SKB as above. They can be
|
||||
* achieved by NGKNET_SKB_CB(skb). Specially more private paramters are
|
||||
* in NGKNET_SKB_CB(skb)->priv->user_data[].
|
||||
*/
|
||||
return dev->cbc->ptp_rx_hwts_get_cb(skb, ts);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb);
|
||||
struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data;
|
||||
|
||||
if (!dev->cbc->ptp_tx_hwts_get_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
cbd->dev_no = dev->dev_no;
|
||||
cbd->dev_id = dev->pdma_dev.dev_id;
|
||||
cbd->priv = priv;
|
||||
cbd->pmd = skb->data + PKT_HDR_SIZE;
|
||||
cbd->pmd_len = pkh->meta_len;
|
||||
cbd->pkt_len = pkh->data_len;
|
||||
|
||||
/*
|
||||
* The callback should get timestamp value for a Tx packet and return
|
||||
* by the parameter <ts>.
|
||||
* For HWTSTAMP_TX_ONESTEP_SYNC type, the time value can be achieved and
|
||||
* returned immediately. Otherwise, for HWTSTAMP_TX_ON type, the callback
|
||||
* should wait till the time value can be available, i.e. the packet has
|
||||
* been tranmitted out from port.
|
||||
* Some parameters have been consolidated to SKB as above. They can be
|
||||
* achieved by NGKNET_SKB_CB(skb). Specially more private paramters are
|
||||
* in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type,
|
||||
* and so on.
|
||||
*/
|
||||
return dev->cbc->ptp_tx_hwts_get_cb(skb, ts);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb);
|
||||
struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data;
|
||||
|
||||
if (!dev->cbc->ptp_tx_meta_set_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
cbd->dev_no = dev->dev_no;
|
||||
cbd->dev_id = dev->pdma_dev.dev_id;
|
||||
cbd->priv = priv;
|
||||
cbd->pmd = skb->data + PKT_HDR_SIZE;
|
||||
cbd->pmd_len = pkh->meta_len;
|
||||
cbd->pkt_len = pkh->data_len;
|
||||
|
||||
/*
|
||||
* The callback should configure the metadata <NGKNET_SKB_CB(skb)->pmd>
|
||||
* for HW timestamping according to the corresponding switch device.
|
||||
* Some parameters have been consolidated to SKB as above. They can be
|
||||
* achieved by NGKNET_SKB_CB(skb). Specially more private paramters are
|
||||
* in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type,
|
||||
* and so on.
|
||||
*/
|
||||
return dev->cbc->ptp_tx_meta_set_cb(skb);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_phc_index_get(struct net_device *ndev, int *index)
|
||||
{
|
||||
struct ngknet_private *priv = netdev_priv(ndev);
|
||||
struct ngknet_dev *dev = priv->bkn_dev;
|
||||
|
||||
if (!dev->cbc->ptp_phc_index_get_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The callback should return the HPC index by the parameter <index>.
|
||||
* priv->user_data[] can be used to get other private parameters such as
|
||||
* phys_port, dev_type, etc, which should be introduced when the netif is
|
||||
* created.
|
||||
*/
|
||||
return dev->cbc->ptp_phc_index_get_cb(priv, index);
|
||||
}
|
||||
|
||||
int
|
||||
ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len)
|
||||
{
|
||||
if (!dev->cbc->ptp_dev_ctrl_cb) {
|
||||
return SHR_E_UNAVAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The callback is IOCTL dispatcher for PTP driver/module.
|
||||
* The parameter <cmd> is the command defined by the user. The parameter
|
||||
* <data> and <len> are used for interactions between the user application
|
||||
* and the driver for PTP device start/stop, enable/disable, set/get, and
|
||||
* so on.
|
||||
*/
|
||||
return dev->cbc->ptp_dev_ctrl_cb(dev, cmd, data, len);
|
||||
}
|
||||
|
111
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h
Normal file
111
platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*! \file ngknet_ptp.h
|
||||
*
|
||||
* Definitions and APIs declaration for PTP.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
* The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
* be found in the LICENSES folder.$
|
||||
*/
|
||||
|
||||
#ifndef NGKNET_PTP_H
|
||||
#define NGKNET_PTP_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include "ngknet_main.h"
|
||||
|
||||
/*!
|
||||
* \brief PTP Rx config set.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [in] filter Rx filter.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter);
|
||||
|
||||
/*!
|
||||
* \brief PTP Tx config set.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [in] type Tx type.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_config_set(struct net_device *ndev, int type);
|
||||
|
||||
/*!
|
||||
* \brief PTP Rx HW timestamping get.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [in] skb Rx packet SKB.
|
||||
* \param [out] ts Timestamp value.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts);
|
||||
|
||||
/*!
|
||||
* \brief PTP Tx HW timestamping get.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [in] skb Tx packet SKB.
|
||||
* \param [out] ts Timestamp value.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts);
|
||||
|
||||
/*!
|
||||
* \brief PTP Tx meta set.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [in] skb Tx packet SKB.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb);
|
||||
|
||||
/*!
|
||||
* \brief PTP PHC index get.
|
||||
*
|
||||
* \param [in] ndev Network device structure point.
|
||||
* \param [out] index PHC index.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_phc_index_get(struct net_device *ndev, int *index);
|
||||
|
||||
/*!
|
||||
* \brief PTP device control.
|
||||
*
|
||||
* \param [in] dev NGKNET device structure point.
|
||||
* \param [in] cmd Command.
|
||||
* \param [in] data Data buffer.
|
||||
* \param [in] len Data length.
|
||||
*
|
||||
* \retval SHR_E_NONE No errors.
|
||||
*/
|
||||
extern int
|
||||
ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len);
|
||||
|
||||
#endif /* NGKNET_PTP_H */
|
||||
|
36
platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild
Normal file
36
platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild
Normal file
@ -0,0 +1,36 @@
|
||||
# -*- Kbuild -*-
|
||||
#
|
||||
# Linux KNET Callback module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
ifeq ($(BUILD_PSAMPLE),1)
|
||||
PSAMPLE_CFLAGS=-DPSAMPLE_SUPPORT
|
||||
PSAMPLE_CB_OBJS=psample-cb.o
|
||||
endif
|
||||
|
||||
obj-m := linux_ngknetcb.o
|
||||
|
||||
ccflags-y := $(LKM_CFLAGS) \
|
||||
-I$(SDK)/shr/include \
|
||||
-I$(SDK)/bcmdrd/include \
|
||||
-I$(SDK)/linux/include \
|
||||
-I$(SDK)/linux/knet/include \
|
||||
-I$(SDK)/linux/knet \
|
||||
$(PSAMPLE_CFLAGS)
|
||||
|
||||
linux_ngknetcb-y := ngknetcb_main.o \
|
||||
$(PSAMPLE_CB_OBJS)
|
33
platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile
Normal file
33
platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- Makefile -*-
|
||||
#
|
||||
# Linux KNET Callback module.
|
||||
#
|
||||
# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved.
|
||||
# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# A copy of the GNU General Public License version 2 (GPLv2) can
|
||||
# be found in the LICENSES folder.$
|
||||
#
|
||||
|
||||
include Kbuild
|
||||
|
||||
ifeq ($(KERNELRELEASE),)
|
||||
|
||||
MOD_NAME = linux_ngknetcb
|
||||
|
||||
include $(SDK)/make/lkm.mk
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: distclean
|
||||
|
||||
distclean:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user