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
110
111
|
static char* eth_gpio_pin_name_by_attr_name(const char* name, int port) {
log_error("attirbute name [%s] is invalid for ETH in port %d", name, port);
return "";
}
// 1 vendor-id
// 1 product-id
// 1 device-id
// 1 hw-version
// 1 mac-addr or eui
// NULL
static size_t ap_eth_attrs_size = 6;
static bool eth_setup(enum ap port) {
int i;
int port_index = port - 1;
int index = 0;
int count = 0;
int ret;
char buf[32];
struct attribute **attrs;
log_info("loading ETH accessory card in port %d", port);
sprintf(buf, "ap%d", port);
ap_subdirs[port_index] = kobject_create_and_add(buf, &mts_io_platform_device->dev.kobj);
if (! ap_subdirs[port_index]) {
log_error("kobject_create_and_add for ETH in port %d failed", port);
return false;
}
// create the link to the apX directory this card is in
// if we're in the first slot, we get plain "eth"
// if we're in a different slot, we might need to use "eth-2" to differentiate
if (port > 1) {
for (i = 1; i < port; i++) {
if (port_info[i - 1]) {
if (strstr(port_info[i - 1]->product_id, PRODUCT_ID_MTAC_ETH)) {
count++;
}
}
}
}
if (count > 0) {
sprintf(buf, "eth-%d", count + 1);
} else {
sprintf(buf, "eth");
}
ret = sysfs_create_link(ap_subdirs[port_index]->parent, ap_subdirs[port_index], buf);
if (ret) {
log_error("failed to link [%s] to [%s], %d", buf, ap_subdirs[port_index]->name, ret);
}
attrs = kzalloc(sizeof(struct attribute*) * ap_eth_attrs_size, GFP_KERNEL);
if (! attrs) {
log_error("failed to allocate attribute space for port %d", port);
return false;
}
// add attributes for eeprom contents
if (! ap_add_product_info_attributes(port, MTAC_ETH_0_0, attrs, &index)) {
log_error("failed to add product info attributes for ETH in port %d", port);
return false;
}
attrs[index] = NULL;
ap_attr_groups[port_index].attrs = attrs;
if (sysfs_create_group(ap_subdirs[port_index], &ap_attr_groups[port_index])) {
log_error("sysfs_create_group failed for ETH in port %d", port);
return false;
}
return true;
}
static bool eth_teardown(enum ap port) {
int i;
int port_index = port - 1;
struct attribute **attrs = ap_attr_groups[port_index].attrs;
log_info("unloading ETH accessory card in port %d", port);
// clean up allocated memory for attributes
for (i = 0; i < ap_eth_attrs_size; i++) {
if (attrs[i]) {
if (attrs[i]->name)
kfree(attrs[i]->name);
kfree(attrs[i]);
}
}
kfree(attrs);
// clean up our "apX/" kobject if it exists
if (ap_subdirs[port_index]) {
kobject_put(ap_subdirs[port_index]);
}
return true;
}
bool set_eth_info(struct ap_info* info) {
snprintf(info->product_id, 32, "%s", PRODUCT_ID_MTAC_ETH);
info->setup = ð_setup;
info->teardown = ð_teardown;
info->gpio_pin_name_by_attr_name = ð_gpio_pin_name_by_attr_name;
return true;
}
|