msi-laptop: Detect 3G device exists by standard ec command

Detect 3G device exists by standard ec command. Driver will not create the threeg sysfs
file and threeg rfkill interface if there have no internal 3G device in MSI notebook/netbook.

Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index af1b62f..c2b05da 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -79,6 +79,8 @@
 
 static int msi_laptop_resume(struct platform_device *device);
 
+#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS	0x2f
+
 static int force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -89,6 +91,7 @@
 
 static bool old_ec_model;
 static int wlan_s, bluetooth_s, threeg_s;
+static int threeg_exists;
 
 /* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G,
  * those netbook will load the SCM (windows app) to disable the original
@@ -224,6 +227,20 @@
 	return 0;
 }
 
+static int get_threeg_exists(void)
+{
+	u8 rdata;
+	int result;
+
+	result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata);
+	if (result < 0)
+		return -1;
+
+	threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK);
+
+	return 0;
+}
+
 /* Backlight device stuff */
 
 static int bl_get_brightness(struct backlight_device *b)
@@ -561,15 +578,17 @@
 	if (retval)
 		goto err_wlan;
 
-	rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN,
-				&rfkill_threeg_ops, NULL);
-	if (!rfk_threeg) {
-		retval = -ENOMEM;
-		goto err_threeg;
+	if (threeg_exists) {
+		rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev,
+				RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL);
+		if (!rfk_threeg) {
+			retval = -ENOMEM;
+			goto err_threeg;
+		}
+		retval = rfkill_register(rfk_threeg);
+		if (retval)
+			goto err_threeg;
 	}
-	retval = rfkill_register(rfk_threeg);
-	if (retval)
-		goto err_threeg;
 
 	return 0;
 
@@ -649,6 +668,9 @@
 	if (force || dmi_check_system(msi_dmi_table))
 		old_ec_model = 1;
 
+	if (!old_ec_model)
+		get_threeg_exists();
+
 	if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table))
 		load_scm_model = 1;
 
@@ -694,7 +716,9 @@
 		goto fail_platform_device2;
 
 	if (!old_ec_model) {
-		ret = device_create_file(&msipf_device->dev, &dev_attr_threeg);
+		if (threeg_exists)
+			ret = device_create_file(&msipf_device->dev,
+						&dev_attr_threeg);
 		if (ret)
 			goto fail_platform_device2;
 	}
@@ -733,7 +757,7 @@
 {
 
 	sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
-	if (!old_ec_model)
+	if (!old_ec_model && threeg_exists)
 		device_remove_file(&msipf_device->dev, &dev_attr_threeg);
 	platform_device_unregister(msipf_device);
 	platform_driver_unregister(&msipf_driver);