Print this page
XXXX cpudrv attach error handling is leaky
XXXX cpudrv attach is racy


 260                     NULL) {
 261                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 262                             "can't get state", instance);
 263                         ddi_soft_state_free(cpudrv_state, instance);
 264                         cpudrv_enabled = B_FALSE;
 265                         return (DDI_FAILURE);
 266                 }
 267                 cpudsp->dip = dip;
 268 
 269                 /*
 270                  * Find CPU number for this dev_info node.
 271                  */
 272                 if (!cpudrv_get_cpu_id(dip, &(cpudsp->cpu_id))) {
 273                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 274                             "can't convert dip to cpu_id", instance);
 275                         ddi_soft_state_free(cpudrv_state, instance);
 276                         cpudrv_enabled = B_FALSE;
 277                         return (DDI_FAILURE);
 278                 }
 279 









 280                 mutex_init(&cpudsp->lock, NULL, MUTEX_DRIVER, NULL);
 281                 if (cpudrv_is_enabled(cpudsp)) {
 282                         if (cpudrv_init(cpudsp) != DDI_SUCCESS) {
 283                                 cpudrv_enabled = B_FALSE;
 284                                 cpudrv_free(cpudsp);
 285                                 ddi_soft_state_free(cpudrv_state, instance);
 286                                 return (DDI_FAILURE);
 287                         }
 288                         if (cpudrv_comp_create(cpudsp) != DDI_SUCCESS) {
 289                                 cpudrv_enabled = B_FALSE;
 290                                 cpudrv_free(cpudsp);
 291                                 ddi_soft_state_free(cpudrv_state, instance);
 292                                 return (DDI_FAILURE);
 293                         }
 294                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
 295                             dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) {
 296                                 cpudrv_enabled = B_FALSE;
 297                                 cpudrv_free(cpudsp);
 298                                 ddi_soft_state_free(cpudrv_state, instance);
 299                                 return (DDI_FAILURE);
 300                         }
 301 
 302                         /*
 303                          * Taskq is used to dispatch routine to monitor CPU
 304                          * activities.
 305                          */
 306                         cpudsp->cpudrv_pm.tq = ddi_taskq_create(dip,
 307                             "cpudrv_monitor", CPUDRV_TASKQ_THREADS,
 308                             TASKQ_DEFAULTPRI, 0);






 309 
 310                         mutex_init(&cpudsp->cpudrv_pm.timeout_lock, NULL,
 311                             MUTEX_DRIVER, NULL);
 312                         cv_init(&cpudsp->cpudrv_pm.timeout_cv, NULL,
 313                             CV_DEFAULT, NULL);
 314 
 315                         /*
 316                          * Driver needs to assume that CPU is running at
 317                          * unknown speed at DDI_ATTACH and switch it to the
 318                          * needed speed. We assume that initial needed speed
 319                          * is full speed for us.
 320                          */
 321                         /*
 322                          * We need to take the lock because cpudrv_monitor()
 323                          * will start running in parallel with attach().
 324                          */
 325                         mutex_enter(&cpudsp->lock);
 326                         cpudsp->cpudrv_pm.cur_spd = NULL;
 327                         cpudsp->cpudrv_pm.pm_started = B_FALSE;
 328                         /*
 329                          * We don't call pm_raise_power() directly from attach
 330                          * because driver attach for a slave CPU node can
 331                          * happen before the CPU is even initialized. We just
 332                          * start the monitoring system which understands
 333                          * unknown speed and moves CPU to top speed when it
 334                          * has been initialized.
 335                          */
 336                         CPUDRV_MONITOR_INIT(cpudsp);
 337                         mutex_exit(&cpudsp->lock);
 338 
 339                 }
 340 
 341                 if (!cpudrv_mach_init(cpudsp)) {
 342                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 343                             "cpudrv_mach_init failed", instance);
 344                         cpudrv_enabled = B_FALSE;

 345                         cpudrv_free(cpudsp);
 346                         ddi_soft_state_free(cpudrv_state, instance);
 347                         return (DDI_FAILURE);
 348                 }
 349 
 350                 CPUDRV_INSTALL_MAX_CHANGE_HANDLER(cpudsp);
 351 
 352                 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 353                     DDI_NO_AUTODETACH, 1);
 354                 ddi_report_dev(dip);
 355                 return (DDI_SUCCESS);
 356 
 357         case DDI_RESUME:
 358                 DPRINTF(D_ATTACH, ("cpudrv_attach: instance %d: "
 359                     "DDI_RESUME called\n", instance));
 360 
 361                 cpudsp = ddi_get_soft_state(cpudrv_state, instance);
 362                 ASSERT(cpudsp != NULL);
 363 
 364                 /*




 260                     NULL) {
 261                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 262                             "can't get state", instance);
 263                         ddi_soft_state_free(cpudrv_state, instance);
 264                         cpudrv_enabled = B_FALSE;
 265                         return (DDI_FAILURE);
 266                 }
 267                 cpudsp->dip = dip;
 268 
 269                 /*
 270                  * Find CPU number for this dev_info node.
 271                  */
 272                 if (!cpudrv_get_cpu_id(dip, &(cpudsp->cpu_id))) {
 273                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 274                             "can't convert dip to cpu_id", instance);
 275                         ddi_soft_state_free(cpudrv_state, instance);
 276                         cpudrv_enabled = B_FALSE;
 277                         return (DDI_FAILURE);
 278                 }
 279 
 280                 if (!cpudrv_is_enabled(cpudsp)) {
 281                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 282                             "not supported or it got disabled on us",
 283                             instance);
 284                         cpudrv_enabled = B_FALSE;
 285                         ddi_soft_state_free(cpudrv_state, instance);
 286                         return (DDI_FAILURE);
 287                 }
 288 
 289                 mutex_init(&cpudsp->lock, NULL, MUTEX_DRIVER, NULL);

 290                 if (cpudrv_init(cpudsp) != DDI_SUCCESS) {
 291                         cpudrv_enabled = B_FALSE;
 292                         cpudrv_free(cpudsp);
 293                         ddi_soft_state_free(cpudrv_state, instance);
 294                         return (DDI_FAILURE);
 295                 }
 296                 if (cpudrv_comp_create(cpudsp) != DDI_SUCCESS) {
 297                         cpudrv_enabled = B_FALSE;
 298                         cpudrv_free(cpudsp);
 299                         ddi_soft_state_free(cpudrv_state, instance);
 300                         return (DDI_FAILURE);
 301                 }
 302                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
 303                     dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) {
 304                         cpudrv_enabled = B_FALSE;
 305                         cpudrv_free(cpudsp);
 306                         ddi_soft_state_free(cpudrv_state, instance);
 307                         return (DDI_FAILURE);
 308                 }
 309 
 310                 /*
 311                  * Taskq is used to dispatch routine to monitor CPU
 312                  * activities.
 313                  */
 314                 cpudsp->cpudrv_pm.tq = ddi_taskq_create(dip,
 315                     "cpudrv_monitor", CPUDRV_TASKQ_THREADS,
 316                     TASKQ_DEFAULTPRI, 0);
 317                 if (cpudsp->cpudrv_pm.tq == NULL) {
 318                         cpudrv_enabled = B_FALSE;
 319                         cpudrv_free(cpudsp);
 320                         ddi_soft_state_free(cpudrv_state, instance);
 321                         return (DDI_FAILURE);
 322                 }
 323 
 324                 mutex_init(&cpudsp->cpudrv_pm.timeout_lock, NULL,
 325                     MUTEX_DRIVER, NULL);
 326                 cv_init(&cpudsp->cpudrv_pm.timeout_cv, NULL,
 327                     CV_DEFAULT, NULL);
 328 
 329                 /*
 330                  * Driver needs to assume that CPU is running at
 331                  * unknown speed at DDI_ATTACH and switch it to the
 332                  * needed speed. We assume that initial needed speed
 333                  * is full speed for us.
 334                  */
 335                 /*
 336                  * We need to take the lock because cpudrv_monitor()
 337                  * will start running in parallel with attach().
 338                  */
 339                 mutex_enter(&cpudsp->lock);
 340                 cpudsp->cpudrv_pm.cur_spd = NULL;
 341                 cpudsp->cpudrv_pm.pm_started = B_FALSE;
 342                 /*
 343                  * We don't call pm_raise_power() directly from attach
 344                  * because driver attach for a slave CPU node can
 345                  * happen before the CPU is even initialized. We just
 346                  * start the monitoring system which understands
 347                  * unknown speed and moves CPU to top speed when it
 348                  * has been initialized.
 349                  */
 350                 CPUDRV_MONITOR_INIT(cpudsp);
 351                 mutex_exit(&cpudsp->lock);
 352 


 353                 if (!cpudrv_mach_init(cpudsp)) {
 354                         cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 355                             "cpudrv_mach_init failed", instance);
 356                         cpudrv_enabled = B_FALSE;
 357                         ddi_taskq_destroy(cpudsp->cpudrv_pm.tq);
 358                         cpudrv_free(cpudsp);
 359                         ddi_soft_state_free(cpudrv_state, instance);
 360                         return (DDI_FAILURE);
 361                 }
 362 
 363                 CPUDRV_INSTALL_MAX_CHANGE_HANDLER(cpudsp);
 364 
 365                 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 366                     DDI_NO_AUTODETACH, 1);
 367                 ddi_report_dev(dip);
 368                 return (DDI_SUCCESS);
 369 
 370         case DDI_RESUME:
 371                 DPRINTF(D_ATTACH, ("cpudrv_attach: instance %d: "
 372                     "DDI_RESUME called\n", instance));
 373 
 374                 cpudsp = ddi_get_soft_state(cpudrv_state, instance);
 375                 ASSERT(cpudsp != NULL);
 376 
 377                 /*