WiMAX pull request
Subsystems (2)
cover WiMAX pull request
This pull request for 2.6.31 adds a new WiMAX API call for getting the device state (from Paulius Zaleckas), fixes random stuff in the i2400m, adds a debug facility to trace commands sent to the device and cleans up state-report handling code.
The following changes since commit 7d18f114897ff4358419b14d551e704a4299a440:
David S. Miller (1):
net: Fix arg to trace_napi_poll() in netpoll.
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax.git linux-2.6.31.y
Patches follow for reviewing convenience.
Inaky Perez-Gonzalez (9):
wimax/i2400m: generate fake source MAC address with random_ether_addr() wimax/i2400m: trace commands sent from user space on the "echo" pipe wimax/i2400m: allow kernel commands to device to be logged too wimax/i2400m: factor out 'state report's TLV handling to a function wimax/i2400m: remove redundant readiness checks from i2400m_report_tlv_*()
wimax: document why wimax_msg_*() operations can be used in any state wimax/i2400m: sdio: set the block size before enabling the function wimax/i2400m: usb: fix device reset on autosuspend while not yet idle
wimax: a new API call was added, increment minor protocol version number
Paulius Zaleckas (1):
wimax: Add netlink interface to get device state
drivers/net/wimax/i2400m/control.c | 100 ++++++++++++++++++++---------------- drivers/net/wimax/i2400m/driver.c | 5 +- drivers/net/wimax/i2400m/i2400m.h | 5 ++ drivers/net/wimax/i2400m/netdev.c | 3 +- drivers/net/wimax/i2400m/rx.c | 6 ++- drivers/net/wimax/i2400m/sdio.c | 18 +++--- drivers/net/wimax/i2400m/usb.c | 35 +++++++++++-- include/linux/wimax.h | 7 ++- net/wimax/Makefile | 1 + net/wimax/debug-levels.h | 1 + net/wimax/debugfs.c | 1 + net/wimax/op-msg.c | 17 +++++- net/wimax/op-state-get.c | 86 +++++++++++++++++++++++++++++++ net/wimax/stack.c | 5 ++- 14 files changed, 221 insertions(+), 69 deletions(-) create mode 100644 net/wimax/op-state-get.c
PATCH 1/10 wimax/i2400m: generate fake source MAC address with random_ether_addr()
The WiMAX i2400m driver needs to generate a fake source MAC address to fake an ethernet header (for destination, the card's MAC is used). This is the source of the packet, which is the basestation it came from. The basestation's mac address is not usable for this, as it uses its own namespace and it is not always available.
Currently the fake source MAC address was being set to all zeros, which was causing trouble with bridging.
Use random_ether_addr() to generate a proper one that creates no trouble.
--- drivers/net/wimax/i2400m/driver.c | 2 ++ drivers/net/wimax/i2400m/i2400m.h | 5 +++++ drivers/net/wimax/i2400m/netdev.c | 3 ++- 3 files changed, 9 insertions(+), 1 deletions(-)
drivers/net/wimax/i2400m/driver.c +2 -0
@@ -62,6 +62,7 @@* unregister_netdev() */ #include "i2400m.h" +#include <linux/etherdevice.h> #include <linux/wimax/i2400m.h> #include <linux/module.h> #include <linux/moduleparam.h>
@@ -650,6 +651,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) result =i2400m_read_mac_addr (i2400m);if (result <0 ) goto error_read_mac_addr; +random_ether_addr (i2400m->src_mac_addr); result =register_netdev (net_dev);/* Okey dokey, bring it up */ if (result <0 ) {
drivers/net/wimax/i2400m/i2400m.h +5 -0
@@ -323,6 +323,10 @@ struct i2400m_roq;* delivered. Then the driver can release them to the host. See * drivers/net/i2400m/rx.c for details. * +* @src_mac_addr: MAC address used to make ethernet packets be coming +* from. This is generated at i2400m_setup() time and used during +* the life cycle of the instance. See i2400m_fake_eth_header(). +* * @init_mutex: Mutex used for serializing the device bringup * sequence; this way if the device reboots in the middle, we * don't try to do a bringup again while we are tearing down the
@@ -421,6 +425,7 @@ struct i2400m {unsigned rx_pl_num, rx_pl_max, rx_pl_min, rx_num, rx_size_acc, rx_size_min, rx_size_max;struct i2400m_roq *rx_roq;/* not under rx_lock! */ +u8 src_mac_addr[ETH_HLEN ];struct mutex msg_mutex;/* serialize command execution */ struct completion msg_completion;
drivers/net/wimax/i2400m/netdev.c +2 -1
@@ -404,10 +404,11 @@ staticvoid i2400m_rx_fake_eth_header (struct net_device *net_dev,void *_eth_hdr,__be16 protocol) { +struct i2400m *i2400m =net_dev_to_i2400m (net_dev);struct ethhdr *eth_hdr = _eth_hdr;memcpy (eth_hdr->h_dest, net_dev->dev_addr,sizeof (eth_hdr->h_dest)); -memset (eth_hdr->h_source,0 ,sizeof (eth_hdr->h_dest)); +memcpy (eth_hdr->h_source, i2400m->src_mac_addr,sizeof (eth_hdr->h_source)); eth_hdr->h_proto = protocol; }
Signature · 1 line
1.6.2.3
PATCH 2/10 wimax/i2400m: trace commands sent from user space on the "echo" pipe
When commands are sent from user space, trace both the command sent and the answer received over the "echo" pipe instead of over the "trace" pipe when command tracing is enabled. As well, when the device sends a reports/indications, send it over the "echo" pipe.
The "trace" pipe is used by the device to send firmware traces; gets confusing. Another named pipe makes it easier to split debug information.
--- drivers/net/wimax/i2400m/driver.c | 13 ++++++++++--- drivers/net/wimax/i2400m/rx.c | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-)
drivers/net/wimax/i2400m/driver.c +10 -3
@@ -231,13 +231,20 @@ int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev,d_fnstart (4 , dev,"(wimax_dev %p [i2400m %p] msg_buf %p " "msg_len %zu genl_info %p)\n" , wimax_dev, i2400m, msg_buf, msg_len, genl_info); +if (unlikely (i2400m->trace_msg_from_user)) +wimax_msg (&i2400m->wimax_dev,"echo" , + msg_buf, msg_len,GFP_KERNEL ); ack_skb =i2400m_msg_to_dev (i2400m, msg_buf, msg_len); result =PTR_ERR (ack_skb);if (IS_ERR (ack_skb)) goto error_msg_to_dev; -if (unlikely (i2400m->trace_msg_from_user)) -wimax_msg (&i2400m->wimax_dev,"trace" , - msg_buf, msg_len,GFP_KERNEL ); +if (unlikely (i2400m->trace_msg_from_user)) { +const void *ack_data; +size_t ack_len; + ack_data =wimax_msg_data_len (ack_skb, &ack_len); +wimax_msg (&i2400m->wimax_dev,"echo" , + ack_data, ack_len,GFP_KERNEL ); + } result =wimax_msg_send (&i2400m->wimax_dev, ack_skb); error_msg_to_dev: d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
drivers/net/wimax/i2400m/rx.c +3 -0
@@ -309,6 +309,9 @@ void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx,skb_get (skb_rx);i2400m_queue_work (i2400m, i2400m_report_hook_work,GFP_KERNEL , &args,sizeof (args)); +if (unlikely (i2400m->trace_msg_from_user)) +wimax_msg (&i2400m->wimax_dev,"echo" , + l3l4_hdr, size,GFP_KERNEL ); result =wimax_msg (&i2400m->wimax_dev,NULL , l3l4_hdr, size,GFP_KERNEL );if (result <0 )
Signature · 1 line
1.6.2.3
PATCH 3/10 wimax/i2400m: allow kernel commands to device to be logged too
By running 'echo 1 > /sys/kernel/debug/wimax:wmxX/i2400m/trace_msg_from_user', the driver will echo to user space all the commands being sent to the device from user space, along with the responses.
However, this only helps with the commands being sent from user space; with this patch, the trace hook is moved to i2400m_msg_to_dev(), which is the single access point for running commands to the device (both by user space and the kernel driver). This allows better debugging by having a complete stream of commands/acks and reports.
--- drivers/net/wimax/i2400m/control.c | 5 +++++ drivers/net/wimax/i2400m/driver.c | 10 ---------- 2 files changed, 5 insertions(+), 10 deletions(-)
drivers/net/wimax/i2400m/control.c +5 -0
@@ -721,6 +721,8 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, ack_timeout =HZ ; }; +if (unlikely (i2400m->trace_msg_from_user)) +wimax_msg (&i2400m->wimax_dev,"echo" , buf, buf_len,GFP_KERNEL );/* The RX path in rx.c will put any response for this message * in i2400m->ack_skb and wake us up. If we cancel the wait, * we need to change the value of i2400m->ack_skb to something
@@ -755,6 +757,9 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, ack_l3l4_hdr =wimax_msg_data_len (ack_skb, &ack_len);/* Check the ack and deliver it if it is ok */ +if (unlikely (i2400m->trace_msg_from_user)) +wimax_msg (&i2400m->wimax_dev,"echo" , + ack_l3l4_hdr, ack_len,GFP_KERNEL ); result =i2400m_msg_size_check (i2400m, ack_l3l4_hdr, ack_len);if (result <0 ) { dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
drivers/net/wimax/i2400m/driver.c +0 -10
@@ -231,20 +231,10 @@ int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev,d_fnstart (4 , dev,"(wimax_dev %p [i2400m %p] msg_buf %p " "msg_len %zu genl_info %p)\n" , wimax_dev, i2400m, msg_buf, msg_len, genl_info); -if (unlikely (i2400m->trace_msg_from_user)) -wimax_msg (&i2400m->wimax_dev,"echo" , - msg_buf, msg_len,GFP_KERNEL ); ack_skb =i2400m_msg_to_dev (i2400m, msg_buf, msg_len); result =PTR_ERR (ack_skb);if (IS_ERR (ack_skb)) goto error_msg_to_dev; -if (unlikely (i2400m->trace_msg_from_user)) { -const void *ack_data; -size_t ack_len; - ack_data =wimax_msg_data_len (ack_skb, &ack_len); -wimax_msg (&i2400m->wimax_dev,"echo" , - ack_data, ack_len,GFP_KERNEL ); - } result =wimax_msg_send (&i2400m->wimax_dev, ack_skb); error_msg_to_dev: d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
Signature · 1 line
1.6.2.3
PATCH 4/10 wimax/i2400m: factor out 'state report's TLV handling to a function
i2400m_report_state_hook() is going to get messier as we add handling code.
--- drivers/net/wimax/i2400m/control.c | 89 ++++++++++++++++++++---------------- 1 files changed, 50 insertions(+), 39 deletions(-)
drivers/net/wimax/i2400m/control.c +50 -39
@@ -400,7 +400,53 @@ out:/* -* Parse a 'state report' and extract carrier on/off information +* Process a TLV from a 'state report' +* +* @i2400m: device descriptor +* @tlv: pointer to the TLV header; it has been already validated for +* consistent size. +* @tag: for error messages +* +* Act on the TLVs from a 'state report'. +*/ +static +void i2400m_report_state_parse_tlv (struct i2400m *i2400m, +const struct i2400m_tlv_hdr *tlv, +const char *tag) +{ +struct device *dev =i2400m_dev (i2400m); +const struct i2400m_tlv_media_status *ms; +const struct i2400m_tlv_system_state *ss; +const struct i2400m_tlv_rf_switches_status *rfss; + +if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_SYSTEM_STATE ,sizeof (*ss))) { + ss =container_of (tlv,typeof (*ss), hdr); +d_printf (2 , dev,"%s: system state TLV " +"found (0x%04x), state 0x%08x\n" , + tag,I2400M_TLV_SYSTEM_STATE , +le32_to_cpu (ss->state)); +i2400m_report_tlv_system_state (i2400m, ss); + } +if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_RF_STATUS ,sizeof (*rfss))) { + rfss =container_of (tlv,typeof (*rfss), hdr); +d_printf (2 , dev,"%s: RF status TLV " +"found (0x%04x), sw 0x%02x hw 0x%02x\n" , + tag,I2400M_TLV_RF_STATUS , +le32_to_cpu (rfss->sw_rf_switch), +le32_to_cpu (rfss->hw_rf_switch)); +i2400m_report_tlv_rf_switches_status (i2400m, rfss); + } +if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_MEDIA_STATUS ,sizeof (*ms))) { + ms =container_of (tlv,typeof (*ms), hdr); +d_printf (2 , dev,"%s: Media Status TLV: %u\n" , + tag,le32_to_cpu (ms->media_status)); +i2400m_report_tlv_media_status (i2400m, ms); + } +} + + +/* +* Parse a 'state report' and extract information * * @i2400m: device descriptor * @l3l4_hdr: pointer to message; it has been already validated for
@@ -409,13 +455,7 @@ out:* declaration is assumed to be congruent with @size (as in * sizeof(*l3l4_hdr) + l3l4_hdr->length == size) * -* Extract from the report state the system state TLV and infer from -* there if we have a carrier or not. Update our local state and tell -* netdev. -* -* When setting the carrier, it's fine to set OFF twice (for example), -* as netif_carrier_off() will not generate two OFF events (just on -* the transitions). +* Walk over the TLVs in a report state and act on them. */ static void i2400m_report_state_hook(struct i2400m *i2400m,
@@ -424,9 +464,6 @@ void i2400m_report_state_hook(struct i2400m *i2400m, {struct device *dev =i2400m_dev (i2400m);const struct i2400m_tlv_hdr *tlv; -const struct i2400m_tlv_system_state *ss; -const struct i2400m_tlv_rf_switches_status *rfss; -const struct i2400m_tlv_media_status *ms;size_t tlv_size =le16_to_cpu (l3l4_hdr->length); d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
@@ -434,34 +471,8 @@ void i2400m_report_state_hook(struct i2400m *i2400m, tlv =NULL ;while ((tlv =i2400m_tlv_buffer_walk (i2400m, &l3l4_hdr->pl, - tlv_size, tlv))) { -if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_SYSTEM_STATE , -sizeof (*ss))) { - ss =container_of (tlv,typeof (*ss), hdr); -d_printf (2 , dev,"%s: system state TLV " -"found (0x%04x), state 0x%08x\n" , - tag,I2400M_TLV_SYSTEM_STATE , -le32_to_cpu (ss->state)); -i2400m_report_tlv_system_state (i2400m, ss); - } -if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_RF_STATUS , -sizeof (*rfss))) { - rfss =container_of (tlv,typeof (*rfss), hdr); -d_printf (2 , dev,"%s: RF status TLV " -"found (0x%04x), sw 0x%02x hw 0x%02x\n" , - tag,I2400M_TLV_RF_STATUS , -le32_to_cpu (rfss->sw_rf_switch), -le32_to_cpu (rfss->hw_rf_switch)); -i2400m_report_tlv_rf_switches_status (i2400m, rfss); - } -if (0 ==i2400m_tlv_match (tlv,I2400M_TLV_MEDIA_STATUS , -sizeof (*ms))) { - ms =container_of (tlv,typeof (*ms), hdr); -d_printf (2 , dev,"%s: Media Status TLV: %u\n" , - tag,le32_to_cpu (ms->media_status)); -i2400m_report_tlv_media_status (i2400m, ms); - } - } + tlv_size, tlv))) +i2400m_report_state_parse_tlv (i2400m, tlv, tag);d_fnend (4 , dev,"(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n" , i2400m, l3l4_hdr, size, tag); }
Signature · 1 line
1.6.2.3
PATCH 5/10 wimax/i2400m: remove redundant readiness checks from i2400m_report_tlv_*()
Functions i2400m_report_tlv*() are only called from i2400m_report_hook(), called in a workqueue by i2400m_report_hook_work(). The scheduler checks for device readiness before scheduling.
Added an extra check for readiness in i2400m_report_hook_work(), which makes all the checks down the line redundant.
Obviously the device state could change in the middle, but error handling would take care of that.
--- drivers/net/wimax/i2400m/control.c | 6 ------ drivers/net/wimax/i2400m/rx.c | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-)
drivers/net/wimax/i2400m/control.c +0 -6
@@ -292,8 +292,6 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m,d_fnstart (3 , dev,"(i2400m %p ss %p [%u])\n" , i2400m, ss, i2400m_state); -if (unlikely (i2400m->ready ==0 ))/* act if up */ - goto out;if (i2400m->state != i2400m_state) { i2400m->state = i2400m_state;wake_up_all (&i2400m->state_wq);
@@ -341,7 +339,6 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, i2400m->bus_reset (i2400m,I2400M_RT_WARM );break ; }; -out:d_fnend (3 , dev,"(i2400m %p ss %p [%u]) = void\n" , i2400m, ss, i2400m_state); }
@@ -372,8 +369,6 @@ void i2400m_report_tlv_media_status(struct i2400m *i2400m,d_fnstart (3 , dev,"(i2400m %p ms %p [%u])\n" , i2400m, ms, status); -if (unlikely (i2400m->ready ==0 ))/* act if up */ - goto out;switch (status) {case I2400M_MEDIA_STATUS_LINK_UP :netif_carrier_on (net_dev);
@@ -393,7 +388,6 @@ void i2400m_report_tlv_media_status(struct i2400m *i2400m,dev_err (dev,"HW BUG? unknown media status %u\n" , status); }; -out:d_fnend (3 , dev,"(i2400m %p ms %p [%u]) = void\n" , i2400m, ms, status); }
drivers/net/wimax/i2400m/rx.c +2 -1
@@ -177,7 +177,8 @@ void i2400m_report_hook_work(struct work_struct *ws)struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);struct i2400m_report_hook_args *args = (void *) iw->pl; -i2400m_report_hook (iw->i2400m, args->l3l4_hdr, args->size); +if (iw->i2400m->ready) +i2400m_report_hook (iw->i2400m, args->l3l4_hdr, args->size);kfree_skb (args->skb_rx);i2400m_put (iw->i2400m);kfree (iw);
Signature · 1 line
1.6.2.3
PATCH 6/10 wimax: document why wimax_msg_*() operations can be used in any state
Funcion documentation for wimax_msg_alloc() and wimax_msg_send() needs to clarify that they can be used in the very early stages of a wimax_dev lifecycle.
--- net/wimax/op-msg.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-)
net/wimax/op-msg.c +14 -3
@@ -108,6 +108,12 @@* Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. +* +* Unlike other WiMAX stack calls, this call can be used way early, +* even before wimax_dev_add() is called, as long as the +* wimax_dev->net_dev pointer is set to point to a proper +* net_dev. This is so that drivers can use it early in case they need +* to send stuff around or communicate with user space. */ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, const char *pipe_name,
@@ -115,7 +121,7 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, gfp_t gfp_flags) {int result; -struct device *dev = wimax_dev->net_dev->dev.parent; +struct device *dev =wimax_dev_to_dev (wimax_dev);size_t msg_size;void *genl_msg;struct sk_buff *skb;
@@ -161,7 +167,6 @@ error_genlmsg_put: error_new:nlmsg_free (skb);return ERR_PTR (result); - }EXPORT_SYMBOL_GPL (wimax_msg_alloc);
@@ -256,10 +261,16 @@ EXPORT_SYMBOL_GPL(wimax_msg_len);* Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. +* +* Unlike other WiMAX stack calls, this call can be used way early, +* even before wimax_dev_add() is called, as long as the +* wimax_dev->net_dev pointer is set to point to a proper +* net_dev. This is so that drivers can use it early in case they need +* to send stuff around or communicate with user space. */ int wimax_msg_send (struct wimax_dev *wimax_dev,struct sk_buff *skb) { -struct device *dev = wimax_dev->net_dev->dev.parent; +struct device *dev =wimax_dev_to_dev (wimax_dev);void *msg = skb->data;size_t size = skb->len;might_sleep ();
Signature · 1 line
1.6.2.3
PATCH 7/10 wimax/i2400m: sdio: set the block size before enabling the function
Quoted 1 line
From a fix by Cindy H Kao:
Block size has to be set before sending IOE enable because the firmware reads the block size register before it reads IOE register.
--- drivers/net/wimax/i2400m/sdio.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
drivers/net/wimax/i2400m/sdio.c +9 -9
@@ -409,19 +409,19 @@ int i2400ms_probe(struct sdio_func *func, i2400m->bus_fw_names = i2400ms_bus_fw_names; i2400m->bus_bm_mac_addr_impaired =1 ; - result =i2400ms_enable_function (i2400ms->func); -if (result <0 ) { -dev_err (dev,"Cannot enable SDIO function: %d\n" , result); - goto error_func_enable; - } -sdio_claim_host (func); result =sdio_set_block_size (func,I2400MS_BLK_SIZE ); +sdio_release_host (func);if (result <0 ) {dev_err (dev,"Failed to set block size: %d\n" , result); goto error_set_blk_size; } -sdio_release_host (func); + + result =i2400ms_enable_function (i2400ms->func); +if (result <0 ) { +dev_err (dev,"Cannot enable SDIO function: %d\n" , result); + goto error_func_enable; + } result =i2400m_setup (i2400m,I2400M_BRI_NO_REBOOT );if (result <0 ) {
@@ -440,12 +440,12 @@ int i2400ms_probe(struct sdio_func *func, error_debugfs_add:i2400m_release (i2400m); error_setup: -sdio_set_drvdata (func,NULL );sdio_claim_host (func); -error_set_blk_size:sdio_disable_func (func);sdio_release_host (func); error_func_enable: +error_set_blk_size: +sdio_set_drvdata (func,NULL );free_netdev (net_dev); error_alloc_netdev:return result;
Signature · 1 line
1.6.2.3
PATCH 8/10 wimax: Add netlink interface to get device state
From: Paulius Zaleckas <[email protected]>
wimax connection manager / daemon has to know what is current state of the device. Previously it was only possible to get notification whet state has changed.
--- include/linux/wimax.h | 5 +++ net/wimax/Makefile | 1 + net/wimax/debug-levels.h | 1 + net/wimax/debugfs.c | 1 + net/wimax/op-state-get.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ net/wimax/stack.c | 5 ++- 6 files changed, 98 insertions(+), 1 deletions(-) create mode 100644 net/wimax/op-state-get.c
include/linux/wimax.h +5 -0
@@ -77,6 +77,7 @@ enum {WIMAX_GNL_OP_MSG_TO_USER ,/* Kernel to user message */ WIMAX_GNL_OP_RFKILL ,/* Run wimax_rfkill() */ WIMAX_GNL_OP_RESET ,/* Run wimax_rfkill() */ +WIMAX_GNL_OP_STATE_GET ,/* Request for current state */ WIMAX_GNL_RE_STATE_CHANGE, /* Report: status change */ };
@@ -113,6 +114,10 @@ enum { WIMAX_GNL_RESET_IFIDX = 1, }; +/* Atributes for wimax_state_get() */ +enum { +WIMAX_GNL_STGET_IFIDX =1 , +};/* * Attributes for the Report State Change
net/wimax/Makefile +1 -0
@@ -6,6 +6,7 @@ wimax-y := \ op-msg.o \ op-reset.o \ op-rfkill.o \ + op-state-get.o \ stack.o wimax-$(CONFIG_DEBUG_FS) += debugfs.o
net/wimax/debug-levels.h +1 -0
@@ -36,6 +36,7 @@ enum d_module {D_SUBMODULE_DECLARE (op_msg),D_SUBMODULE_DECLARE (op_reset),D_SUBMODULE_DECLARE (op_rfkill), +D_SUBMODULE_DECLARE (op_state_get), D_SUBMODULE_DECLARE(stack), };
net/wimax/debugfs.c +1 -0
@@ -61,6 +61,7 @@ int wimax_debugfs_add(struct wimax_dev *wimax_dev)__debugfs_register ("wimax_dl_" , op_msg, dentry);__debugfs_register ("wimax_dl_" , op_reset, dentry);__debugfs_register ("wimax_dl_" , op_rfkill, dentry); +__debugfs_register ("wimax_dl_" , op_state_get, dentry);__debugfs_register ("wimax_dl_" , stack, dentry); result =0 ; out:
net/wimax/op-state-get.c new file +86 -0
86 lines not on this page · raw message
net/wimax/stack.c +4 -1
@@ -402,13 +402,15 @@ EXPORT_SYMBOL_GPL(wimax_dev_init);extern struct genl_ops wimax_gnl_msg_from_user, wimax_gnl_reset, - wimax_gnl_rfkill; + wimax_gnl_rfkill, + wimax_gnl_state_get;static struct genl_ops *wimax_gnl_ops[] = { &wimax_gnl_msg_from_user, &wimax_gnl_reset, &wimax_gnl_rfkill, + &wimax_gnl_state_get, };
@@ -533,6 +535,7 @@ struct d_level D_LEVEL[] = {D_SUBMODULE_DEFINE (op_msg),D_SUBMODULE_DEFINE (op_reset),D_SUBMODULE_DEFINE (op_rfkill), +D_SUBMODULE_DEFINE (op_state_get), D_SUBMODULE_DEFINE(stack), };size_t D_LEVEL_SIZE =ARRAY_SIZE (D_LEVEL );
Signature · 1 line
1.6.2.3
PATCH 9/10 wimax/i2400m: usb: fix device reset on autosuspend while not yet idle
When the i2400m is connected to a network, the host interface (USB) cannot be suspended. For that to happen, the device has to have negotiated with the basestation to put the link on IDLE state.
If the host tries to put the device in standby while it is connected but not idle, the device resets, as the driver should not do that.
To avoid triggering that, when the USB susbsytem requires the driver to autosuspend the device, the driver checks if the device is not yet idle. If it is not, the request is requested (will be retried again later on after the autosuspend timeout). At some point the device will enter idle and the request will succeed (unless of course, there is network traffic, but at that point, there is no idle neither in the link or the host interface).
--- drivers/net/wimax/i2400m/usb.c | 35 ++++++++++++++++++++++++++++++----- 1 files changed, 30 insertions(+), 5 deletions(-)
drivers/net/wimax/i2400m/usb.c +30 -5
@@ -505,27 +505,52 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)#ifdef CONFIG_PM struct usb_device *usb_dev = i2400mu->usb_dev;#endif +unsigned is_autosuspend =0 ;struct i2400m *i2400m = &i2400mu->i2400m; +#ifdef CONFIG_PM +if (usb_dev->auto_pm >0 ) + is_autosuspend =1 ; +#endif +d_fnstart (3 , dev,"(iface %p pm_msg %u)\n" , iface, pm_msg.event);if (i2400m->updown ==0 ) goto no_firmware; -d_printf (1 , dev,"fw up, requesting standby\n" ); +if (i2400m->state ==I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) { +/* ugh -- the device is connected and this suspend +* request is an autosuspend one (not a system standby +* / hibernate). +* +* The only way the device can go to standby is if the +* link with the base station is in IDLE mode; that +* were the case, we'd be in status +* I2400M_SS_CONNECTED_IDLE. But we are not. +* +* If we *tell* him to go power save now, it'll reset +* as a precautionary measure, so if this is an +* autosuspend thing, say no and it'll come back +* later, when the link is IDLE +*/ + result = -EBADF ; +d_printf (1 , dev,"fw up, link up, not-idle, autosuspend: " +"not entering powersave\n" ); + goto error_not_now; + } +d_printf (1 , dev,"fw up: entering powersave\n" );atomic_dec (&i2400mu->do_autopm); result =i2400m_cmd_enter_powersave (i2400m);atomic_inc (&i2400mu->do_autopm); -#ifdef CONFIG_PM -if (result <0 && usb_dev->auto_pm ==0 ) { +if (result <0 && !is_autosuspend) {/* System suspend, can't fail */ dev_err (dev,"failed to suspend, will reset on resume\n" ); result =0 ; } -#endif if (result <0 ) goto error_enter_powersave;i2400mu_notification_release (i2400mu); -d_printf (1 , dev,"fw up, got standby\n" ); +d_printf (1 , dev,"powersave requested\n" ); error_enter_powersave: +error_not_now: no_firmware:d_fnend (3 , dev,"(iface %p pm_msg %u) = %d\n" , iface, pm_msg.event, result);
Signature · 1 line
1.6.2.3
PATCH 10/10 wimax: a new API call was added, increment minor protocol version number
As the 'state_get' API call was added, we need to increase the minor protocol version number so applications that depend on the can check it's presence.
--- include/linux/wimax.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/wimax.h +1 -1
@@ -59,7 +59,7 @@ enum {* M - Major: change if removing or modifying an existing call. * m - minor: change when adding a new call */ -WIMAX_GNL_VERSION =00 , +WIMAX_GNL_VERSION =01 ,/* Generic NetLink attributes */ WIMAX_GNL_ATTR_INVALID =0x00 , WIMAX_GNL_ATTR_MAX = 10,
Signature · 1 line
1.6.2.3
Re: [patch 2.6.31 08/10] wimax: Add netlink interface to get device state
In reply to Inaky Perez-GonzalezQuoted 22 lines · On Wed, 27 May 2009 18:05:13 -0700 Inaky Perez-Gonzalez…
From: Paulius Zaleckas <[email protected]>
wimax connection manager / daemon has to know what is current state of the device. Previously it was only possible to get notification whet state has changed.
Signed-off-by Paulius Zaleckas <[email protected]>--- include/linux/wimax.h | 5 +++ net/wimax/Makefile | 1 + net/wimax/debug-levels.h | 1 + net/wimax/debugfs.c | 1 + net/wimax/op-state-get.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ net/wimax/stack.c | 5 ++- 6 files changed, 98 insertions(+), 1 deletions(-) create mode 100644 net/wimax/op-state-get.cinclude/linux/wimax.h +0
-0
include/linux/wimax.h enum { · line 82
Quoted 6 lines
include/linux/wimax.h +1
-0@@ -77,6 +77,7 @@ enum {WIMAX_GNL_OP_MSG_TO_USER ,/* Kernel to user message */ WIMAX_GNL_OP_RFKILL ,/* Run wimax_rfkill() */ WIMAX_GNL_OP_RESET ,/* Run wimax_rfkill() */ +WIMAX_GNL_OP_STATE_GET ,/* Request for current state */ WIMAX_GNL_RE_STATE_CHANGE, /* Report: status change */ };
Won't adding new element in middle of list break existing ABI?
Re: [patch 2.6.31 08/10] wimax: Add netlink interface to get device state
Quoted 11 lines · Stephen Hemminger
On Wed, 27 May 2009 18:05:13 -0700
Quoted 8 lines · Inaky Perez-Gonzalez
From: Paulius Zaleckas <[email protected]>
wimax connection manager / daemon has to know what is current state of the device. Previously it was only possible to get notification whet state has changed.
...
...
Quoted 13 lines
include/linux/wimax.h enum { · line 82
Quoted 11 lines
Quoted 1 line
include/linux/wimax.h
Quoted 1 line
include/linux/wimax.h +0
-0index c89de7f..c750f42 100644
include/linux/wimax.h +1
-0@@ -77,6 +77,7 @@ enum {WIMAX_GNL_OP_MSG_TO_USER ,/* Kernel to user message */ WIMAX_GNL_OP_RFKILL ,/* Run wimax_rfkill() */ WIMAX_GNL_OP_RESET ,/* Run wimax_rfkill() */ +WIMAX_GNL_OP_STATE_GET ,/* Request for current state */ WIMAX_GNL_RE_STATE_CHANGE, /* Report: status change */ };Won't adding new element in middle of list break existing ABI?
Actually that's an extremely good point that I missed completely. Thanks for catching it.
David, I'll submit an extra commit for correcting that point.
Signature · 1 line
Inaky
David Miller
maintainerRe: [patch 2.6.31 08/10] wimax: Add netlink interface to get device state
From: Inaky Perez-Gonzalez <[email protected]>
Date: Thu, 28 May 2009 09:16:21 -0700
Quoted 4 lines
Actually that's an extremely good point that I missed completely. Thanks for catching it.
David, I'll submit an extra commit for correcting that point.
As I explained on IRC, it's better to repsin the patch set, putting the bug fix into patch #8 discussed here, rather than to add a follow-on fix for the bug.
This way the tree is properly bisectable.
Thanks.
Re: [patch 2.6.31 08/10] wimax: Add netlink interface to get device state
Quoted 6 lines · David Miller
From: Inaky Perez-Gonzalez <[email protected]>
Date: Thu, 28 May 2009 09:16:21 -0700Quoted 3 lines
Actually that's an extremely good point that I missed completely. Thanks for catching it.
Quoted 7 lines
Quoted 1 line
David, I'll submit an extra commit for correcting that point.
As I explained on IRC, it's better to repsin the patch set, putting the bug fix into patch #8 discussed here, rather than to add a follow-on fix for the bug.
This way the tree is properly bisectable.
Thanks, I'll do so.
Sorry I missed you on IRC--had to run to a meeting.
Signature · 1 line
Inaky