aboutsummaryrefslogtreecommitdiff
path: root/scripts/coccinelle/reset-type.cocci
blob: 14abdd7bd0c57ee7be22bed8ef123f01ee32d29a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Convert device code using three-phase reset to add a ResetType
// argument to implementations of ResettableHoldPhase and
// ResettableEnterPhase methods.
//
// Copyright Linaro Ltd 2024
// SPDX-License-Identifier: GPL-2.0-or-later
//
// for dir in include hw target; do \
// spatch --macro-file scripts/cocci-macro-file.h \
//        --sp-file scripts/coccinelle/reset-type.cocci \
//        --keep-comments --smpl-spacing --in-place --include-headers \
//        --dir $dir; done
//
// This coccinelle script aims to produce a complete change that needs
// no human interaction, so as well as the generic "update device
// implementations of the hold and exit phase methods" it includes
// the special-case transformations needed for the core code and for
// one device model that does something a bit nonstandard. Those
// special cases are at the end of the file.

// Look for where we use a function as a ResettableHoldPhase method,
// either by directly assigning it to phases.hold or by calling
// resettable_class_set_parent_phases, and remember the function name.
@ holdfn_assigned @
identifier enterfn, holdfn, exitfn;
identifier rc;
expression e;
@@
ResettableClass *rc;
...
(
 rc->phases.hold = holdfn;
|
 resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
)

// Look for the definition of the function we found in holdfn_assigned,
// and add the new argument. If the function calls a hold function
// itself (probably chaining to the parent class reset) then add the
// new argument there too.
@ holdfn_defined @
identifier holdfn_assigned.holdfn;
typedef Object;
identifier obj;
expression parent;
@@
-holdfn(Object *obj)
+holdfn(Object *obj, ResetType type)
{
    <...
-    parent.hold(obj)
+    parent.hold(obj, type)
    ...>
}

// Similarly for ResettableExitPhase.
@ exitfn_assigned @
identifier enterfn, holdfn, exitfn;
identifier rc;
expression e;
@@
ResettableClass *rc;
...
(
 rc->phases.exit = exitfn;
|
 resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
)
@ exitfn_defined @
identifier exitfn_assigned.exitfn;
typedef Object;
identifier obj;
expression parent;
@@
-exitfn(Object *obj)
+exitfn(Object *obj, ResetType type)
{
    <...
-    parent.exit(obj)
+    parent.exit(obj, type)
    ...>
}

// SPECIAL CASES ONLY BELOW HERE
// We use a python scripted constraint on the position of the match
// to ensure that they only match in a particular function. See
// https://public-inbox.org/git/alpine.DEB.2.21.1808240652370.2344@hadrien/
// which recommends this as the way to do "match only in this function".

// Special case: isl_pmbus_vr.c has some reset methods calling others directly
@ isl_pmbus_vr @
identifier obj;
@@
- isl_pmbus_vr_exit_reset(obj);
+ isl_pmbus_vr_exit_reset(obj, type);

// Special case: device_phases_reset() needs to pass RESET_TYPE_COLD
@ device_phases_reset_hold @
expression obj;
identifier rc;
identifier phase;
position p : script:python() { p[0].current_element == "device_phases_reset" };
@@
- rc->phases.phase(obj)@p
+ rc->phases.phase(obj, RESET_TYPE_COLD)

// Special case: in resettable_phase_hold() and resettable_phase_exit()
// we need to pass through the ResetType argument to the method being called
@ resettable_phase_hold @
expression obj;
identifier rc;
position p : script:python() { p[0].current_element == "resettable_phase_hold" };
@@
- rc->phases.hold(obj)@p
+ rc->phases.hold(obj, type)
@ resettable_phase_exit @
expression obj;
identifier rc;
position p : script:python() { p[0].current_element == "resettable_phase_exit" };
@@
- rc->phases.exit(obj)@p
+ rc->phases.exit(obj, type)
// Special case: the typedefs for the methods need to declare the new argument
@ phase_typedef_hold @
identifier obj;
@@
- typedef void (*ResettableHoldPhase)(Object *obj);
+ typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
@ phase_typedef_exit @
identifier obj;
@@
- typedef void (*ResettableExitPhase)(Object *obj);
+ typedef void (*ResettableExitPhase)(Object *obj, ResetType type);