Skip to content

Commit e718da0

Browse files
committed
addons/intel: Introduce gnss.disabled flag to disable e825 incoming GNSS for BC profiles
Signed-off-by: Jim Ramsay <[email protected]>
1 parent 6873360 commit e718da0

File tree

2 files changed

+198
-1
lines changed

2 files changed

+198
-1
lines changed

addons/intel/e825.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package intel
33
import (
44
"encoding/binary"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"os"
89
"os/exec"
@@ -27,6 +28,12 @@ type E825Opts struct {
2728
DpllSettings map[string]uint64 `json:"settings"`
2829
PhaseOffsetPins map[string]map[string]string `json:"phaseOffsetPins"`
2930
PhaseInputs []PhaseInputs `json:"interconnections"`
31+
Gnss GnssOptions `json:"gnss"`
32+
}
33+
34+
// GnssOptions defines GNSS-specific options for the e825
35+
type GnssOptions struct {
36+
Disabled bool `json:"disabled"`
3037
}
3138

3239
// GetPhaseInputs implements PhaseInputsProvider
@@ -35,6 +42,7 @@ func (o E825Opts) GetPhaseInputs() []PhaseInputs { return o.PhaseInputs }
3542
// E825PluginData is the data structure for e825 plugin
3643
type E825PluginData struct {
3744
hwplugins *[]string
45+
dpllPins []*dpll_netlink.PinInfo
3846
}
3947

4048
// EnableE825PTPConfig is the script to enable default e825 PTP configuration
@@ -46,7 +54,8 @@ echo "No E825 specific configuration is needed"
4654
`
4755

4856
// OnPTPConfigChangeE825 performs actions on PTP config change for e825 plugin
49-
func OnPTPConfigChangeE825(_ *interface{}, nodeProfile *ptpv1.PtpProfile) error {
57+
func OnPTPConfigChangeE825(data *interface{}, nodeProfile *ptpv1.PtpProfile) error {
58+
pluginData := (*data).(*E825PluginData)
5059
glog.Info("calling onPTPConfigChange for e825 plugin")
5160
var e825Opts E825Opts
5261
var err error
@@ -148,11 +157,67 @@ func OnPTPConfigChangeE825(_ *interface{}, nodeProfile *ptpv1.PtpProfile) error
148157
} else {
149158
glog.Error("no clock chain set")
150159
}
160+
// Always enforce GNSS setting (default = enabled)
161+
pluginData.setupGnss(e825Opts.Gnss)
151162
}
152163
}
153164
return nil
154165
}
155166

167+
func (d *E825PluginData) populateDpllPins() error {
168+
if unitTest {
169+
return nil
170+
}
171+
conn, err := dpll_netlink.Dial(nil)
172+
if err != nil {
173+
return fmt.Errorf("failed to dial DPLL: %w", err)
174+
}
175+
defer conn.Close()
176+
d.dpllPins, err = conn.DumpPinGet()
177+
if err != nil {
178+
return fmt.Errorf("failed to dump DPLL pins: %w", err)
179+
}
180+
return nil
181+
}
182+
183+
// Setup mockable pin setting function
184+
var e825DoPinSet = BatchPinSet
185+
186+
func (d *E825PluginData) setupGnss(gnss GnssOptions) error {
187+
if len(d.dpllPins) == 0 {
188+
err := d.populateDpllPins()
189+
if err != nil {
190+
return fmt.Errorf("could not detect any DPLL pins: %w", err)
191+
}
192+
}
193+
priority := uint8(PriorityEnabled)
194+
action := "enable"
195+
if gnss.Disabled {
196+
priority = uint8(PriorityDisabled)
197+
action = "disable"
198+
}
199+
commands := []dpll_netlink.PinParentDeviceCtl{}
200+
affectedPins := []string{}
201+
for _, pin := range d.dpllPins {
202+
// Look for all GNSS pins whose priority can be changed
203+
if pin.Type == dpll_netlink.PinTypeGNSS &&
204+
(pin.Capabilities&dpll_netlink.PinCapPrio != 0) {
205+
command := SetPinControlData(*pin, PinParentControl{
206+
EecPriority: priority,
207+
PpsPriority: priority,
208+
})
209+
commands = append(commands, *command)
210+
affectedPins = append(affectedPins, pin.BoardLabel)
211+
}
212+
}
213+
if len(commands) == 0 {
214+
glog.Errorf("Could not locate any GNSS pins to %s", action)
215+
return errors.New("no GNSS pins found")
216+
}
217+
glog.Infof("Will %s %d GNSS pins: %v", action, len(commands), affectedPins)
218+
return e825DoPinSet(&commands)
219+
}
220+
156221
// AfterRunPTPCommandE825 performs actions after certain PTP commands for e825 plugin
157222
func AfterRunPTPCommandE825(data *interface{}, nodeProfile *ptpv1.PtpProfile, command string) error {
158223
pluginData := (*data).(*E825PluginData)

addons/intel/e825_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"slices"
55
"testing"
66

7+
dpll "github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/dpll-netlink"
78
ptpv1 "github.com/k8snetworkplumbingwg/ptp-operator/api/v1"
89
"github.com/stretchr/testify/assert"
910
)
@@ -88,3 +89,134 @@ func Test_PopulateHwConfdigE825(t *testing.T) {
8889
},
8990
output)
9091
}
92+
93+
type mockBatchPinSet struct {
94+
commands *[]dpll.PinParentDeviceCtl
95+
}
96+
97+
func (m *mockBatchPinSet) mock(commands *[]dpll.PinParentDeviceCtl) error {
98+
m.commands = commands
99+
return nil
100+
}
101+
102+
func Test_setupGnss(t *testing.T) {
103+
unitTest = true
104+
tcs := []struct {
105+
name string
106+
gnss GnssOptions
107+
dpll []*dpll.PinInfo
108+
expectError bool
109+
expectedCmdCount int
110+
}{
111+
{
112+
name: "No DPLL Pins",
113+
dpll: []*dpll.PinInfo{},
114+
expectError: true,
115+
},
116+
{
117+
name: "No matching GNSS Pins",
118+
dpll: []*dpll.PinInfo{
119+
{
120+
ID: 1,
121+
BoardLabel: "SkipMe",
122+
Type: dpll.PinTypeEXT,
123+
Capabilities: dpll.PinCapPrio,
124+
},
125+
{
126+
ID: 2,
127+
BoardLabel: "SkipMe-Too",
128+
Type: dpll.PinTypeGNSS,
129+
Capabilities: 0,
130+
},
131+
},
132+
expectError: true,
133+
},
134+
{
135+
name: "Single matching pin (enable)",
136+
gnss: GnssOptions{
137+
Disabled: false,
138+
},
139+
dpll: []*dpll.PinInfo{
140+
{
141+
ID: 1,
142+
BoardLabel: "SkipMe",
143+
Type: dpll.PinTypeEXT,
144+
Capabilities: dpll.PinCapPrio,
145+
},
146+
{
147+
BoardLabel: "GNSS_1PPS_IN",
148+
ID: 2,
149+
Type: dpll.PinTypeGNSS,
150+
Capabilities: dpll.PinCapPrio | dpll.PinCapState,
151+
ParentDevice: []dpll.PinParentDevice{
152+
{
153+
ParentID: uint32(1),
154+
Direction: dpll.PinDirectionInput,
155+
},
156+
{
157+
ParentID: uint32(2),
158+
Direction: dpll.PinDirectionInput,
159+
},
160+
},
161+
},
162+
},
163+
expectedCmdCount: 1,
164+
},
165+
{
166+
name: "Single matching pin (disable)",
167+
gnss: GnssOptions{
168+
Disabled: true,
169+
},
170+
dpll: []*dpll.PinInfo{
171+
{
172+
ID: 1,
173+
Type: dpll.PinTypeEXT,
174+
Capabilities: dpll.PinCapPrio,
175+
},
176+
{
177+
ID: 2,
178+
Type: dpll.PinTypeGNSS,
179+
Capabilities: dpll.PinCapPrio | dpll.PinCapState,
180+
ParentDevice: []dpll.PinParentDevice{
181+
{
182+
ParentID: uint32(1),
183+
Direction: dpll.PinDirectionInput,
184+
},
185+
{
186+
ParentID: uint32(2),
187+
Direction: dpll.PinDirectionInput,
188+
},
189+
},
190+
},
191+
},
192+
expectedCmdCount: 1,
193+
},
194+
}
195+
for _, tc := range tcs {
196+
t.Run(tc.name, func(tt *testing.T) {
197+
mockPinSet := mockBatchPinSet{}
198+
e825DoPinSet = mockPinSet.mock
199+
data := E825PluginData{
200+
dpllPins: tc.dpll,
201+
}
202+
err := data.setupGnss(tc.gnss)
203+
if tc.expectError {
204+
assert.Error(tt, err)
205+
} else {
206+
assert.NoError(tt, err)
207+
assert.Equal(tt, tc.expectedCmdCount, len(*mockPinSet.commands))
208+
expectedPriority := uint32(PriorityEnabled)
209+
if tc.gnss.Disabled {
210+
expectedPriority = uint32(PriorityDisabled)
211+
}
212+
for _, cmd := range *mockPinSet.commands {
213+
for _, ctrl := range cmd.PinParentCtl {
214+
tt.Logf("Do the thing: %v", ctrl)
215+
tt.Logf("Do the thing: %v", ctrl)
216+
assert.Equal(tt, expectedPriority, *ctrl.Prio)
217+
}
218+
}
219+
}
220+
})
221+
}
222+
}

0 commit comments

Comments
 (0)