Changeset 753 for GPL/branches/uniaud32-exp/lib32/devres.c
- Timestamp:
- Oct 22, 2022, 9:53:37 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/branches/uniaud32-exp/lib32/devres.c
r744 r753 221 221 } 222 222 223 static int release_nodes(struct device *dev, struct list_head *first, 224 struct list_head *end, unsigned long flags) 225 { 226 // LIST_HEAD(todo); 227 struct list_head todo; 228 229 int cnt; 223 static void release_nodes(struct device *dev, struct list_head *todo) 224 { 230 225 struct devres *dr, *tmp; 231 232 cnt = remove_nodes(dev, first, end, &todo);233 234 spin_unlock_irqrestore(&dev->devres_lock, flags);235 226 236 227 /* Release. Note that both devres and devres_group are 237 228 * handled as devres in the following loop. This is safe. 238 229 */ 239 list_for_each_entry_safe_reverse(dr, tmp, &todo, node.entry, struct devres) {230 list_for_each_entry_safe_reverse(dr, tmp, todo, node.entry, struct devres) { 240 231 devres_log(dev, &dr->node, "REL"); 241 232 dr->node.release(dev, dr->data); 242 233 kfree(dr); 243 234 } 244 245 return cnt;246 235 } 247 236 … … 256 245 { 257 246 unsigned long flags; 247 struct list_head todo; 248 int cnt; 258 249 259 250 /* Looks like an uninitialized device structure */ 260 251 if (WARN_ON(dev->devres_head.next == NULL)) 261 252 return -ENODEV; 253 254 /* Nothing to release if list is empty */ 255 if (list_empty(&dev->devres_head)) 256 return 0; 257 262 258 spin_lock_irqsave(&dev->devres_lock, flags); 263 return release_nodes(dev, dev->devres_head.next, &dev->devres_head, 264 flags); 265 } 259 cnt = remove_nodes(dev, dev->devres_head.next, &dev->devres_head, &todo); 260 spin_unlock_irqrestore(&dev->devres_lock, flags); 261 262 release_nodes(dev, &todo); 263 return cnt; 264 } 265 266 /** 267 * devres_open_group - Open a new devres group 268 * @dev: Device to open devres group for 269 * @id: Separator ID 270 * @gfp: Allocation flags 271 * 272 * Open a new devres group for @dev with @id. For @id, using a 273 * pointer to an object which won't be used for another group is 274 * recommended. If @id is NULL, address-wise unique ID is created. 275 * 276 * RETURNS: 277 * ID of the new group, NULL on failure. 278 */ 279 void * devres_open_group(struct device *dev, void *id, gfp_t gfp) 280 { 281 struct devres_group *grp; 282 unsigned long flags; 283 284 grp = kmalloc(sizeof(*grp), gfp); 285 if (unlikely(!grp)) 286 return NULL; 287 288 grp->node[0].release = &group_open_release; 289 grp->node[1].release = &group_close_release; 290 INIT_LIST_HEAD(&grp->node[0].entry); 291 INIT_LIST_HEAD(&grp->node[1].entry); 292 set_node_dbginfo(&grp->node[0], "grp<", 0); 293 set_node_dbginfo(&grp->node[1], "grp>", 0); 294 grp->id = grp; 295 if (id) 296 grp->id = id; 297 298 spin_lock_irqsave(&dev->devres_lock, flags); 299 add_dr(dev, &grp->node[0]); 300 spin_unlock_irqrestore(&dev->devres_lock, flags); 301 return grp->id; 302 } 303 EXPORT_SYMBOL_GPL(devres_open_group); 304 305 /* Find devres group with ID @id. If @id is NULL, look for the latest. */ 306 static struct devres_group * find_group(struct device *dev, void *id) 307 { 308 struct devres_node *node; 309 310 list_for_each_entry_reverse(node, &dev->devres_head, entry, struct devres_node) { 311 struct devres_group *grp; 312 313 if (node->release != &group_open_release) 314 continue; 315 316 grp = container_of(node, struct devres_group, node[0]); 317 318 if (id) { 319 if (grp->id == id) 320 return grp; 321 } else if (list_empty(&grp->node[1].entry)) 322 return grp; 323 } 324 325 return NULL; 326 } 327 328 /** 329 * devres_release_group - Release resources in a devres group 330 * @dev: Device to release group for 331 * @id: ID of target group, can be NULL 332 * 333 * Release all resources in the group identified by @id. If @id is 334 * NULL, the latest open group is selected. The selected group and 335 * groups properly nested inside the selected group are removed. 336 * 337 * RETURNS: 338 * The number of released non-group resources. 339 */ 340 int devres_release_group(struct device *dev, void *id) 341 { 342 struct devres_group *grp; 343 unsigned long flags; 344 struct list_head todo; 345 int cnt = 0; 346 347 spin_lock_irqsave(&dev->devres_lock, flags); 348 349 grp = find_group(dev, id); 350 if (grp) { 351 struct list_head *first = &grp->node[0].entry; 352 struct list_head *end = &dev->devres_head; 353 354 if (!list_empty(&grp->node[1].entry)) 355 end = grp->node[1].entry.next; 356 357 cnt = remove_nodes(dev, first, end, &todo); 358 spin_unlock_irqrestore(&dev->devres_lock, flags); 359 360 release_nodes(dev, &todo); 361 } else { 362 WARN_ON(1); 363 spin_unlock_irqrestore(&dev->devres_lock, flags); 364 } 365 366 return cnt; 367 } 368 EXPORT_SYMBOL_GPL(devres_release_group); 266 369 267 370 static struct devres *find_dr(struct device *dev, dr_release_t release,
Note:
See TracChangeset
for help on using the changeset viewer.