Changeset 4031

Show
Ignore:
Timestamp:
05/31/06 16:31:01 (2 years ago)
Author:
anonymous
Message:

Fix the subclient handling.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • lm-sensors/trunk/kernel/chips/w83792d.c

    r3225 r4031  
    253253        unsigned long last_updated;     /* In jiffies */ 
    254254 
    255         struct i2c_client *lm75;      /* for secondary I2C addresses */ 
     255        struct i2c_client *lm75[2];   /* for secondary I2C addresses */ 
    256256        /* pointer to array of 2 subclients */ 
    257257 
     
    505505} 
    506506 
     507static int  
     508w83792d_create_subclient(struct i2c_adapter *adapter, 
     509                                struct i2c_client *new_client, int addr, 
     510                                struct i2c_client **sub_cli)  
     511{ 
     512        int err; 
     513        struct i2c_client *sub_client; 
     514         
     515        (*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); 
     516        if (!(sub_client)) { 
     517                return -ENOMEM; 
     518        } 
     519        memset(sub_client, 0x00, sizeof(struct i2c_client)); 
     520        sub_client->addr = 0x48 + addr; 
     521        sub_client->data = NULL; 
     522        sub_client->adapter = adapter; 
     523        sub_client->driver = &w83792d_driver; 
     524        sub_client->flags = 0; 
     525        strcpy(sub_client->name, "w83792d subclient"); 
     526        if ((err = i2c_attach_client(sub_client))) { 
     527                printk(KERN_ERR "w83792: subclient registration " 
     528                        "at address 0x%x failed\n", sub_client->addr); 
     529                kfree(sub_client); 
     530                return err; 
     531        } 
     532        return 0; 
     533} 
     534 
     535static int 
     536w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, 
     537                struct i2c_client *new_client) 
     538{ 
     539        int i, id, err; 
     540        u8 val; 
     541        struct w83792d_data *data = new_client->data; 
     542 
     543        data->lm75[0] = NULL; 
     544        data->lm75[1] = NULL; 
     545 
     546        id = i2c_adapter_id(adapter); 
     547        if (force_subclients[0] == id && force_subclients[1] == address) { 
     548                for (i = 2; i <= 3; i++) { 
     549                        if (force_subclients[i] < 0x48 || 
     550                            force_subclients[i] > 0x4f) { 
     551                                printk(KERN_ERR "w83792d: invalid subclient " 
     552                                        "address %d; must be 0x48-0x4f\n", 
     553                                        force_subclients[i]); 
     554                                err = -ENODEV; 
     555                                goto ERROR_SC_0; 
     556                        } 
     557                } 
     558                w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR, 
     559                                        (force_subclients[2] & 0x07) | 
     560                                        ((force_subclients[3] & 0x07) << 4)); 
     561        } 
     562 
     563        val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); 
     564        if (!(val & 0x08)) { 
     565                err = w83792d_create_subclient(adapter, new_client, val & 0x7, 
     566                                                &data->lm75[0]); 
     567                if (err < 0) 
     568                        goto ERROR_SC_0; 
     569        } 
     570        if (!(val & 0x80)) { 
     571                if ((data->lm75[0] != NULL) && 
     572                        ((val & 0x7) == ((val >> 4) & 0x7))) { 
     573                        printk(KERN_ERR "w83792d: duplicate addresses 0x%x, " 
     574                                "use force_subclient\n", data->lm75[0]->addr); 
     575                        err = -ENODEV; 
     576                        goto ERROR_SC_1; 
     577                } 
     578                err = w83792d_create_subclient(adapter, new_client, 
     579                                                (val >> 4) & 0x7, &data->lm75[1]); 
     580                if (err < 0) 
     581                        goto ERROR_SC_1; 
     582        } 
     583 
     584        return 0; 
     585 
     586/* Undo inits in case of errors */ 
     587 
     588ERROR_SC_1: 
     589        if (data->lm75[0] != NULL) { 
     590                i2c_detach_client(data->lm75[0]); 
     591                kfree(data->lm75[0]); 
     592        } 
     593ERROR_SC_0: 
     594        return err; 
     595} 
     596 
     597 
    507598static int w83792d_detect(struct i2c_adapter *adapter, int address, 
    508599                          unsigned short flags, int kind) 
    509600{ 
    510         int i, val1 = 0, val2 = 0, id
     601        int i, val1 = 0, val2 = 0
    511602        struct i2c_client *new_client; 
    512603        struct w83792d_data *data; 
     
    619710                goto ERROR1; 
    620711        } 
    621  
    622         /* attach secondary i2c lm75-like clients */ 
    623         if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client), 
    624                                    GFP_KERNEL))) { 
    625                 err = -ENOMEM; 
    626                 goto ERROR2; 
    627         } 
    628         id = i2c_adapter_id(adapter); 
    629         if(force_subclients[0] == id && force_subclients[1] == address) { 
    630                 if(force_subclients[2] < 0x48 || force_subclients[2] > 0x4b) { 
    631                         printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x48-0x4b\n", 
    632                                force_subclients[2]); 
    633                         goto ERROR5; 
    634                 } 
    635                 if(force_subclients[3] < 0x4c || force_subclients[3] > 0x4f) { 
    636                         printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x4c-0x4f\n", 
    637                                force_subclients[3]); 
    638                         goto ERROR5; 
    639                 } 
    640                 w83792d_write_value(new_client, 
    641                                     W83792D_REG_I2C_SUBADDR, 
    642                                     0x40 | (force_subclients[2] & 0x03) | 
    643                                     ((force_subclients[3] & 0x03) <<4)); 
    644                 data->lm75[0].addr = force_subclients[2]; 
    645                 data->lm75[1].addr = force_subclients[3]; 
    646         } else { 
    647                 val1 = w83792d_read_value(new_client, 
    648                                           W83792D_REG_I2C_SUBADDR); 
    649                 data->lm75[0].addr = 0x48 + (val1 & 0x07); 
    650                 data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07); 
    651                 if (data->lm75[0].addr == data->lm75[1].addr) 
    652                         printk(KERN_WARNING "w83792d: Subclients have the same " 
    653                                "address (0x%02x)! Use force_subclients.\n", 
    654                                data->lm75[0].addr); 
    655         } 
    656         client_name = "W83792D subclient"; 
    657  
    658  
    659         for (i = 0; i <= 1; i++) { 
    660                 data->lm75[i].data = NULL;      /* store all data in w83792d */ 
    661                 data->lm75[i].adapter = adapter; 
    662                 data->lm75[i].driver = &w83792d_driver; 
    663                 data->lm75[i].flags = 0; 
    664                 strcpy(data->lm75[i].name, client_name); 
    665                 if ((err = i2c_attach_client(&(data->lm75[i])))) { 
    666                         printk(KERN_ERR "w83792d.o: Subclient %d registration at address 0x%x failed.\n", 
    667                                i, data->lm75[i].addr); 
    668                         if (i == 1) 
    669                                 goto ERROR6; 
    670                         goto ERROR5; 
    671                 } 
    672         } 
     712         
     713        if ((err = w83792d_detect_subclients(adapter, address, 
     714                        kind, new_client))) 
     715                goto ERROR2; 
    673716 
    674717        /* Read GPIO enable register to check if pins for fan 4,5 are used as 
     
    690733                                    w83792d_dir_table_template, THIS_MODULE)) < 0) { 
    691734                err = i; 
    692                 goto ERROR7
     735                goto ERROR3
    693736        } 
    694737        data->sysctl_id = i; 
     
    699742        return 0; 
    700743 
    701       ERROR7: 
    702         i2c_detach_client(& 
    703                           (((struct 
    704                              w83792d_data *) (new_client->data))-> 
    705                            lm75[1])); 
    706       ERROR6: 
    707         i2c_detach_client(& 
    708                           (((struct 
    709                              w83792d_data *) (new_client->data))-> 
    710                            lm75[0])); 
    711       ERROR5: 
    712         kfree(((struct w83792d_data *) (new_client->data))->lm75); 
    713       ERROR2: 
     744ERROR3: 
     745        if (data->lm75[0] != NULL) { 
     746                i2c_detach_client(data->lm75[0]); 
     747                kfree(data->lm75[0]); 
     748        } 
     749        if (data->lm75[1] != NULL) { 
     750                i2c_detach_client(data->lm75[1]); 
     751                kfree(data->lm75[1]); 
     752        } 
     753ERROR2: 
    714754        i2c_detach_client(new_client); 
    715       ERROR1: 
     755ERROR1: 
    716756        kfree(data); 
    717       ERROR0: 
     757ERROR0: 
    718758 
    719759        LEAVE() 
     
    727767        ENTER() 
    728768 
    729         i2c_deregister_entry(data->sysctl_id); 
     769        /* remove sysctl table (primary client only) */ 
     770        if ((data)) 
     771                i2c_deregister_entry(data->sysctl_id); 
    730772 
    731773        if ((err = i2c_detach_client(client))) { 
     
    734776                return err; 
    735777        } 
    736         i2c_detach_client(&(data->lm75[0])); 
    737         i2c_detach_client(&(data->lm75[1])); 
    738         kfree(data->lm75); 
    739         kfree(data); 
    740  
    741         LEAVE() 
     778 
     779        if (data) { 
     780                /* primary client */ 
     781                kfree(data); 
     782        } else { 
     783                /* subclients */ 
     784                kfree(client); 
     785        } 
     786 
    742787        return 0; 
    743788}