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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/cpudrv.c
          +++ new/usr/src/uts/common/io/cpudrv.c
↓ open down ↓ 269 lines elided ↑ open up ↑
 270  270                   * Find CPU number for this dev_info node.
 271  271                   */
 272  272                  if (!cpudrv_get_cpu_id(dip, &(cpudsp->cpu_id))) {
 273  273                          cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 274  274                              "can't convert dip to cpu_id", instance);
 275  275                          ddi_soft_state_free(cpudrv_state, instance);
 276  276                          cpudrv_enabled = B_FALSE;
 277  277                          return (DDI_FAILURE);
 278  278                  }
 279  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      -                        }
      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 +                }
 301  288  
 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);
      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  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);
      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 +                }
 314  323  
 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);
      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);
 338  328  
 339      -                }
      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);
 340  352  
 341  353                  if (!cpudrv_mach_init(cpudsp)) {
 342  354                          cmn_err(CE_WARN, "cpudrv_attach: instance %d: "
 343  355                              "cpudrv_mach_init failed", instance);
 344  356                          cpudrv_enabled = B_FALSE;
      357 +                        ddi_taskq_destroy(cpudsp->cpudrv_pm.tq);
 345  358                          cpudrv_free(cpudsp);
 346  359                          ddi_soft_state_free(cpudrv_state, instance);
 347  360                          return (DDI_FAILURE);
 348  361                  }
 349  362  
 350  363                  CPUDRV_INSTALL_MAX_CHANGE_HANDLER(cpudsp);
 351  364  
 352  365                  (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 353  366                      DDI_NO_AUTODETACH, 1);
 354  367                  ddi_report_dev(dip);
↓ open down ↓ 845 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX