]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/net/wireless/mediatek/mt76/eeprom.c
powerpc/cacheinfo: Remove double free
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / wireless / mediatek / mt76 / eeprom.c
1 /*
2 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 #include <linux/of.h>
17 #include <linux/of_net.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/mtd/partitions.h>
20 #include <linux/etherdevice.h>
21 #include "mt76.h"
22
23 static int
24 mt76_get_of_eeprom(struct mt76_dev *dev, int len)
25 {
26 #if defined(CONFIG_OF) && defined(CONFIG_MTD)
27 struct device_node *np = dev->dev->of_node;
28 struct mtd_info *mtd;
29 const __be32 *list;
30 const char *part;
31 phandle phandle;
32 int offset = 0;
33 int size;
34 size_t retlen;
35 int ret;
36
37 if (!np)
38 return -ENOENT;
39
40 list = of_get_property(np, "mediatek,mtd-eeprom", &size);
41 if (!list)
42 return -ENOENT;
43
44 phandle = be32_to_cpup(list++);
45 if (!phandle)
46 return -ENOENT;
47
48 np = of_find_node_by_phandle(phandle);
49 if (!np)
50 return -EINVAL;
51
52 part = of_get_property(np, "label", NULL);
53 if (!part)
54 part = np->name;
55
56 mtd = get_mtd_device_nm(part);
57 if (IS_ERR(mtd)) {
58 ret = PTR_ERR(mtd);
59 goto out_put_node;
60 }
61
62 if (size <= sizeof(*list)) {
63 ret = -EINVAL;
64 goto out_put_node;
65 }
66
67 offset = be32_to_cpup(list);
68 ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data);
69 put_mtd_device(mtd);
70 if (ret)
71 goto out_put_node;
72
73 if (retlen < len) {
74 ret = -EINVAL;
75 goto out_put_node;
76 }
77
78 out_put_node:
79 of_node_put(np);
80 return ret;
81 #else
82 return -ENOENT;
83 #endif
84 }
85
86 void
87 mt76_eeprom_override(struct mt76_dev *dev)
88 {
89 #ifdef CONFIG_OF
90 struct device_node *np = dev->dev->of_node;
91 const u8 *mac;
92
93 if (!np)
94 return;
95
96 mac = of_get_mac_address(np);
97 if (!IS_ERR(mac))
98 memcpy(dev->macaddr, mac, ETH_ALEN);
99 #endif
100
101 if (!is_valid_ether_addr(dev->macaddr)) {
102 eth_random_addr(dev->macaddr);
103 dev_info(dev->dev,
104 "Invalid MAC address, using random address %pM\n",
105 dev->macaddr);
106 }
107 }
108 EXPORT_SYMBOL_GPL(mt76_eeprom_override);
109
110 int
111 mt76_eeprom_init(struct mt76_dev *dev, int len)
112 {
113 dev->eeprom.size = len;
114 dev->eeprom.data = devm_kzalloc(dev->dev, len, GFP_KERNEL);
115 if (!dev->eeprom.data)
116 return -ENOMEM;
117
118 return !mt76_get_of_eeprom(dev, len);
119 }
120 EXPORT_SYMBOL_GPL(mt76_eeprom_init);