Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: cs5535audio: Allocate resources with device-managed APIs

This patch converts the resource management in PCI cs5535audio driver
with devres as a clean up. Each manual resource management is
converted with the corresponding devres helper, and the card object
release is managed now via card->private_free instead of a lowlevel
snd_device. A slight uncertain change is the call of
olpc_quirks_cleanup() at removal: formerly this was called
unconditionally at remove, but this should be a conditionally call,
hence the machine_is_olpc() check is added here as well.

This should give no user-visible functional changes.

Link: https://lore.kernel.org/r/20210715075941.23332-32-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+25 -80
+22 -76
sound/pci/cs5535audio/cs5535audio.c
··· 237 237 return IRQ_HANDLED; 238 238 } 239 239 240 - static int snd_cs5535audio_free(struct cs5535audio *cs5535au) 240 + static void snd_cs5535audio_free(struct snd_card *card) 241 241 { 242 - pci_set_power_state(cs5535au->pci, PCI_D3hot); 243 - 244 - if (cs5535au->irq >= 0) 245 - free_irq(cs5535au->irq, cs5535au); 246 - 247 - pci_release_regions(cs5535au->pci); 248 - pci_disable_device(cs5535au->pci); 249 - kfree(cs5535au); 250 - return 0; 251 - } 252 - 253 - static int snd_cs5535audio_dev_free(struct snd_device *device) 254 - { 255 - struct cs5535audio *cs5535au = device->device_data; 256 - return snd_cs5535audio_free(cs5535au); 242 + olpc_quirks_cleanup(); 257 243 } 258 244 259 245 static int snd_cs5535audio_create(struct snd_card *card, 260 - struct pci_dev *pci, 261 - struct cs5535audio **rcs5535au) 246 + struct pci_dev *pci) 262 247 { 263 - struct cs5535audio *cs5535au; 264 - 248 + struct cs5535audio *cs5535au = card->private_data; 265 249 int err; 266 - static const struct snd_device_ops ops = { 267 - .dev_free = snd_cs5535audio_dev_free, 268 - }; 269 250 270 - *rcs5535au = NULL; 271 - err = pci_enable_device(pci); 251 + err = pcim_enable_device(pci); 272 252 if (err < 0) 273 253 return err; 274 254 275 255 if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { 276 256 dev_warn(card->dev, "unable to get 32bit dma\n"); 277 - err = -ENXIO; 278 - goto pcifail; 279 - } 280 - 281 - cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL); 282 - if (cs5535au == NULL) { 283 - err = -ENOMEM; 284 - goto pcifail; 257 + return -ENXIO; 285 258 } 286 259 287 260 spin_lock_init(&cs5535au->reg_lock); ··· 263 290 cs5535au->irq = -1; 264 291 265 292 err = pci_request_regions(pci, "CS5535 Audio"); 266 - if (err < 0) { 267 - kfree(cs5535au); 268 - goto pcifail; 269 - } 293 + if (err < 0) 294 + return err; 270 295 271 296 cs5535au->port = pci_resource_start(pci, 0); 272 297 273 - if (request_irq(pci->irq, snd_cs5535audio_interrupt, 274 - IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { 298 + if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt, 299 + IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { 275 300 dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); 276 - err = -EBUSY; 277 - goto sndfail; 301 + return -EBUSY; 278 302 } 279 303 280 304 cs5535au->irq = pci->irq; 281 305 card->sync_irq = cs5535au->irq; 282 306 pci_set_master(pci); 283 307 284 - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops); 285 - if (err < 0) 286 - goto sndfail; 287 - 288 - *rcs5535au = cs5535au; 289 308 return 0; 290 - 291 - sndfail: /* leave the device alive, just kill the snd */ 292 - snd_cs5535audio_free(cs5535au); 293 - return err; 294 - 295 - pcifail: 296 - pci_disable_device(pci); 297 - return err; 298 309 } 299 310 300 311 static int snd_cs5535audio_probe(struct pci_dev *pci, ··· 296 339 return -ENOENT; 297 340 } 298 341 299 - err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 300 - 0, &card); 342 + err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 343 + sizeof(*cs5535au), &card); 344 + if (err < 0) 345 + return err; 346 + cs5535au = card->private_data; 347 + card->private_free = snd_cs5535audio_free; 348 + 349 + err = snd_cs5535audio_create(card, pci); 301 350 if (err < 0) 302 351 return err; 303 352 304 - err = snd_cs5535audio_create(card, pci, &cs5535au); 305 - if (err < 0) 306 - goto probefail_out; 307 - 308 - card->private_data = cs5535au; 309 - 310 353 err = snd_cs5535audio_mixer(cs5535au); 311 354 if (err < 0) 312 - goto probefail_out; 355 + return err; 313 356 314 357 err = snd_cs5535audio_pcm(cs5535au); 315 358 if (err < 0) 316 - goto probefail_out; 359 + return err; 317 360 318 361 strcpy(card->driver, DRIVER_NAME); 319 362 ··· 324 367 325 368 err = snd_card_register(card); 326 369 if (err < 0) 327 - goto probefail_out; 370 + return err; 328 371 329 372 pci_set_drvdata(pci, card); 330 373 dev++; 331 374 return 0; 332 - 333 - probefail_out: 334 - snd_card_free(card); 335 - return err; 336 - } 337 - 338 - static void snd_cs5535audio_remove(struct pci_dev *pci) 339 - { 340 - olpc_quirks_cleanup(); 341 - snd_card_free(pci_get_drvdata(pci)); 342 375 } 343 376 344 377 static struct pci_driver cs5535audio_driver = { 345 378 .name = KBUILD_MODNAME, 346 379 .id_table = snd_cs5535audio_ids, 347 380 .probe = snd_cs5535audio_probe, 348 - .remove = snd_cs5535audio_remove, 349 381 #ifdef CONFIG_PM_SLEEP 350 382 .driver = { 351 383 .pm = &snd_cs5535audio_pm,
+3 -4
sound/pci/cs5535audio/cs5535audio_olpc.c
··· 171 171 for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { 172 172 err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], 173 173 ac97->private_data)); 174 - if (err < 0) { 175 - gpio_free(OLPC_GPIO_MIC_AC); 174 + if (err < 0) 176 175 return err; 177 - } 178 176 } 179 177 180 178 /* turn off the mic by default */ ··· 182 184 183 185 void olpc_quirks_cleanup(void) 184 186 { 185 - gpio_free(OLPC_GPIO_MIC_AC); 187 + if (machine_is_olpc()) 188 + gpio_free(OLPC_GPIO_MIC_AC); 186 189 }