diff options
Diffstat (limited to 'drivers/net/wimax/i2400m')
-rw-r--r-- | drivers/net/wimax/i2400m/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/control.c | 98 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/debug-levels.h | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 10 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 29 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/sysfs.c | 80 |
6 files changed, 211 insertions, 8 deletions
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile index 1696e936cf5a..5d9e018d31af 100644 --- a/drivers/net/wimax/i2400m/Makefile +++ b/drivers/net/wimax/i2400m/Makefile | |||
@@ -8,6 +8,7 @@ i2400m-y := \ | |||
8 | driver.o \ | 8 | driver.o \ |
9 | fw.o \ | 9 | fw.o \ |
10 | op-rfkill.o \ | 10 | op-rfkill.o \ |
11 | sysfs.o \ | ||
11 | netdev.o \ | 12 | netdev.o \ |
12 | tx.o \ | 13 | tx.o \ |
13 | rx.o | 14 | rx.o |
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index c8b3a68b72b8..c3968b240d69 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c | |||
@@ -1222,6 +1222,77 @@ EXPORT_SYMBOL_GPL(i2400m_set_init_config); | |||
1222 | 1222 | ||
1223 | 1223 | ||
1224 | /** | 1224 | /** |
1225 | * i2400m_set_idle_timeout - Set the device's idle mode timeout | ||
1226 | * | ||
1227 | * @i2400m: i2400m device descriptor | ||
1228 | * | ||
1229 | * @msecs: milliseconds for the timeout to enter idle mode. Between | ||
1230 | * 100 to 300000 (5m); 0 to disable. In increments of 100. | ||
1231 | * | ||
1232 | * After this @msecs of the link being idle (no data being sent or | ||
1233 | * received), the device will negotiate with the basestation entering | ||
1234 | * idle mode for saving power. The connection is maintained, but | ||
1235 | * getting out of it (done in tx.c) will require some negotiation, | ||
1236 | * possible crypto re-handshake and a possible DHCP re-lease. | ||
1237 | * | ||
1238 | * Only available if fw_version >= 0x00090002. | ||
1239 | * | ||
1240 | * Returns: 0 if ok, < 0 errno code on error. | ||
1241 | */ | ||
1242 | int i2400m_set_idle_timeout(struct i2400m *i2400m, unsigned msecs) | ||
1243 | { | ||
1244 | int result; | ||
1245 | struct device *dev = i2400m_dev(i2400m); | ||
1246 | struct sk_buff *ack_skb; | ||
1247 | struct { | ||
1248 | struct i2400m_l3l4_hdr hdr; | ||
1249 | struct i2400m_tlv_config_idle_timeout cit; | ||
1250 | } *cmd; | ||
1251 | const struct i2400m_l3l4_hdr *ack; | ||
1252 | size_t ack_len; | ||
1253 | char strerr[32]; | ||
1254 | |||
1255 | result = -ENOSYS; | ||
1256 | if (i2400m_le_v1_3(i2400m)) | ||
1257 | goto error_alloc; | ||
1258 | result = -ENOMEM; | ||
1259 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1260 | if (cmd == NULL) | ||
1261 | goto error_alloc; | ||
1262 | cmd->hdr.type = cpu_to_le16(I2400M_MT_GET_STATE); | ||
1263 | cmd->hdr.length = cpu_to_le16(sizeof(*cmd) - sizeof(cmd->hdr)); | ||
1264 | cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
1265 | |||
1266 | cmd->cit.hdr.type = | ||
1267 | cpu_to_le16(I2400M_TLV_CONFIG_IDLE_TIMEOUT); | ||
1268 | cmd->cit.hdr.length = cpu_to_le16(sizeof(cmd->cit.timeout)); | ||
1269 | cmd->cit.timeout = cpu_to_le32(msecs); | ||
1270 | |||
1271 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
1272 | if (IS_ERR(ack_skb)) { | ||
1273 | dev_err(dev, "Failed to issue 'set idle timeout' command: " | ||
1274 | "%ld\n", PTR_ERR(ack_skb)); | ||
1275 | result = PTR_ERR(ack_skb); | ||
1276 | goto error_msg_to_dev; | ||
1277 | } | ||
1278 | ack = wimax_msg_data_len(ack_skb, &ack_len); | ||
1279 | result = i2400m_msg_check_status(ack, strerr, sizeof(strerr)); | ||
1280 | if (result < 0) { | ||
1281 | dev_err(dev, "'set idle timeout' (0x%04x) command failed: " | ||
1282 | "%d - %s\n", I2400M_MT_GET_STATE, result, strerr); | ||
1283 | goto error_cmd_failed; | ||
1284 | } | ||
1285 | result = 0; | ||
1286 | kfree_skb(ack_skb); | ||
1287 | error_cmd_failed: | ||
1288 | error_msg_to_dev: | ||
1289 | kfree(cmd); | ||
1290 | error_alloc: | ||
1291 | return result; | ||
1292 | } | ||
1293 | |||
1294 | |||
1295 | /** | ||
1225 | * i2400m_dev_initialize - Initialize the device once communications are ready | 1296 | * i2400m_dev_initialize - Initialize the device once communications are ready |
1226 | * | 1297 | * |
1227 | * @i2400m: device descriptor | 1298 | * @i2400m: device descriptor |
@@ -1239,19 +1310,28 @@ int i2400m_dev_initialize(struct i2400m *i2400m) | |||
1239 | int result; | 1310 | int result; |
1240 | struct device *dev = i2400m_dev(i2400m); | 1311 | struct device *dev = i2400m_dev(i2400m); |
1241 | struct i2400m_tlv_config_idle_parameters idle_params; | 1312 | struct i2400m_tlv_config_idle_parameters idle_params; |
1313 | struct i2400m_tlv_config_idle_timeout idle_timeout; | ||
1242 | const struct i2400m_tlv_hdr *args[9]; | 1314 | const struct i2400m_tlv_hdr *args[9]; |
1243 | unsigned argc = 0; | 1315 | unsigned argc = 0; |
1244 | 1316 | ||
1245 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 1317 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
1246 | /* Useless for now...might change */ | ||
1247 | if (i2400m_idle_mode_disabled) { | 1318 | if (i2400m_idle_mode_disabled) { |
1248 | idle_params.hdr.type = | 1319 | if (i2400m_le_v1_3(i2400m)) { |
1249 | cpu_to_le16(I2400M_TLV_CONFIG_IDLE_PARAMETERS); | 1320 | idle_params.hdr.type = |
1250 | idle_params.hdr.length = cpu_to_le16( | 1321 | cpu_to_le16(I2400M_TLV_CONFIG_IDLE_PARAMETERS); |
1251 | sizeof(idle_params) - sizeof(idle_params.hdr)); | 1322 | idle_params.hdr.length = cpu_to_le16( |
1252 | idle_params.idle_timeout = 0; | 1323 | sizeof(idle_params) - sizeof(idle_params.hdr)); |
1253 | idle_params.idle_paging_interval = 0; | 1324 | idle_params.idle_timeout = 0; |
1254 | args[argc++] = &idle_params.hdr; | 1325 | idle_params.idle_paging_interval = 0; |
1326 | args[argc++] = &idle_params.hdr; | ||
1327 | } else { | ||
1328 | idle_timeout.hdr.type = | ||
1329 | cpu_to_le16(I2400M_TLV_CONFIG_IDLE_TIMEOUT); | ||
1330 | idle_timeout.hdr.length = cpu_to_le16( | ||
1331 | sizeof(idle_timeout) - sizeof(idle_timeout.hdr)); | ||
1332 | idle_timeout.timeout = 0; | ||
1333 | args[argc++] = &idle_timeout.hdr; | ||
1334 | } | ||
1255 | } | 1335 | } |
1256 | result = i2400m_set_init_config(i2400m, args, argc); | 1336 | result = i2400m_set_init_config(i2400m, args, argc); |
1257 | if (result < 0) | 1337 | if (result < 0) |
@@ -1264,6 +1344,8 @@ int i2400m_dev_initialize(struct i2400m *i2400m) | |||
1264 | */ | 1344 | */ |
1265 | result = i2400m_cmd_get_state(i2400m); | 1345 | result = i2400m_cmd_get_state(i2400m); |
1266 | error: | 1346 | error: |
1347 | if (result < 0) | ||
1348 | dev_err(dev, "failed to initialize the device: %d\n", result); | ||
1267 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | 1349 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); |
1268 | return result; | 1350 | return result; |
1269 | } | 1351 | } |
diff --git a/drivers/net/wimax/i2400m/debug-levels.h b/drivers/net/wimax/i2400m/debug-levels.h index 3183baa16a52..48fbfaa0d403 100644 --- a/drivers/net/wimax/i2400m/debug-levels.h +++ b/drivers/net/wimax/i2400m/debug-levels.h | |||
@@ -38,6 +38,7 @@ enum d_module { | |||
38 | D_SUBMODULE_DECLARE(netdev), | 38 | D_SUBMODULE_DECLARE(netdev), |
39 | D_SUBMODULE_DECLARE(rfkill), | 39 | D_SUBMODULE_DECLARE(rfkill), |
40 | D_SUBMODULE_DECLARE(rx), | 40 | D_SUBMODULE_DECLARE(rx), |
41 | D_SUBMODULE_DECLARE(sysfs), | ||
41 | D_SUBMODULE_DECLARE(tx), | 42 | D_SUBMODULE_DECLARE(tx), |
42 | }; | 43 | }; |
43 | 44 | ||
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 69a816e7c5db..f988771bfae0 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -662,6 +662,11 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | |||
662 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); | 662 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); |
663 | 663 | ||
664 | /* Now setup all that requires a registered net and wimax device. */ | 664 | /* Now setup all that requires a registered net and wimax device. */ |
665 | result = sysfs_create_group(&net_dev->dev.kobj, &i2400m_dev_attr_group); | ||
666 | if (result < 0) { | ||
667 | dev_err(dev, "cannot setup i2400m's sysfs: %d\n", result); | ||
668 | goto error_sysfs_setup; | ||
669 | } | ||
665 | result = i2400m_debugfs_add(i2400m); | 670 | result = i2400m_debugfs_add(i2400m); |
666 | if (result < 0) { | 671 | if (result < 0) { |
667 | dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); | 672 | dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); |
@@ -671,6 +676,9 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | |||
671 | return result; | 676 | return result; |
672 | 677 | ||
673 | error_debugfs_setup: | 678 | error_debugfs_setup: |
679 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, | ||
680 | &i2400m_dev_attr_group); | ||
681 | error_sysfs_setup: | ||
674 | wimax_dev_rm(&i2400m->wimax_dev); | 682 | wimax_dev_rm(&i2400m->wimax_dev); |
675 | error_wimax_dev_add: | 683 | error_wimax_dev_add: |
676 | i2400m_dev_stop(i2400m); | 684 | i2400m_dev_stop(i2400m); |
@@ -702,6 +710,8 @@ void i2400m_release(struct i2400m *i2400m) | |||
702 | netif_stop_queue(i2400m->wimax_dev.net_dev); | 710 | netif_stop_queue(i2400m->wimax_dev.net_dev); |
703 | 711 | ||
704 | i2400m_debugfs_rm(i2400m); | 712 | i2400m_debugfs_rm(i2400m); |
713 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, | ||
714 | &i2400m_dev_attr_group); | ||
705 | wimax_dev_rm(&i2400m->wimax_dev); | 715 | wimax_dev_rm(&i2400m->wimax_dev); |
706 | i2400m_dev_stop(i2400m); | 716 | i2400m_dev_stop(i2400m); |
707 | unregister_netdev(i2400m->wimax_dev.net_dev); | 717 | unregister_netdev(i2400m->wimax_dev.net_dev); |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 5008cdb12b42..0c60d5c43007 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -585,6 +585,8 @@ unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr) | |||
585 | * Driver / device setup and internal functions | 585 | * Driver / device setup and internal functions |
586 | */ | 586 | */ |
587 | extern void i2400m_netdev_setup(struct net_device *net_dev); | 587 | extern void i2400m_netdev_setup(struct net_device *net_dev); |
588 | extern int i2400m_sysfs_setup(struct device_driver *); | ||
589 | extern void i2400m_sysfs_release(struct device_driver *); | ||
588 | extern int i2400m_tx_setup(struct i2400m *); | 590 | extern int i2400m_tx_setup(struct i2400m *); |
589 | extern void i2400m_wake_tx_work(struct work_struct *); | 591 | extern void i2400m_wake_tx_work(struct work_struct *); |
590 | extern void i2400m_tx_release(struct i2400m *); | 592 | extern void i2400m_tx_release(struct i2400m *); |
@@ -728,6 +730,7 @@ extern struct sk_buff *i2400m_get_device_info(struct i2400m *); | |||
728 | extern int i2400m_firmware_check(struct i2400m *); | 730 | extern int i2400m_firmware_check(struct i2400m *); |
729 | extern int i2400m_set_init_config(struct i2400m *, | 731 | extern int i2400m_set_init_config(struct i2400m *, |
730 | const struct i2400m_tlv_hdr **, size_t); | 732 | const struct i2400m_tlv_hdr **, size_t); |
733 | extern int i2400m_set_idle_timeout(struct i2400m *, unsigned); | ||
731 | 734 | ||
732 | static inline | 735 | static inline |
733 | struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep) | 736 | struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep) |
@@ -740,6 +743,32 @@ extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, | |||
740 | extern void i2400m_report_tlv_rf_switches_status( | 743 | extern void i2400m_report_tlv_rf_switches_status( |
741 | struct i2400m *, const struct i2400m_tlv_rf_switches_status *); | 744 | struct i2400m *, const struct i2400m_tlv_rf_switches_status *); |
742 | 745 | ||
746 | /* | ||
747 | * Helpers for firmware backwards compability | ||
748 | * | ||
749 | * As we aim to support at least the firmware version that was | ||
750 | * released with the previous kernel/driver release, some code will be | ||
751 | * conditionally executed depending on the firmware version. On each | ||
752 | * release, the code to support fw releases past the last two ones | ||
753 | * will be purged. | ||
754 | * | ||
755 | * By making it depend on this macros, it is easier to keep it a tab | ||
756 | * on what has to go and what not. | ||
757 | */ | ||
758 | static inline | ||
759 | unsigned i2400m_le_v1_3(struct i2400m *i2400m) | ||
760 | { | ||
761 | /* running fw is lower or v1.3 */ | ||
762 | return i2400m->fw_version <= 0x00090001; | ||
763 | } | ||
764 | |||
765 | static inline | ||
766 | unsigned i2400m_ge_v1_4(struct i2400m *i2400m) | ||
767 | { | ||
768 | /* running fw is higher or v1.4 */ | ||
769 | return i2400m->fw_version >= 0x00090002; | ||
770 | } | ||
771 | |||
743 | 772 | ||
744 | /* | 773 | /* |
745 | * Do a millisecond-sleep for allowing wireshark to dump all the data | 774 | * Do a millisecond-sleep for allowing wireshark to dump all the data |
diff --git a/drivers/net/wimax/i2400m/sysfs.c b/drivers/net/wimax/i2400m/sysfs.c new file mode 100644 index 000000000000..1237109f251a --- /dev/null +++ b/drivers/net/wimax/i2400m/sysfs.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Sysfs interfaces to show driver and device information | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/etherdevice.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/device.h> | ||
28 | #include "i2400m.h" | ||
29 | |||
30 | |||
31 | #define D_SUBMODULE sysfs | ||
32 | #include "debug-levels.h" | ||
33 | |||
34 | |||
35 | /* | ||
36 | * Set the idle timeout (msecs) | ||
37 | * | ||
38 | * FIXME: eventually this should be a common WiMAX stack method, but | ||
39 | * would like to wait to see how other devices manage it. | ||
40 | */ | ||
41 | static | ||
42 | ssize_t i2400m_idle_timeout_store(struct device *dev, | ||
43 | struct device_attribute *attr, | ||
44 | const char *buf, size_t size) | ||
45 | { | ||
46 | ssize_t result; | ||
47 | struct i2400m *i2400m = net_dev_to_i2400m(to_net_dev(dev)); | ||
48 | unsigned val; | ||
49 | |||
50 | result = -EINVAL; | ||
51 | if (sscanf(buf, "%u\n", &val) != 1) | ||
52 | goto error_no_unsigned; | ||
53 | if (val != 0 && (val < 100 || val > 300000 || val % 100 != 0)) { | ||
54 | dev_err(dev, "idle_timeout: %u: invalid msecs specification; " | ||
55 | "valid values are 0, 100-300000 in 100 increments\n", | ||
56 | val); | ||
57 | goto error_bad_value; | ||
58 | } | ||
59 | result = i2400m_set_idle_timeout(i2400m, val); | ||
60 | if (result >= 0) | ||
61 | result = size; | ||
62 | error_no_unsigned: | ||
63 | error_bad_value: | ||
64 | return result; | ||
65 | } | ||
66 | |||
67 | static | ||
68 | DEVICE_ATTR(i2400m_idle_timeout, S_IWUSR, | ||
69 | NULL, i2400m_idle_timeout_store); | ||
70 | |||
71 | static | ||
72 | struct attribute *i2400m_dev_attrs[] = { | ||
73 | &dev_attr_i2400m_idle_timeout.attr, | ||
74 | NULL, | ||
75 | }; | ||
76 | |||
77 | struct attribute_group i2400m_dev_attr_group = { | ||
78 | .name = NULL, /* we want them in the same directory */ | ||
79 | .attrs = i2400m_dev_attrs, | ||
80 | }; | ||