@@ -141,6 +141,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
141
141
return len ;
142
142
}
143
143
144
+ /*
145
+ * acpi_companion_match() - Can we match via ACPI companion device
146
+ * @dev: Device in question
147
+ *
148
+ * Check if the given device has an ACPI companion and if that companion has
149
+ * a valid list of PNP IDs, and if the device is the first (primary) physical
150
+ * device associated with it.
151
+ *
152
+ * If multiple physical devices are attached to a single ACPI companion, we need
153
+ * to be careful. The usage scenario for this kind of relationship is that all
154
+ * of the physical devices in question use resources provided by the ACPI
155
+ * companion. A typical case is an MFD device where all the sub-devices share
156
+ * the parent's ACPI companion. In such cases we can only allow the primary
157
+ * (first) physical device to be matched with the help of the companion's PNP
158
+ * IDs.
159
+ *
160
+ * Additional physical devices sharing the ACPI companion can still use
161
+ * resources available from it but they will be matched normally using functions
162
+ * provided by their bus types (and analogously for their modalias).
163
+ */
164
+ static bool acpi_companion_match (const struct device * dev )
165
+ {
166
+ struct acpi_device * adev ;
167
+ bool ret ;
168
+
169
+ adev = ACPI_COMPANION (dev );
170
+ if (!adev )
171
+ return false;
172
+
173
+ if (list_empty (& adev -> pnp .ids ))
174
+ return false;
175
+
176
+ mutex_lock (& adev -> physical_node_lock );
177
+ if (list_empty (& adev -> physical_node_list )) {
178
+ ret = false;
179
+ } else {
180
+ const struct acpi_device_physical_node * node ;
181
+
182
+ node = list_first_entry (& adev -> physical_node_list ,
183
+ struct acpi_device_physical_node , node );
184
+ ret = node -> dev == dev ;
185
+ }
186
+ mutex_unlock (& adev -> physical_node_lock );
187
+
188
+ return ret ;
189
+ }
190
+
144
191
/*
145
192
* Creates uevent modalias field for ACPI enumerated devices.
146
193
* Because the other buses does not support ACPI HIDs & CIDs.
@@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
149
196
*/
150
197
int acpi_device_uevent_modalias (struct device * dev , struct kobj_uevent_env * env )
151
198
{
152
- struct acpi_device * acpi_dev ;
153
199
int len ;
154
200
155
- acpi_dev = ACPI_COMPANION (dev );
156
- if (!acpi_dev )
157
- return - ENODEV ;
158
-
159
- /* Fall back to bus specific way of modalias exporting */
160
- if (list_empty (& acpi_dev -> pnp .ids ))
201
+ if (!acpi_companion_match (dev ))
161
202
return - ENODEV ;
162
203
163
204
if (add_uevent_var (env , "MODALIAS=" ))
164
205
return - ENOMEM ;
165
- len = create_modalias (acpi_dev , & env -> buf [env -> buflen - 1 ],
206
+ len = create_modalias (ACPI_COMPANION ( dev ) , & env -> buf [env -> buflen - 1 ],
166
207
sizeof (env -> buf ) - env -> buflen );
167
208
if (len <= 0 )
168
209
return len ;
@@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
179
220
*/
180
221
int acpi_device_modalias (struct device * dev , char * buf , int size )
181
222
{
182
- struct acpi_device * acpi_dev ;
183
223
int len ;
184
224
185
- acpi_dev = ACPI_COMPANION (dev );
186
- if (!acpi_dev )
225
+ if (!acpi_companion_match (dev ))
187
226
return - ENODEV ;
188
227
189
- /* Fall back to bus specific way of modalias exporting */
190
- if (list_empty (& acpi_dev -> pnp .ids ))
191
- return - ENODEV ;
192
-
193
- len = create_modalias (acpi_dev , buf , size - 1 );
228
+ len = create_modalias (ACPI_COMPANION (dev ), buf , size - 1 );
194
229
if (len <= 0 )
195
230
return len ;
196
231
buf [len ++ ] = '\n' ;
@@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
853
888
if (!ids || !handle || acpi_bus_get_device (handle , & adev ))
854
889
return NULL ;
855
890
891
+ if (!acpi_companion_match (dev ))
892
+ return NULL ;
893
+
856
894
return __acpi_match_device (adev , ids );
857
895
}
858
896
EXPORT_SYMBOL_GPL (acpi_match_device );
0 commit comments