OSDN Git Service

Merge tag 'char-misc-3.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 26 Oct 2012 17:24:19 +0000 (10:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 26 Oct 2012 17:24:19 +0000 (10:24 -0700)
Pull char/misc driver fixes from Greg Kroah-Hartman:
 "Here are some driver fixes for 3.7.  They include extcon driver fixes,
  a hyper-v bugfix, and two other minor driver fixes.

  All of these have been in the linux-next releases for a while.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'char-misc-3.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  sonypi: suspend/resume callbacks should be conditionally compiled on CONFIG_PM_SLEEP
  Drivers: hv: Cleanup error handling in vmbus_open()
  extcon : register for cable interest by cable name
  extcon: trivial: kfree missed from remove path
  extcon: driver model release call not needed
  extcon: MAX77693: Add platform data for MUIC device to initialize registers
  extcon: max77693: Use max77693_update_reg for rmw operations
  extcon: Fix kerneldoc for extcon_set_cable_state and extcon_set_cable_state_
  extcon: adc-jack: Add missing MODULE_LICENSE
  extcon: adc-jack: Fix checking return value of request_any_context_irq
  extcon: Fix return value in extcon_register_interest()
  extcon: unregister compat link on cleanup
  extcon: Unregister compat class at module unload to fix oops
  extcon: optimising the check_mutually_exclusive function
  extcon: standard cable names definition and declaration changed
  extcon-max8997: remove usage of ret in max8997_muic_handle_charger_type_detach
  extcon: Remove duplicate inclusion of extcon.h header file

drivers/char/sonypi.c
drivers/extcon/extcon-adc-jack.c
drivers/extcon/extcon-class.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/hv/channel.c
include/linux/extcon.h
include/linux/mfd/max77693.h

index 320debb..9b4f011 100644 (file)
@@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int old_camera_power;
 
 static int sonypi_suspend(struct device *dev)
index 725eb5a..e87196f 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
        err = request_any_context_irq(data->irq, adc_jack_irq_thread,
                        pdata->irq_flags, pdata->name, data);
 
-       if (err) {
+       if (err < 0) {
                dev_err(&pdev->dev, "error: irq %d\n", data->irq);
-               err = -EINVAL;
                goto err_irq;
        }
 
-       goto out;
+       return 0;
 
 err_irq:
        extcon_dev_unregister(&data->edev);
@@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {
 };
 
 module_platform_driver(adc_jack_driver);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("ADC Jack extcon driver");
+MODULE_LICENSE("GPL v2");
index 946a318..d398821 100644 (file)
@@ -41,7 +41,7 @@
  * every single port-type of the following cable names. Please choose cable
  * names that are actually used in your extcon device.
  */
-const char *extcon_cable_name[] = {
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
        [EXTCON_USB]            = "USB",
        [EXTCON_USB_HOST]       = "USB-Host",
        [EXTCON_TA]             = "TA",
@@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {
        [EXTCON_VIDEO_IN]       = "Video-in",
        [EXTCON_VIDEO_OUT]      = "Video-out",
        [EXTCON_MECHANICAL]     = "Mechanical",
-
-       NULL,
 };
 
 static struct class *extcon_class;
@@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
                return 0;
 
        for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int count = 0, j;
+               int weight;
                u32 correspondants = new_state & edev->mutually_exclusive[i];
-               u32 exp = 1;
-
-               for (j = 0; j < 32; j++) {
-                       if (exp & correspondants)
-                               count++;
-                       if (count > 1)
-                               return i + 1;
-                       exp <<= 1;
-               }
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
        }
 
        return 0;
@@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 
 /**
- * extcon_get_cable_state_() - Set the status of a specific cable.
+ * extcon_set_cable_state_() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @index:     cable index that can be retrieved by extcon_find_cable_index().
  * @cable_state:       the new cable status. The default semantics is
@@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 
 /**
- * extcon_get_cable_state() - Set the status of a specific cable.
+ * extcon_set_cable_state() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @cable_name:        cable name.
  * @cable_state:       the new cable status. The default semantics is
@@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
  *                           extcon device.
  * @obj:       an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
  * @cable_name:                the target cable name.
  * @nb:                the notifier block to get notified.
  *
@@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
                             const char *extcon_name, const char *cable_name,
                             struct notifier_block *nb)
 {
-       if (!obj || !extcon_name || !cable_name || !nb)
+       if (!obj || !cable_name || !nb)
                return -EINVAL;
 
-       obj->edev = extcon_get_extcon_dev(extcon_name);
-       if (!obj->edev)
-               return -ENODEV;
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
 
-       obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-       if (obj->cable_index < 0)
-               return -ENODEV;
+               obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+               if (obj->cable_index < 0)
+                       return -ENODEV;
+
+               obj->user_nb = nb;
 
-       obj->user_nb = nb;
+               obj->internal_nb.notifier_call = _call_per_cable;
 
-       obj->internal_nb.notifier_call = _call_per_cable;
+               return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = (struct extcon_dev *)dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
 
-       return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+               return -ENODEV;
+       }
 }
 
 /**
@@ -551,43 +569,9 @@ static int create_extcon_class(void)
        return 0;
 }
 
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (!skip && get_device(edev->dev)) {
-               int index;
-
-               if (edev->mutually_exclusive && edev->max_supported) {
-                       for (index = 0; edev->mutually_exclusive[index];
-                            index++)
-                               kfree(edev->d_attrs_muex[index].attr.name);
-                       kfree(edev->d_attrs_muex);
-                       kfree(edev->attrs_muex);
-               }
-
-               for (index = 0; index < edev->max_supported; index++)
-                       kfree(edev->cables[index].attr_g.name);
-
-               if (edev->max_supported) {
-                       kfree(edev->extcon_dev_type.groups);
-                       kfree(edev->cables);
-               }
-
-               device_unregister(edev->dev);
-               put_device(edev->dev);
-       }
-
-       kfree(edev->dev);
-}
-
 static void extcon_dev_release(struct device *dev)
 {
-       struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-       extcon_cleanup(edev, true);
+       kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
  */
 void extcon_dev_unregister(struct extcon_dev *edev)
 {
-       extcon_cleanup(edev, false);
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(edev->dev))) {
+               dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(edev->dev));
+               return;
+       }
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
+       device_unregister(edev->dev);
+       put_device(edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
@@ -825,6 +842,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
        class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
index 3cc152e..71d3ab7 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/extcon.h>
index e21387e..a17d0d9 100644 (file)
@@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {
 static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                enum max77693_muic_adc_debounce_time time)
 {
-       int ret = 0;
-       u8 ctrl3;
+       int ret;
 
        switch (time) {
        case ADC_DEBOUNCE_TIME_5MS:
        case ADC_DEBOUNCE_TIME_10MS:
        case ADC_DEBOUNCE_TIME_25MS:
        case ADC_DEBOUNCE_TIME_38_62MS:
-               ret = max77693_read_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, &ctrl3);
-               ctrl3 &= ~CONTROL3_ADCDBSET_MASK;
-               ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT);
-
-               ret = max77693_write_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, ctrl3);
-               if (ret) {
+               ret = max77693_update_reg(info->max77693->regmap_muic,
+                                         MAX77693_MUIC_REG_CTRL3,
+                                         time << CONTROL3_ADCDBSET_SHIFT,
+                                         CONTROL3_ADCDBSET_MASK);
+               if (ret)
                        dev_err(info->dev, "failed to set ADC debounce time\n");
-                       ret = -EINVAL;
-               }
                break;
        default:
                dev_err(info->dev, "invalid ADC debounce time\n");
