|
@@ -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);
|
|
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) {
|
|
if (i2400m->state != i2400m_state) {
|
|
i2400m->state = i2400m_state;
|
|
i2400m->state = i2400m_state;
|
|
wake_up_all(&i2400m->state_wq);
|
|
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);
|
|
i2400m->bus_reset(i2400m, I2400M_RT_WARM);
|
|
break;
|
|
break;
|
|
};
|
|
};
|
|
-out:
|
|
|
|
d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n",
|
|
d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n",
|
|
i2400m, ss, i2400m_state);
|
|
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);
|
|
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) {
|
|
switch (status) {
|
|
case I2400M_MEDIA_STATUS_LINK_UP:
|
|
case I2400M_MEDIA_STATUS_LINK_UP:
|
|
netif_carrier_on(net_dev);
|
|
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",
|
|
dev_err(dev, "HW BUG? unknown media status %u\n",
|
|
status);
|
|
status);
|
|
};
|
|
};
|
|
-out:
|
|
|
|
d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n",
|
|
d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n",
|
|
i2400m, ms, status);
|
|
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
|
|
* @i2400m: device descriptor
|
|
* @l3l4_hdr: pointer to message; it has been already validated for
|
|
* @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
|
|
* declaration is assumed to be congruent with @size (as in
|
|
* sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
|
|
* 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
|
|
static
|
|
void i2400m_report_state_hook(struct i2400m *i2400m,
|
|
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);
|
|
struct device *dev = i2400m_dev(i2400m);
|
|
const struct i2400m_tlv_hdr *tlv;
|
|
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);
|
|
size_t tlv_size = le16_to_cpu(l3l4_hdr->length);
|
|
|
|
|
|
d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
|
|
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;
|
|
tlv = NULL;
|
|
|
|
|
|
while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl,
|
|
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",
|
|
d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n",
|
|
i2400m, l3l4_hdr, size, tag);
|
|
i2400m, l3l4_hdr, size, tag);
|
|
}
|
|
}
|
|
@@ -721,6 +726,8 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,
|
|
ack_timeout = HZ;
|
|
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
|
|
/* 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,
|
|
* 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
|
|
* we need to change the value of i2400m->ack_skb to something
|
|
@@ -755,6 +762,9 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,
|
|
ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len);
|
|
ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len);
|
|
|
|
|
|
/* Check the ack and deliver it if it is ok */
|
|
/* 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);
|
|
result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len);
|
|
if (result < 0) {
|
|
if (result < 0) {
|
|
dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
|
|
dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
|