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);
|