@@ -657,6 +651,8 @@ out:
 static int __devinit max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
        int ret, i;
        u8 id;
@@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
                goto err_extcon;
        }
 
+       /* Initialize MUIC register by using platform data */
+       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
+               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+               max77693_write_reg(info->max77693->regmap_muic,
+                               muic_pdata->init_data[i].addr,
+                               muic_pdata->init_data[i].data);
+
+               switch (muic_pdata->init_data[i].addr) {
+               case MAX77693_MUIC_REG_INTMASK1:
+                       irq_src = MUIC_INT1;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK2:
+                       irq_src = MUIC_INT2;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK3:
+                       irq_src = MUIC_INT3;
+                       break;
+               }
+
+               if (irq_src < MAX77693_IRQ_GROUP_NR)
+                       info->max77693->irq_masks_cur[irq_src]
+                               = muic_pdata->init_data[i].data;
+       }
+
        /* Check revision number of MUIC device*/
        ret = max77693_read_reg(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_ID, &id);
@@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
                free_irq(muic_irqs[i].virq, info);
        cancel_work_sync(&info->irq_work);
        extcon_dev_unregister(info->edev);
+       kfree(info->edev);
        kfree(info);
 
        return 0;
index ef9090a..77b66b0 100644 (file)
@@ -271,8 +271,6 @@ out:
 static int max8997_muic_handle_charger_type_detach(
                                struct max8997_muic_info *info)
 {
-       int ret = 0;
-
        switch (info->pre_charger_type) {
        case MAX8997_CHARGER_TYPE_USB:
                extcon_set_cable_state(info->edev, "USB", false);
@@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(
                extcon_set_cable_state(info->edev, "Fast-charger", false);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
index 4065374..f4c3d28 100644 (file)
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        ret = hv_ringbuffer_init(
                &newchannel->inbound, in, recv_ringbuffer_size);
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
 
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        /* Create and init the channel open message */
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto errorout;
+               goto error0;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto errorout;
+               goto error0;
        }
 
        if (userdatalen)
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                               sizeof(struct vmbus_channel_open_channel));
 
        if (ret != 0)
-               goto cleanup;
+               goto error1;
 
        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
        if (t == 0) {
                err = -ETIMEDOUT;
-               goto errorout;
+               goto error1;
        }
 
 
        if (open_info->response.open_result.status)
                err = open_info->response.open_result.status;
 
-cleanup:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +227,12 @@ cleanup:
        kfree(open_info);
        return err;
 
-errorout:
-       hv_ringbuffer_cleanup(&newchannel->outbound);
-       hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
index 7443a56..2c26c14 100644 (file)
@@ -68,7 +68,7 @@ enum extcon_cable_name {
        EXTCON_VIDEO_OUT,
        EXTCON_MECHANICAL,
 };
-extern const char *extcon_cable_name[];
+extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
 
 struct extcon_cable;
 
index 1d28ae9..fe03b2d 100644 (file)
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
+struct max77693_reg_data {
+       u8 addr;
+       u8 data;
+};
+
+struct max77693_muic_platform_data {
+       struct max77693_reg_data *init_data;
+       int num_init_data;
+};
+
 struct max77693_platform_data {
        int wakeup;
+
+       /* muic data */
+       struct max77693_muic_platform_data *muic_data;
 };
 #endif /* __LINUX_MFD_MAX77693_H */