diff options
Diffstat (limited to 'drivers/net/wimax/i2400m/control.c')
-rw-r--r-- | drivers/net/wimax/i2400m/control.c | 124 |
1 files changed, 71 insertions, 53 deletions
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index b3cadb626fe0..07308686dbcf 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -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,14 +388,59 @@ 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); } /* - * 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 +449,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 +458,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 +465,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); } @@ -500,8 +505,15 @@ void i2400m_report_hook(struct i2400m *i2400m, * it. */ case I2400M_MT_REPORT_POWERSAVE_READY: /* zzzzz */ if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) { - d_printf(1, dev, "ready for powersave, requesting\n"); - i2400m_cmd_enter_powersave(i2400m); + if (i2400m_power_save_disabled) + d_printf(1, dev, "ready for powersave, " + "not requesting (disabled by module " + "parameter)\n"); + else { + d_printf(1, dev, "ready for powersave, " + "requesting\n"); + i2400m_cmd_enter_powersave(i2400m); + } } break; }; @@ -683,8 +695,9 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n", i2400m, buf, buf_len); + rmb(); /* Make sure we see what i2400m_dev_reset_handle() */ if (i2400m->boot_mode) - return ERR_PTR(-ENODEV); + return ERR_PTR(-EL3RST); msg_l3l4_hdr = buf; /* Check msg & payload consistency */ @@ -721,6 +734,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 +770,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", @@ -1379,16 +1397,16 @@ error: * * @i2400m: device descriptor * - * Gracefully stops the device, moving it to the lowest power - * consumption state possible. + * Release resources acquired during the running of the device; in + * theory, should also tell the device to go to sleep, switch off the + * radio, all that, but at this point, in most cases (driver + * disconnection, reset handling) we can't even talk to the device. */ void i2400m_dev_shutdown(struct i2400m *i2400m) { - int result = -ENODEV; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); - d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result); + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); return; } |