summaryrefslogtreecommitdiffstats
path: root/patches/linux-3.8.13/0340-bone-capemgr-Make-sure-cape-removal-works.patch
blob: 838b423f3f74658293182343bf7240d029b1139f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
From: Pantelis Antoniou <panto@antoniou-consulting.com>
Date: Wed, 27 Feb 2013 11:32:20 +0200
Subject: [PATCH] bone-capemgr: Make sure cape removal works.

Cape removal wasn't working properly before; fix it.

Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 drivers/misc/cape/beaglebone/capemgr.c |   62 +++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 17 deletions(-)

diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
index d828af7..2656e3a 100644
--- a/drivers/misc/cape/beaglebone/capemgr.c
+++ b/drivers/misc/cape/beaglebone/capemgr.c
@@ -154,6 +154,7 @@ static int bone_slot_fill_override(struct bone_cape_slot *slot,
 static struct bone_cape_slot *bone_capemgr_add_slot(
 		struct bone_capemgr_info *info, struct device_node *node,
 		const char *part_number, const char *version);
+static int bone_capemgr_remove_slot(struct bone_cape_slot *slot);
 static int bone_capemgr_load(struct bone_cape_slot *slot);
 static int bone_capemgr_unload(struct bone_cape_slot *slot);
 
@@ -991,14 +992,23 @@ static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
 			if (slotno == slot->slotno)
 				break;
 		}
-		mutex_unlock(&info->slots_list_mutex);
 
-		if (slot == NULL)
+		/* found? */
+		if (slot == NULL) {
+			mutex_unlock(&info->slots_list_mutex);
 			return -ENODEV;
+		}
+
+		ret = bone_capemgr_remove_slot(slot);
+		mutex_unlock(&info->slots_list_mutex);
 
-		bone_capemgr_unload(slot);
+		if (ret == 0)
+			dev_info(&pdev->dev, "Removed slot #%d\n", slotno);
+		else
+			dev_err(&pdev->dev, "Failed to remove slot #%d\n",
+					slotno);
 
-		return strlen(buf);
+		return ret == 0 ? strlen(buf) : ret;
 	}
 
 	part_number = kstrdup(buf, GFP_KERNEL);
@@ -1292,6 +1302,35 @@ static int bone_capemgr_unload(struct bone_cape_slot *slot)
 
 }
 
+/* slots_list_mutex must be taken */
+static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	int ret;
+
+	if (slot == NULL)
+		return 0;
+
+	/* unload just in case */
+	ret = bone_capemgr_unload(slot);
+	if (ret != 0) {
+		dev_err(dev, "Unable to unload slot #%d\n", slot->slotno);
+		return ret;
+	}
+
+	/* if probed OK, remove the sysfs nodes */
+	if (slot->probed && !slot->probe_failed)
+		bone_cape_slot_sysfs_unregister(slot);
+
+	/* remove it from the list */
+	list_del(&slot->node);
+
+	devm_kfree(dev, slot);
+
+	return 0;
+}
+
 static int bone_slot_fill_override(struct bone_cape_slot *slot,
 		struct device_node *node,
 		const char *part_number, const char *version)
@@ -1755,19 +1794,8 @@ static int bone_capemgr_remove(struct platform_device *pdev)
 	int ret;
 
 	mutex_lock(&info->slots_list_mutex);
-	list_for_each_entry_safe(slot, slotn, &info->slot_list, node) {
-
-		/* unload just in case */
-		bone_capemgr_unload(slot);
-
-		/* if probed OK, remove the sysfs nodes */
-		if (slot->probed && !slot->probe_failed)
-			bone_cape_slot_sysfs_unregister(slot);
-
-		/* remove it from the list */
-		list_del(&slot->node);
-
-	}
+	list_for_each_entry_safe(slot, slotn, &info->slot_list, node)
+		bone_capemgr_remove_slot(slot);
 	mutex_unlock(&info->slots_list_mutex);
 
 	bone_capemgr_info_sysfs_unregister(info);